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

import RecommendationShow from './Show';

vi.mock('@inertiajs/react', async () => {
  const actual = await vi.importActual('@inertiajs/react');
  return {
    ...actual,
    Head: ({ title }: { title: string }) => <title>{title}</title>,
    Link: ({ children, href }: { children: React.ReactNode; href: string }) => (
      <a href={href}>{children}</a>
    ),
    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 },
      },
    })),
    router: { reload: vi.fn() },
  };
});

vi.mock('@/Layouts/DashboardLayout', () => ({
  default: ({ children }: { children: React.ReactNode }) => (
    <div data-testid="dashboard-layout">{children}</div>
  ),
}));

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

vi.mock('@/Components/Shared/MetricDelta', () => ({
  default: ({ value, format }: { value: number; format?: string }) => {
    const abs = Math.abs(value);
    const sign = value > 0 ? '+' : value < 0 ? '-' : '';
    const formatted = format === 'percent' ? `${Math.round(abs)}%` : `${abs}`;
    return <span data-testid="metric-delta">{`${sign}${formatted}`}</span>;
  },
}));

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

vi.mock('@/Components/Recommendations/GenerateDraftButton', () => ({
  default: () => <button>Generate Draft</button>,
}));

vi.mock('@/Components/Recommendations/StatusChangeModal', () => ({
  default: () => null,
}));

const baseSite = { id: 1, name: 'Test Site', domain: 'test.com' };

const baseRecommendation = {
  id: 10,
  page_url: 'https://test.com/blog/seo-guide',
  action_type: 'content_rewrite',
  impact_score: 85,
  confidence_score: 0.92,
  title: 'Rewrite SEO Guide',
  reasoning: 'Traffic dropped significantly after algorithm update.',
  evidence: {
    clicks_before: 200,
    clicks_after: 80,
    delta_percent: -60,
    position_before: 3.2,
    position_after: 8.5,
  },
  has_draft: false,
  latest_draft_id: null,
  lifecycle_status: 'pending',
};

const baseFinding = {
  id: 20,
  page_url: 'https://test.com/blog/seo-guide',
  delta_percent: -60,
  direction: 'down',
  metric_before: 200,
  metric_after: 80,
  segment_type: 'page',
  supporting_data: null,
};

const baseAnalysisRun = {
  id: 5,
  status: 'completed',
  before_start: '2025-12-01',
  before_end: '2025-12-14',
  after_start: '2025-12-15',
  after_end: '2025-12-28',
};

