import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { beforeEach, describe, expect, it, vi } from 'vitest';

import { router, usePage } from '@inertiajs/react';

import type { SiteSummary } from '@/types';

import SiteSwitcher from './SiteSwitcher';

// Inertia is globally mocked in test/setup.ts. We re-mock router.visit + usePage
// here so we can assert navigation targets and control the URL surface.
vi.mock('@inertiajs/react', async (importOriginal) => {
  const actual = await importOriginal<typeof import('@inertiajs/react')>();
  return {
    ...actual,
    usePage: vi.fn(),
    router: {
      visit: vi.fn(),
    },
    Link: ({ href, children }: { href: string; children: React.ReactNode }) => (
      <a href={href}>{children}</a>
    ),
  };
});

const onboardedSite: SiteSummary = {
  id: '1',
  name: 'heatware.net',
  domain: 'heatware.net',
  has_gsc: true,
  gsc_synced: true,
  has_wp: true,
  wp_connected: true,
  has_analysis: true,
  has_reviewed_recommendation: true,
  has_ai_key: true,
  ai_available: true,
  has_ga4: false,
  onboarding_completed: true,
  current_role: 'owner',
};

const unonboardedSite: SiteSummary = {
  ...onboardedSite,
  id: '2',
  name: 'newsite.com',
  domain: 'newsite.com',
  onboarding_completed: false,
};

function setPage(url: string, features: Partial<Record<string, boolean>> = {}) {
  vi.mocked(usePage).mockReturnValue({
    url,
    props: { sites: [], features },
    component: '',
    version: '',
    scrollRegions: [],
    rememberedState: {},
  } as unknown as ReturnType<typeof usePage>);
}

/** Backward-compatible alias for tests that only care about the URL. */
function setUrl(url: string) {
  setPage(url, { portfolio: false });
}

describe('SiteSwitcher', () => {
  beforeEach(() => {
    vi.clearAllMocks();
    setUrl('/sites/1/insights');
  });

  it('renders the current site name in the trigger', () => {
    render(<SiteSwitcher sites={[onboardedSite]} currentSiteId={'1'} />);
    expect(screen.getByRole('combobox')).toHaveTextContent('heatware.net');
  });

  it('shows "Select site" when no site is current', () => {
    render(<SiteSwitcher sites={[onboardedSite]} />);
    expect(screen.getByRole('combobox')).toHaveTextContent('Select site');
  });

  it('opens the popover and lists All sites + the site row (multi-site, portfolio enabled)', async () => {
    const user = userEvent.setup();
    // R10UXB-101: the "All sites" Portfolio row requires BOTH multi-site AND features.portfolio=true.
    setPage('/sites/1/insights', { portfolio: true });
    render(
      <SiteSwitcher
        sites={[onboardedSite, { ...onboardedSite, id: '3', name: 'second.com', domain: 'second.com' }]}
        currentSiteId={'1'}
      />,
    );
    await user.click(screen.getByRole('combobox'));

    expect(screen.getByRole('option', { name: /All sites/i })).toBeInTheDocument();
    // heatware.net appears in trigger AND option — use option role to disambiguate
    expect(screen.getByRole('option', { name: /heatware\.net/i })).toBeInTheDocument();
    // "Add site" is rendered as a Link inside CommandItem — appears as a link role.
    expect(screen.getByRole('link', { name: /Add site/i })).toBeInTheDocument();
  });

  it('hides the All sites Portfolio row for a single-site user (Wave C persona gate)', async () => {
    const user = userEvent.setup();
    setPage('/sites/1/insights', { portfolio: true });
    render(<SiteSwitcher sites={[onboardedSite]} currentSiteId={'1'} />);
    await user.click(screen.getByRole('combobox'));

    expect(screen.queryByRole('option', { name: /All sites/i })).not.toBeInTheDocument();
    // The site row itself still renders.
    expect(screen.getByRole('option', { name: /heatware\.net/i })).toBeInTheDocument();
  });

  // R10UXB-101: feature-flag gate tests
  describe('R10UXB-101 — portfolio feature-flag gate', () => {
    it('hides the All sites row when features.portfolio=false even with 2+ sites', async () => {
      const user = userEvent.setup();
      setPage('/sites/1/insights', { portfolio: false });
      render(
        <SiteSwitcher
          sites={[onboardedSite, { ...onboardedSite, id: '3', name: 'second.com', domain: 'second.com' }]}
          currentSiteId={'1'}
        />,
      );
      await user.click(screen.getByRole('combobox'));

      expect(screen.queryByRole('option', { name: /All sites/i })).not.toBeInTheDocument();
    });

    it('shows the All sites row when features.portfolio=true AND 2+ sites', async () => {
      const user = userEvent.setup();
      setPage('/sites/1/insights', { portfolio: true });
      render(
        <SiteSwitcher
          sites={[onboardedSite, { ...onboardedSite, id: '3', name: 'second.com', domain: 'second.com' }]}
          currentSiteId={'1'}
        />,
      );
      await user.click(screen.getByRole('combobox'));

      expect(screen.getByRole('option', { name: /All sites/i })).toBeInTheDocument();
    });
  });

  it('maintains the current section when switching to an onboarded site', async () => {
    const user = userEvent.setup();
    setUrl('/sites/1/insights');
    render(
      <SiteSwitcher
        sites={[onboardedSite, { ...onboardedSite, id: '3', name: 'other.com', domain: 'other.com' }]}
        currentSiteId={'1'}
      />,
    );

    await user.click(screen.getByRole('combobox'));
    await user.click(screen.getByRole('option', { name: /other\.com/i }));

    expect(router.visit).toHaveBeenCalledWith('/sites/3/insights');
  });

  it('routes to onboarding when target site has not completed onboarding', async () => {
    const user = userEvent.setup();
    setUrl('/sites/1/insights');
    render(<SiteSwitcher sites={[onboardedSite, unonboardedSite]} currentSiteId={'1'} />);

    await user.click(screen.getByRole('combobox'));
    await user.click(screen.getByRole('option', { name: /newsite\.com/i }));

    expect(router.visit).toHaveBeenCalledWith('/sites/2/onboarding');
  });

  it('routes to overview when switching from a non-site URL', async () => {
    const user = userEvent.setup();
    setUrl('/portfolio');
    render(<SiteSwitcher sites={[onboardedSite]} />);

    await user.click(screen.getByRole('combobox'));
    await user.click(screen.getByRole('option', { name: /heatware\.net/i }));

    expect(router.visit).toHaveBeenCalledWith('/sites/1/analyze');
  });

  it('All sites row navigates to portfolio (multi-site, portfolio enabled)', async () => {
    const user = userEvent.setup();
    // R10UXB-101: Portfolio row requires BOTH portfolio feature AND multi-site.
    setPage('/sites/1/insights', { portfolio: true });
    render(
      <SiteSwitcher
        sites={[onboardedSite, { ...onboardedSite, id: '3', name: 'second.com', domain: 'second.com' }]}
        currentSiteId={'1'}
      />,
    );

    await user.click(screen.getByRole('combobox'));
    await user.click(screen.getByRole('option', { name: /All sites/i }));

    expect(router.visit).toHaveBeenCalledWith('/portfolio');
  });
});
