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

vi.mock('@inertiajs/react', async () => {
  const actual = await vi.importActual('@inertiajs/react');
  return {
    ...actual,
    Head: ({ title }: { title: string }) => <title>{title}</title>,
    usePage: vi.fn(() => ({
      url: '/admin/sites',
      props: {
        auth: { user: { id: 1, name: 'Admin', email: 'admin@test.com', is_admin: true } },
        features: {
          billing: false,
          socialAuth: false,
          emailVerification: true,
          apiTokens: true,
          userSettings: true,
          notifications: false,
          onboarding: false,
          apiDocs: false,
          twoFactor: false,
          webhooks: false,
          admin: true,
        },
      },
    })),
    Link: ({
      children,
      href,
      ...rest
    }: {
      children: React.ReactNode;
      href: string;
      className?: string;
    }) => (
      <a href={href} {...rest}>
        {children}
      </a>
    ),
    router: {
      patch: vi.fn(),
      delete: vi.fn(),
      post: vi.fn(),
      get: vi.fn(),
      on: vi.fn(() => vi.fn()),
    },
  };
});

vi.mock('@/Components/theme/use-theme', () => ({
  useTheme: vi.fn(() => ({ theme: 'system', setTheme: vi.fn(), resolvedTheme: 'light' })),
}));

vi.mock('sonner', () => ({
  toast: { success: vi.fn(), error: vi.fn() },
}));

import AdminSitesIndex from './Index';

const makePagination = <T,>(data: T[]) => ({
  data,
  current_page: 1,
  per_page: 25,
  total: data.length,
  last_page: 1,
  from: data.length > 0 ? 1 : 0,
  to: data.length,
  links: [],
});

const defaultStats = {
  total_sites: 1,
  avg_health_score: 72.5,
  both_connections_pct: 50.0,
  critical_count: 0,
};

const makeSite = (overrides = {}) => ({
  id: 1,
  name: 'Test Site',
  domain: 'example.com',
  user_id: 2,
  user_name: 'Alice Example',
  user_email: 'alice@example.com',
  health_score: '72.50',
  health_status: 'Needs Attention',
  last_analysis_at: '2026-01-15T10:00:00Z',
  has_gsc: true,
  has_wp: false,
  created_at: '2026-01-01T00:00:00Z',
  deleted_at: null,
  ...overrides,
});

