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

import FreshnessIndex from './Index';

const mockPost = vi.fn();

vi.mock('@inertiajs/react', async () => {
  const actual = await vi.importActual('@inertiajs/react');
  return {
    ...actual,
    usePage: vi.fn(() => ({
      props: {
        auth: {
          user: {
            name: 'Test User',
            email: 'test@example.com',
          },
        },
        features: {
          billing: false,
          notifications: false,
        },
        sites: [],
        limits: null,
        ai_defaults: { model: 'gpt-4o-mini', temperature: 0.7 },
      },
    })),
    Head: ({ title }: { title: string }) => <title>{title}</title>,
    Link: ({ children, href }: { children: React.ReactNode; href: string }) => (
      <a href={href}>{children}</a>
    ),
    router: {
      reload: vi.fn(),
      get: vi.fn(),
    },
    useForm: vi.fn(() => ({
      data: {
        analysis_window_start: '2026-01-01',
        analysis_window_end: '2026-01-31',
      },
      setData: vi.fn(),
      post: mockPost,
      processing: false,
      errors: {},
    })),
  };
});

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

vi.mock('@/Components/Navigation/SiteNav', () => ({
  default: () => <div data-testid="site-nav" />,
}));

vi.mock('@/Components/ContentIntelligence/DecayPatternBadge', () => ({
  default: ({ pattern }: { pattern: string }) => (
    <div data-testid="decay-pattern-badge">{pattern}</div>
  ),
}));

vi.mock('@/Components/ContentIntelligence/FreshnessScoreCard', () => ({
  default: ({ score }: { score: number }) => <div data-testid="freshness-score-card">{score}</div>,
}));

vi.mock('@/Components/ui/empty-state', () => ({
  EmptyState: ({ title, description }: { title: string; description?: string }) => (
    <div data-testid="empty-state">
      {title}: {description}
    </div>
  ),
}));

vi.mock('@/lib/format', () => ({
  formatNumber: (n: number) => String(n),
  formatPercent: (value: number) => `${(value * 100).toFixed(1)}%`,
  formatDateOnly: (dateString: string | null, fallback = 'N/A') =>
    dateString ? new Date(dateString).toLocaleDateString('en-US') : fallback,
}));

vi.mock('@/Components/ui/pagination', () => ({
  Pagination: ({ children }: { children: React.ReactNode }) => (
    <div data-testid="pagination">{children}</div>
  ),
  PaginationContent: ({ children }: { children: React.ReactNode }) => <div>{children}</div>,
  PaginationItem: ({ children }: { children: React.ReactNode }) => <div>{children}</div>,
  PaginationLink: ({
    children,
    href,
    isActive,
  }: {
    children: React.ReactNode;
    href: string;
    isActive?: boolean;
  }) => (
    <a href={href} data-active={isActive}>
      {children}
    </a>
  ),
  PaginationPrevious: ({ href }: { href: string }) => <a href={href}>Previous</a>,
  PaginationNext: ({ href }: { href: string }) => <a href={href}>Next</a>,
  PaginationEllipsis: () => <span>...</span>,
}));

const defaultProps = {
  site: { id: 1, name: 'Test Site', domain: 'https://test.com' },
  latestRun: null,
  recommendations: {
    data: [],
    current_page: 1,
    last_page: 1,
    per_page: 15,
    total: 0,
    from: null,
    to: null,
  },
  filters: {},
  counts: {
    total: 0,
    light_refresh: 0,
    section_refresh: 0,
    full_rewrite: 0,
    reposition_intent: 0,
  },
};

const completedRun = {
  id: 1,
  status: 'completed' as const,
  analysis_window_start: '2026-01-01',
  analysis_window_end: '2026-01-31',
  summary: {
    total_analyzed: 100,
    recommendations_generated: 15,
  },
  completed_at: '2026-02-01T10:00:00Z',
};

const mockRecommendations = [
  {
    id: 1,
    page_url: 'https://test.com/page-1',
    title: 'Test Page 1',
    action_type: 'light_refresh' as const,
    impact_score: 85,
    confidence_score: 0.9,
    effort_score: 20,
    urgency_score: 70,
    freshness_score: 45.5,
    reasoning: 'Page has gradual decay pattern',
    evidence: {},
    status: 'pending',
    created_at: '2026-02-01T10:00:00Z',
    page_decay_signal: {
      decay_pattern_type: 'gradual_decay' as const,
      baseline_7d_clicks: 100,
      baseline_28d_clicks: 400,
      baseline_90d_clicks: 1200,
      current_clicks: 50,
      decay_magnitude: 50,
      confidence_score: 0.9,
      freshness_score: 45.5,
      supporting_data: {},
      created_at: '2026-02-01T10:00:00Z',
    },
  },
  {
    id: 2,
    page_url: 'https://test.com/page-2',
    title: 'Test Page 2',
    action_type: 'full_rewrite' as const,
    impact_score: 95,
    confidence_score: 0.85,
    effort_score: 80,
    urgency_score: 90,
    freshness_score: 25.3,
    reasoning: 'Page has step drop pattern',
    evidence: {},
    status: 'pending',
    created_at: '2026-02-01T10:00:00Z',
    page_decay_signal: {
      decay_pattern_type: 'step_drop' as const,
      baseline_7d_clicks: 200,
      baseline_28d_clicks: 800,
      baseline_90d_clicks: 2400,
      current_clicks: 30,
      decay_magnitude: 85,
      confidence_score: 0.85,
      freshness_score: 25.3,
      supporting_data: {},
      created_at: '2026-02-01T10:00:00Z',
    },
  },
];