describe('Recommendations/Show', () => {
  describe('page title', () => {
    it('renders page title with site name and recommendation title', () => {
      render(
        <RecommendationShow
          site={baseSite}
          recommendation={baseRecommendation}
          finding={baseFinding}
          analysis_run={baseAnalysisRun}
          ai_available={false}
        />,
      );

      expect(document.querySelector('title')).toHaveTextContent('Test Site - Rewrite SEO Guide');
    });
  });

  describe('navigation', () => {
    it('renders SiteNav', () => {
      render(
        <RecommendationShow
          site={baseSite}
          recommendation={baseRecommendation}
          finding={baseFinding}
          analysis_run={baseAnalysisRun}
          ai_available={false}
        />,
      );

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

    it('renders back to recommendations link', () => {
      render(
        <RecommendationShow
          site={baseSite}
          recommendation={baseRecommendation}
          finding={baseFinding}
          analysis_run={baseAnalysisRun}
          ai_available={false}
        />,
      );

      const backLink = screen.getByRole('link', { name: /back to recommendations/i });
      expect(backLink).toBeInTheDocument();
    });
  });

  describe('recommendation details', () => {
    it('renders recommendation title as heading', () => {
      render(
        <RecommendationShow
          site={baseSite}
          recommendation={baseRecommendation}
          finding={baseFinding}
          analysis_run={baseAnalysisRun}
          ai_available={false}
        />,
      );

      expect(screen.getByRole('heading', { name: 'Rewrite SEO Guide' })).toBeInTheDocument();
    });

    it('renders action type badge for content_rewrite', () => {
      render(
        <RecommendationShow
          site={baseSite}
          recommendation={baseRecommendation}
          finding={baseFinding}
          analysis_run={baseAnalysisRun}
          ai_available={false}
        />,
      );

      expect(screen.getByText('AI Draft')).toBeInTheDocument();
    });

    it('renders action type badge for noindex', () => {
      const noindexRec = { ...baseRecommendation, action_type: 'noindex' };

      render(
        <RecommendationShow
          site={baseSite}
          recommendation={noindexRec}
          finding={baseFinding}
          analysis_run={baseAnalysisRun}
          ai_available={false}
        />,
      );

      expect(screen.getByText('Remove from Index')).toBeInTheDocument();
    });

    it('renders known action type label for meta_tag_optimization', () => {
      const unknownRec = { ...baseRecommendation, action_type: 'meta_tag_optimization' };

      render(
        <RecommendationShow
          site={baseSite}
          recommendation={unknownRec}
          finding={baseFinding}
          analysis_run={baseAnalysisRun}
          ai_available={false}
        />,
      );

      expect(screen.getByText('Meta Tag Optimisation')).toBeInTheDocument();
    });

    it('renders page url', () => {
      render(
        <RecommendationShow
          site={baseSite}
          recommendation={baseRecommendation}
          finding={baseFinding}
          analysis_run={baseAnalysisRun}
          ai_available={false}
        />,
      );

      expect(screen.getByText('https://test.com/blog/seo-guide')).toBeInTheDocument();
    });
  });

  describe('reasoning section', () => {
    it('renders reasoning heading', () => {
      render(
        <RecommendationShow
          site={baseSite}
          recommendation={baseRecommendation}
          finding={baseFinding}
          analysis_run={baseAnalysisRun}
          ai_available={false}
        />,
      );

      expect(screen.getByRole('heading', { name: 'Reasoning' })).toBeInTheDocument();
    });

    it('renders reasoning text', () => {
      render(
        <RecommendationShow
          site={baseSite}
          recommendation={baseRecommendation}
          finding={baseFinding}
          analysis_run={baseAnalysisRun}
          ai_available={false}
        />,
      );

      expect(
        screen.getByText('Traffic dropped significantly after algorithm update.'),
      ).toBeInTheDocument();
    });

    it('renders impact score', () => {
      render(
        <RecommendationShow
          site={baseSite}
          recommendation={baseRecommendation}
          finding={baseFinding}
          analysis_run={baseAnalysisRun}
          ai_available={false}
        />,
      );

      expect(screen.getByText('85/100')).toBeInTheDocument();
    });

    it('renders confidence score as percentage', () => {
      render(
        <RecommendationShow
          site={baseSite}
          recommendation={baseRecommendation}
          finding={baseFinding}
          analysis_run={baseAnalysisRun}
          ai_available={false}
        />,
      );

      expect(screen.getByText('92%')).toBeInTheDocument();
    });
  });

  describe('evidence section', () => {
    it('renders evidence heading', () => {
      render(
        <RecommendationShow
          site={baseSite}
          recommendation={baseRecommendation}
          finding={baseFinding}
          analysis_run={baseAnalysisRun}
          ai_available={false}
        />,
      );

      expect(screen.getByRole('heading', { name: 'Evidence' })).toBeInTheDocument();
    });

    it('renders clicks before and after labels', () => {
      render(
        <RecommendationShow
          site={baseSite}
          recommendation={baseRecommendation}
          finding={baseFinding}
          analysis_run={baseAnalysisRun}
          ai_available={false}
        />,
      );

      expect(screen.getByText('Clicks (before)')).toBeInTheDocument();
      expect(screen.getByText('Clicks (after)')).toBeInTheDocument();
    });

    it('renders change delta via MetricDelta', () => {
      render(
        <RecommendationShow
          site={baseSite}
          recommendation={baseRecommendation}
          finding={baseFinding}
          analysis_run={baseAnalysisRun}
          ai_available={false}
        />,
      );

      const deltas = screen.getAllByTestId('metric-delta');
      expect(deltas.length).toBeGreaterThanOrEqual(1);
      expect(deltas[0]).toHaveTextContent('-60%');
    });

    it('renders position before and after when available', () => {
      render(
        <RecommendationShow
          site={baseSite}
          recommendation={baseRecommendation}
          finding={baseFinding}
          analysis_run={baseAnalysisRun}
          ai_available={false}
        />,
      );

      expect(screen.getByText('3.2')).toBeInTheDocument();
      expect(screen.getByText('8.5')).toBeInTheDocument();
    });

    it('does not render position data when not available', () => {
      const recWithoutPosition = {
        ...baseRecommendation,
        evidence: {
          clicks_before: 200,
          clicks_after: 80,
          delta_percent: -60,
        },
      };

      render(
        <RecommendationShow
          site={baseSite}
          recommendation={recWithoutPosition}
          finding={baseFinding}
          analysis_run={baseAnalysisRun}
          ai_available={false}
        />,
      );

      expect(screen.queryByText('Position (before)')).not.toBeInTheDocument();
      expect(screen.queryByText('Position (after)')).not.toBeInTheDocument();
    });
  });

  describe('finding details', () => {
    it('renders finding details section when finding exists', () => {
      render(
        <RecommendationShow
          site={baseSite}
          recommendation={baseRecommendation}
          finding={baseFinding}
          analysis_run={baseAnalysisRun}
          ai_available={false}
        />,
      );

      expect(screen.getByRole('heading', { name: 'Finding Details' })).toBeInTheDocument();
    });

    it('renders finding metric before and after', () => {
      render(
        <RecommendationShow
          site={baseSite}
          recommendation={baseRecommendation}
          finding={baseFinding}
          analysis_run={baseAnalysisRun}
          ai_available={false}
        />,
      );

      expect(screen.getByText('Metric Before')).toBeInTheDocument();
      expect(screen.getByText('Metric After')).toBeInTheDocument();
    });

    it('renders finding direction', () => {
      render(
        <RecommendationShow
          site={baseSite}
          recommendation={baseRecommendation}
          finding={baseFinding}
          analysis_run={baseAnalysisRun}
          ai_available={false}
        />,
      );

      expect(screen.getByText('down')).toBeInTheDocument();
    });

    it('does not render finding details when finding is null', () => {
      render(
        <RecommendationShow
          site={baseSite}
          recommendation={baseRecommendation}
          finding={null}
          analysis_run={baseAnalysisRun}
          ai_available={false}
        />,
      );

      expect(screen.queryByRole('heading', { name: 'Finding Details' })).not.toBeInTheDocument();
    });
  });

  describe('draft link', () => {
    it('renders view draft button when draft exists', () => {
      const recWithDraft = {
        ...baseRecommendation,
        has_draft: true,
        latest_draft_id: 42,
      };

      render(
        <RecommendationShow
          site={baseSite}
          recommendation={recWithDraft}
          finding={baseFinding}
          analysis_run={baseAnalysisRun}
          ai_available={false}
        />,
      );

      const draftLink = screen.getByRole('link', { name: 'View Draft' });
      expect(draftLink).toBeInTheDocument();
    });

    it('does not render view draft button when no draft', () => {
      render(
        <RecommendationShow
          site={baseSite}
          recommendation={baseRecommendation}
          finding={baseFinding}
          analysis_run={baseAnalysisRun}
          ai_available={false}
        />,
      );

      expect(screen.queryByRole('link', { name: 'View Draft' })).not.toBeInTheDocument();
    });

    it('does not render view draft button when has_draft is true but latest_draft_id is null', () => {
      const recInvalidDraft = {
        ...baseRecommendation,
        has_draft: true,
        latest_draft_id: null,
      };

      render(
        <RecommendationShow
          site={baseSite}
          recommendation={recInvalidDraft}
          finding={baseFinding}
          analysis_run={baseAnalysisRun}
          ai_available={false}
        />,
      );

      expect(screen.queryByRole('link', { name: 'View Draft' })).not.toBeInTheDocument();
    });

    it('renders edit draft button when draft exists', () => {
      const recWithDraft = {
        ...baseRecommendation,
        has_draft: true,
        latest_draft_id: 42,
      };

      render(
        <RecommendationShow
          site={baseSite}
          recommendation={recWithDraft}
          finding={baseFinding}
          analysis_run={baseAnalysisRun}
          ai_available={false}
        />,
      );

      const editLink = screen.getByRole('link', { name: 'Edit Draft' });
      expect(editLink).toBeInTheDocument();
    });

    it('does not render edit draft button when no draft', () => {
      render(
        <RecommendationShow
          site={baseSite}
          recommendation={baseRecommendation}
          finding={baseFinding}
          analysis_run={baseAnalysisRun}
          ai_available={false}
        />,
      );

      expect(screen.queryByRole('link', { name: 'Edit Draft' })).not.toBeInTheDocument();
    });
  });

  describe('layout', () => {
    it('assigns DashboardLayout as layout', () => {
      expect(RecommendationShow.layout).toBeDefined();
    });
  });

  // ============================================
  // userEvent interaction tests
  // ============================================

  describe('interactions', () => {
    it('Generate Draft button is clickable via userEvent', async () => {
      const { default: userEvent } = await import('@testing-library/user-event');
      const user = userEvent.setup();

      render(
        <RecommendationShow
          site={baseSite}
          recommendation={baseRecommendation}
          finding={baseFinding}
          analysis_run={baseAnalysisRun}
          ai_available={true}
        />,
      );

      const btn = screen.getByRole('button', { name: /generate draft/i });
      await user.click(btn);

      expect(btn).toBeInTheDocument();
    });

    it('back to recommendations link navigates correctly via userEvent', async () => {
      const { default: userEvent } = await import('@testing-library/user-event');
      const user = userEvent.setup();

      render(
        <RecommendationShow
          site={baseSite}
          recommendation={baseRecommendation}
          finding={baseFinding}
          analysis_run={baseAnalysisRun}
          ai_available={false}
        />,
      );

      const backLink = screen.getByRole('link', { name: /back to recommendations/i });
      // Verify the link is focusable and has the correct href
      await user.tab();
      expect(backLink).toBeInTheDocument();
    });
  });
});