describe('AdminSitesIndex', () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  it('renders the Sites heading', () => {
    render(
      <AdminSitesIndex
        sites={makePagination([makeSite()])}
        filters={{}}
        stats={defaultStats}
      />,
    );
    expect(screen.getByRole('heading', { name: 'Sites', level: 1 })).toBeInTheDocument();
  });

  it('renders site name and domain', () => {
    render(
      <AdminSitesIndex
        sites={makePagination([makeSite()])}
        filters={{}}
        stats={defaultStats}
      />,
    );
    expect(screen.getByText('Test Site')).toBeInTheDocument();
    expect(screen.getByText('example.com')).toBeInTheDocument();
  });

  it('renders site owner name', () => {
    render(
      <AdminSitesIndex
        sites={makePagination([makeSite()])}
        filters={{}}
        stats={defaultStats}
      />,
    );
    expect(screen.getByText('Alice Example')).toBeInTheDocument();
  });

  it('shows a good health badge for high score', () => {
    render(
      <AdminSitesIndex
        sites={makePagination([makeSite({ health_score: '85.00', health_status: 'Good' })])}
        filters={{}}
        stats={{ ...defaultStats, avg_health_score: 85 }}
      />,
    );
    expect(screen.getByText('85 - Good')).toBeInTheDocument();
  });

  it('shows a warning health badge for mid score', () => {
    render(
      <AdminSitesIndex
        sites={makePagination([makeSite({ health_score: '45.00', health_status: 'Warning' })])}
        filters={{}}
        stats={defaultStats}
      />,
    );
    expect(screen.getByText('45 - Warning')).toBeInTheDocument();
  });

  it('shows a critical health badge for low score', () => {
    render(
      <AdminSitesIndex
        sites={makePagination([makeSite({ health_score: '20.00', health_status: 'Critical' })])}
        filters={{}}
        stats={{ ...defaultStats, critical_count: 1 }}
      />,
    );
    expect(screen.getByText('20 - Critical')).toBeInTheDocument();
  });

  it('shows Unknown badge for null health score', () => {
    render(
      <AdminSitesIndex
        sites={makePagination([makeSite({ health_score: null, health_status: 'Unknown' })])}
        filters={{}}
        stats={defaultStats}
      />,
    );
    expect(screen.getByText('Unknown')).toBeInTheDocument();
  });

  it('shows Deleted badge for soft-deleted sites', () => {
    render(
      <AdminSitesIndex
        sites={makePagination([makeSite({ deleted_at: '2026-02-01T00:00:00Z' })])}
        filters={{}}
        stats={defaultStats}
      />,
    );
    expect(screen.getByText('Deleted')).toBeInTheDocument();
  });

  it('shows empty state when no sites exist', () => {
    render(
      <AdminSitesIndex
        sites={makePagination([])}
        filters={{}}
        stats={{ total_sites: 0, avg_health_score: 0, both_connections_pct: 0, critical_count: 0 }}
      />,
    );
    expect(screen.getByText('No sites in the system yet')).toBeInTheDocument();
  });

  it('shows stat cards with correct values', () => {
    render(
      <AdminSitesIndex
        sites={makePagination([makeSite()])}
        filters={{}}
        stats={{ total_sites: 42, avg_health_score: 68.3, both_connections_pct: 33.3, critical_count: 5 }}
      />,
    );
    expect(screen.getByText('42')).toBeInTheDocument();
    expect(screen.getByText('5')).toBeInTheDocument();
  });

  it('renders search input', () => {
    render(
      <AdminSitesIndex sites={makePagination([])} filters={{}} stats={defaultStats} />,
    );
    expect(screen.getByRole('textbox', { name: /Search sites/ })).toBeInTheDocument();
  });

  it('renders Export CSV link', () => {
    render(
      <AdminSitesIndex sites={makePagination([])} filters={{}} stats={defaultStats} />,
    );
    expect(screen.getByRole('link', { name: /Export CSV/ })).toBeInTheDocument();
  });

  it('shows selection toolbar with site count when a row is selected', () => {
    render(
      <AdminSitesIndex
        sites={makePagination([makeSite()])}
        filters={{}}
        stats={defaultStats}
      />,
    );
    const checkbox = screen.getByRole('checkbox', { name: /Select Test Site/ });
    fireEvent.click(checkbox);
    expect(screen.getByText('1 site selected')).toBeInTheDocument();
  });

  it('shows "Deactivate" button in toolbar when sites are selected', () => {
    render(
      <AdminSitesIndex
        sites={makePagination([makeSite()])}
        filters={{}}
        stats={defaultStats}
      />,
    );
    fireEvent.click(screen.getByRole('checkbox', { name: /Select Test Site/ }));
    // Button text is "Deactivate (N)" — match by prefix
    expect(screen.getByRole('button', { name: /Deactivate \(/ })).toBeInTheDocument();
  });

  it('clears selection when Clear button is clicked', () => {
    render(
      <AdminSitesIndex
        sites={makePagination([makeSite()])}
        filters={{}}
        stats={defaultStats}
      />,
    );
    fireEvent.click(screen.getByRole('checkbox', { name: /Select Test Site/ }));
    expect(screen.getByText('1 site selected')).toBeInTheDocument();
    fireEvent.click(screen.getByRole('button', { name: /Clear selection/ }));
    expect(screen.queryByText('1 site selected')).not.toBeInTheDocument();
  });

  it('opens bulk deactivate confirm dialog when Deactivate button is clicked', () => {
    render(
      <AdminSitesIndex
        sites={makePagination([makeSite()])}
        filters={{}}
        stats={defaultStats}
      />,
    );
    fireEvent.click(screen.getByRole('checkbox', { name: /Select Test Site/ }));
    fireEvent.click(screen.getByRole('button', { name: /Deactivate \(/ }));
    expect(screen.getByText(/Deactivate 1 site\(s\)/i)).toBeInTheDocument();
  });

  it('shows correct site count in bulk deactivate confirmation', () => {
    const sites = [
      makeSite({ id: 1, name: 'Site One' }),
      makeSite({ id: 2, name: 'Site Two' }),
    ];
    render(
      <AdminSitesIndex
        sites={makePagination(sites)}
        filters={{}}
        stats={{ ...defaultStats, total_sites: 2 }}
      />,
    );
    fireEvent.click(screen.getByRole('checkbox', { name: /Select Site One/ }));
    fireEvent.click(screen.getByRole('checkbox', { name: /Select Site Two/ }));
    expect(screen.getByText('2 sites selected')).toBeInTheDocument();
    fireEvent.click(screen.getByRole('button', { name: /Deactivate \(/ }));
    expect(screen.getByText(/Deactivating 2 site\(s\) will remove them from those users' dashboards immediately/i)).toBeInTheDocument();
  });

  it('disabled checkbox for soft-deleted sites', () => {
    render(
      <AdminSitesIndex
        sites={makePagination([makeSite({ deleted_at: '2026-02-01T00:00:00Z' })])}
        filters={{}}
        stats={defaultStats}
      />,
    );
    // Deleted site has a disabled checkbox (cannot be selected for bulk actions)
    const disabledCheckbox = screen.getByRole('checkbox', {
      name: /Cannot select Test Site/,
    });
    expect(disabledCheckbox).toBeDisabled();
  });

  it('shows filter empty state with message when hasFilters is true', () => {
    render(
      <AdminSitesIndex
        sites={makePagination([])}
        filters={{ search: 'nonexistent' }}
        stats={{ total_sites: 0, avg_health_score: 0, both_connections_pct: 0, critical_count: 0 }}
      />,
    );
    expect(
      screen.getByText(/No sites match your filters/),
    ).toBeInTheDocument();
  });

  it('renders GSC connected icon for site with GSC', () => {
    render(
      <AdminSitesIndex
        sites={makePagination([makeSite({ has_gsc: true })])}
        filters={{}}
        stats={defaultStats}
      />,
    );
    // CheckCircle icon rendered with aria-label="Connected"
    expect(screen.getAllByLabelText('Connected').length).toBeGreaterThanOrEqual(1);
  });

  it('renders WP not-connected icon for site without WP', () => {
    render(
      <AdminSitesIndex
        sites={makePagination([makeSite({ has_wp: false })])}
        filters={{}}
        stats={defaultStats}
      />,
    );
    expect(screen.getAllByLabelText('Not connected').length).toBeGreaterThanOrEqual(1);
  });
});