describe('ContentIntelligence/Freshness/Index', () => {
  beforeEach(() => {
    vi.clearAllMocks();
    mockPost.mockClear();
  });

  it('renders page title with site name', () => {
    render(<FreshnessIndex {...defaultProps} />);

    expect(document.querySelector('title')).toHaveTextContent('Test Site - Freshness Watchlist');
  });

  it('renders heading "Freshness Watchlist"', () => {
    render(<FreshnessIndex {...defaultProps} />);

    expect(screen.getByText('Freshness Watchlist')).toBeInTheDocument();
  });

  it('renders description text', () => {
    render(<FreshnessIndex {...defaultProps} />);

    expect(screen.getByText('Track pages losing performance due to staleness')).toBeInTheDocument();
  });

  it('always renders SiteNav', () => {
    render(<FreshnessIndex {...defaultProps} />);

    expect(screen.getByTestId('site-nav')).toBeInTheDocument();
  });

  it('shows empty state when no latestRun', () => {
    render(<FreshnessIndex {...defaultProps} />);

    expect(screen.getByTestId('empty-state')).toBeInTheDocument();
    expect(screen.getByTestId('empty-state')).toHaveTextContent(
      'Run your first freshness analysis',
    );
  });

  it('renders analysis form', () => {
    render(<FreshnessIndex {...defaultProps} />);

    expect(screen.getByText('Run Freshness Analysis')).toBeInTheDocument();
    expect(screen.getByLabelText('Analysis Window Start')).toBeInTheDocument();
    expect(screen.getByLabelText('Analysis Window End')).toBeInTheDocument();
    expect(screen.getByRole('button', { name: /Run Analysis/i })).toBeInTheDocument();
  });

  // ============================================
  // Run status tests
  // ============================================

  it('shows processing status when run is processing', () => {
    const processingRun = {
      ...completedRun,
      status: 'processing' as const,
      summary: null,
      completed_at: null,
    };

    render(<FreshnessIndex {...defaultProps} latestRun={processingRun} />);

    expect(screen.getByText('Analysis in Progress')).toBeInTheDocument();
    expect(screen.getByText(/Analyzing pages from/)).toBeInTheDocument();
  });

  it('shows pending status when run is pending', () => {
    const pendingRun = {
      ...completedRun,
      status: 'pending' as const,
      summary: null,
      completed_at: null,
    };

    render(<FreshnessIndex {...defaultProps} latestRun={pendingRun} />);

    expect(screen.getByText('Analysis in Progress')).toBeInTheDocument();
  });

  it('shows failed status when run is failed', () => {
    const failedRun = {
      ...completedRun,
      status: 'failed' as const,
      summary: null,
      completed_at: null,
    };

    render(<FreshnessIndex {...defaultProps} latestRun={failedRun} />);

    expect(screen.getByText('Analysis Failed')).toBeInTheDocument();
    expect(screen.getByText(/The freshness analysis could not be completed/)).toBeInTheDocument();
  });

  it('shows summary when run is completed', () => {
    render(
      <FreshnessIndex
        {...defaultProps}
        latestRun={completedRun}
        counts={{
          total: 15,
          light_refresh: 5,
          section_refresh: 4,
          full_rewrite: 3,
          reposition_intent: 3,
        }}
      />,
    );

    expect(screen.getByText('Latest Analysis Summary')).toBeInTheDocument();
    expect(screen.getByText('15')).toBeInTheDocument(); // Total
    expect(screen.getByText('5')).toBeInTheDocument(); // Light refresh
    expect(screen.getByText('4')).toBeInTheDocument(); // Section refresh
    const threes = screen.getAllByText('3');
    expect(threes.length).toBeGreaterThanOrEqual(2); // Full rewrite and reposition intent
  });

  // ============================================
  // Skeleton/loading state tests
  // ============================================

  it('shows skeleton placeholders when run is processing', () => {
    const processingRun = {
      ...completedRun,
      status: 'processing' as const,
      summary: null,
      completed_at: null,
    };

    render(<FreshnessIndex {...defaultProps} latestRun={processingRun} />);

    // Should show skeleton elements with role="status" and aria-label="Loading"
    const loadingSkeletons = screen.getAllByRole('status', { name: /loading/i });
    expect(loadingSkeletons.length).toBeGreaterThan(0);
  });

  // ============================================
  // Recommendations table tests
  // ============================================

  it('shows empty state when completed with no recommendations', () => {
    render(<FreshnessIndex {...defaultProps} latestRun={completedRun} />);

    expect(screen.getByTestId('empty-state')).toBeInTheDocument();
    expect(screen.getByTestId('empty-state')).toHaveTextContent('No recommendations found');
  });

  it('shows recommendations table when completed with data', () => {
    render(
      <FreshnessIndex
        {...defaultProps}
        latestRun={completedRun}
        recommendations={{
          data: mockRecommendations,
          current_page: 1,
          last_page: 1,
          per_page: 15,
          total: 2,
          from: 1,
          to: 2,
        }}
        counts={{
          total: 2,
          light_refresh: 1,
          section_refresh: 0,
          full_rewrite: 1,
          reposition_intent: 0,
        }}
      />,
    );

    expect(screen.getByText('Test Page 1')).toBeInTheDocument();
    expect(screen.getByText('Test Page 2')).toBeInTheDocument();
    expect(screen.getByText('https://test.com/page-1')).toBeInTheDocument();
    expect(screen.getByText('https://test.com/page-2')).toBeInTheDocument();
  });

  it('renders decay pattern badges in table', () => {
    render(
      <FreshnessIndex
        {...defaultProps}
        latestRun={completedRun}
        recommendations={{
          data: mockRecommendations,
          current_page: 1,
          last_page: 1,
          per_page: 15,
          total: 2,
          from: 1,
          to: 2,
        }}
        counts={{
          total: 2,
          light_refresh: 1,
          section_refresh: 0,
          full_rewrite: 1,
          reposition_intent: 0,
        }}
      />,
    );

    const badges = screen.getAllByTestId('decay-pattern-badge');
    expect(badges).toHaveLength(2);
    expect(badges[0]).toHaveTextContent('gradual_decay');
    expect(badges[1]).toHaveTextContent('step_drop');
  });

  it('renders freshness score cards in table', () => {
    render(
      <FreshnessIndex
        {...defaultProps}
        latestRun={completedRun}
        recommendations={{
          data: mockRecommendations,
          current_page: 1,
          last_page: 1,
          per_page: 15,
          total: 2,
          from: 1,
          to: 2,
        }}
        counts={{
          total: 2,
          light_refresh: 1,
          section_refresh: 0,
          full_rewrite: 1,
          reposition_intent: 0,
        }}
      />,
    );

    const scoreCards = screen.getAllByTestId('freshness-score-card');
    expect(scoreCards).toHaveLength(2);
    expect(scoreCards[0]).toHaveTextContent('45.5');
    expect(scoreCards[1]).toHaveTextContent('25.3');
  });

  it('renders action type badges in table', () => {
    render(
      <FreshnessIndex
        {...defaultProps}
        latestRun={completedRun}
        recommendations={{
          data: mockRecommendations,
          current_page: 1,
          last_page: 1,
          per_page: 15,
          total: 2,
          from: 1,
          to: 2,
        }}
        counts={{
          total: 2,
          light_refresh: 1,
          section_refresh: 0,
          full_rewrite: 1,
          reposition_intent: 0,
        }}
      />,
    );

    const lightRefresh = screen.getAllByText('Light Refresh');
    expect(lightRefresh.length).toBeGreaterThan(0);
    const fullRewrite = screen.getAllByText('Full Rewrite');
    expect(fullRewrite.length).toBeGreaterThan(0);
  });

  it('renders confidence scores in table', () => {
    render(
      <FreshnessIndex
        {...defaultProps}
        latestRun={completedRun}
        recommendations={{
          data: mockRecommendations,
          current_page: 1,
          last_page: 1,
          per_page: 15,
          total: 2,
          from: 1,
          to: 2,
        }}
        counts={{
          total: 2,
          light_refresh: 1,
          section_refresh: 0,
          full_rewrite: 1,
          reposition_intent: 0,
        }}
      />,
    );

    expect(screen.getByText('90%')).toBeInTheDocument(); // 0.9 * 100
    expect(screen.getByText('85%')).toBeInTheDocument(); // 0.85 * 100
  });

  it('renders View links for each recommendation', () => {
    render(
      <FreshnessIndex
        {...defaultProps}
        latestRun={completedRun}
        recommendations={{
          data: mockRecommendations,
          current_page: 1,
          last_page: 1,
          per_page: 15,
          total: 2,
          from: 1,
          to: 2,
        }}
        counts={{
          total: 2,
          light_refresh: 1,
          section_refresh: 0,
          full_rewrite: 1,
          reposition_intent: 0,
        }}
      />,
    );

    const viewLinks = screen.getAllByText('View');
    expect(viewLinks).toHaveLength(2);
  });

  // ============================================
  // Filters tests
  // ============================================

  it('shows filters when completed with recommendations', () => {
    render(
      <FreshnessIndex
        {...defaultProps}
        latestRun={completedRun}
        recommendations={{
          data: mockRecommendations,
          current_page: 1,
          last_page: 1,
          per_page: 15,
          total: 2,
          from: 1,
          to: 2,
        }}
        counts={{
          total: 2,
          light_refresh: 1,
          section_refresh: 0,
          full_rewrite: 1,
          reposition_intent: 0,
        }}
      />,
    );

    expect(screen.getByText('Filters')).toBeInTheDocument();
    expect(screen.getByLabelText('Action Type')).toBeInTheDocument();
    expect(screen.getByLabelText('Decay Pattern')).toBeInTheDocument();
    expect(screen.getByLabelText('Min Confidence')).toBeInTheDocument();
    expect(screen.getByLabelText('Sort By')).toBeInTheDocument();
  });

  it('does not show filters when no recommendations', () => {
    render(<FreshnessIndex {...defaultProps} latestRun={completedRun} />);

    expect(screen.queryByText('Filters')).not.toBeInTheDocument();
  });

  it('shows Clear Filters button when filters are active', () => {
    render(
      <FreshnessIndex
        {...defaultProps}
        latestRun={completedRun}
        recommendations={{
          data: mockRecommendations,
          current_page: 1,
          last_page: 1,
          per_page: 15,
          total: 2,
          from: 1,
          to: 2,
        }}
        filters={{
          action_type: 'light_refresh',
        }}
        counts={{
          total: 2,
          light_refresh: 1,
          section_refresh: 0,
          full_rewrite: 1,
          reposition_intent: 0,
        }}
      />,
    );

    expect(screen.getByRole('button', { name: /Clear Filters/i })).toBeInTheDocument();
  });

  it('does not show Clear Filters button when no filters are active', () => {
    render(
      <FreshnessIndex
        {...defaultProps}
        latestRun={completedRun}
        recommendations={{
          data: mockRecommendations,
          current_page: 1,
          last_page: 1,
          per_page: 15,
          total: 2,
          from: 1,
          to: 2,
        }}
        filters={{}}
        counts={{
          total: 2,
          light_refresh: 1,
          section_refresh: 0,
          full_rewrite: 1,
          reposition_intent: 0,
        }}
      />,
    );

    expect(screen.queryByRole('button', { name: /Clear Filters/i })).not.toBeInTheDocument();
  });

  // ============================================
  // Pagination tests
  // ============================================

  it('shows pagination when multiple pages exist', () => {
    render(
      <FreshnessIndex
        {...defaultProps}
        latestRun={completedRun}
        recommendations={{
          data: mockRecommendations,
          current_page: 2,
          last_page: 5,
          per_page: 15,
          total: 75,
          from: 16,
          to: 30,
        }}
        counts={{
          total: 75,
          light_refresh: 25,
          section_refresh: 20,
          full_rewrite: 15,
          reposition_intent: 15,
        }}
      />,
    );

    expect(screen.getByText('1')).toBeInTheDocument();
    expect(screen.getByText('2')).toBeInTheDocument();
    expect(screen.getByText('5')).toBeInTheDocument();
  });

  it('does not show pagination when only one page', () => {
    render(
      <FreshnessIndex
        {...defaultProps}
        latestRun={completedRun}
        recommendations={{
          data: mockRecommendations,
          current_page: 1,
          last_page: 1,
          per_page: 15,
          total: 2,
          from: 1,
          to: 2,
        }}
        counts={{
          total: 2,
          light_refresh: 1,
          section_refresh: 0,
          full_rewrite: 1,
          reposition_intent: 0,
        }}
      />,
    );

    // Pagination component should not be rendered at all
    expect(screen.queryByText('Previous')).not.toBeInTheDocument();
    expect(screen.queryByText('Next')).not.toBeInTheDocument();
  });

  // ============================================
  // Form interaction tests
  // ============================================

  it('calls post when Run Analysis button is clicked', async () => {
    const user = userEvent.setup();

    render(<FreshnessIndex {...defaultProps} />);

    const runButton = screen.getByRole('button', { name: /Run Analysis/i });
    await user.click(runButton);

    expect(mockPost).toHaveBeenCalledTimes(1);
  });
});
