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

import View from './View';

const { mockTrackProductEvent, mockTrackEvent, mockHasAnalyticsConsent } = vi.hoisted(() => ({
  mockTrackProductEvent: vi.fn(),
  mockTrackEvent: vi.fn(),
  mockHasAnalyticsConsent: vi.fn().mockReturnValue(true),
}));

vi.mock('@/lib/analytics', () => ({
  trackEvent: mockTrackEvent,
  trackProductEvent: mockTrackProductEvent,
  hasAnalyticsConsent: mockHasAnalyticsConsent,
}));

vi.mock('@inertiajs/react', async () => {
  const actual = await vi.importActual('@inertiajs/react');
  return {
    ...actual,
    Head: ({ title }: { title: string }) => <title>{title}</title>,
    Link: ({
      children,
      href,
      onClick,
      className,
    }: {
      children: React.ReactNode;
      href: string;
      onClick?: () => void;
      className?: string;
    }) => (
      <a href={href} onClick={onClick} className={className}>
        {children}
      </a>
    ),
    usePage: vi.fn(() => ({
      props: {
        auth: { user: null },
        features: {},
        sites: [],
        limits: null,
        ai_defaults: { model: 'gpt-4o-mini', temperature: 0.7 },
        polling_interval_ms: 5000,
      },
    })),
  };
});

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

vi.mock('recharts', () => ({
  ResponsiveContainer: ({ children }: { children: React.ReactNode }) => <div>{children}</div>,
  LineChart: () => <div data-testid="line-chart" />,
  Line: () => null,
  XAxis: () => null,
  YAxis: () => null,
  CartesianGrid: () => null,
  Tooltip: () => null,
  Legend: () => null,
}));

const baseProps = {
  report: {
    id: 1,
    name: 'Test Report',
    sections: ['traffic_overview'],
    filters: {},
    status: 'completed',
    generated_at: '2026-01-15 10:00:00',
    data: {
      site: { id: 1, name: 'Test Site', domain: 'example.com' },
      generated_at: '2026-01-15 10:00:00',
      filters: {},
      branding: null,
    },
  },
  site: { name: 'Test Site', domain: 'example.com' },
  shared_link: { view_count: 5 },
};

describe('SharedReport/View', () => {
  beforeEach(() => {
    // Restore the default consent mock before each test so that
    // mockReturnValueOnce() calls in one test don't bleed into subsequent tests.
    mockHasAnalyticsConsent.mockReturnValue(true);
    mockTrackProductEvent.mockClear();
    mockTrackEvent.mockClear();
  });

  it('renders RankWiz branding and Try button when no branding data', () => {
    render(<View {...baseProps} />);

    expect(screen.getByText('Try RankWiz Free')).toBeInTheDocument();
    // RankWiz AI appears in both the page footer and the embedded ReportPreview footer
    const rankwizElements = screen.getAllByText('RankWiz AI');
    expect(rankwizElements.length).toBeGreaterThanOrEqual(1);
  });

  it('hides Try button and RankWiz branding when white-labeled', () => {
    const props = {
      ...baseProps,
      report: {
        ...baseProps.report,
        data: {
          ...baseProps.report.data,
          branding: {
            company_name: 'Acme Agency',
            logo_url: null,
            primary_color: '#ff6b35',
            secondary_color: '#004e89',
            remove_rankwiz_branding: true,
          },
        },
      },
    };

    render(<View {...props} />);

    expect(screen.queryByText('Try RankWiz Free')).not.toBeInTheDocument();
    expect(screen.queryByText('RankWiz AI')).not.toBeInTheDocument();
  });

  it('renders branded company name in header when white-labeled without logo', () => {
    const props = {
      ...baseProps,
      report: {
        ...baseProps.report,
        data: {
          ...baseProps.report.data,
          branding: {
            company_name: 'Acme Agency',
            logo_url: null,
            primary_color: '#ff6b35',
            secondary_color: '#004e89',
            remove_rankwiz_branding: true,
          },
        },
      },
    };

    render(<View {...props} />);

    // Company name appears in page header, ReportPreview header, and footers
    const acmeElements = screen.getAllByText('Acme Agency');
    expect(acmeElements.length).toBeGreaterThanOrEqual(2);
  });

  it('renders branded logo in header when logo_url provided', () => {
    const props = {
      ...baseProps,
      report: {
        ...baseProps.report,
        data: {
          ...baseProps.report.data,
          branding: {
            company_name: 'Acme Agency',
            logo_url: 'https://example.com/logo.png',
            primary_color: '#ff6b35',
            secondary_color: '#004e89',
            remove_rankwiz_branding: true,
          },
        },
      },
    };

    render(<View {...props} />);

    // Logo appears in both the View header and the embedded ReportPreview header
    const logos = screen.getAllByAltText('Acme Agency');
    expect(logos.length).toBeGreaterThanOrEqual(1);
    expect(logos[0]).toHaveAttribute('src', 'https://example.com/logo.png');
  });

  it('renders branded footer when white-labeled', () => {
    const props = {
      ...baseProps,
      report: {
        ...baseProps.report,
        data: {
          ...baseProps.report.data,
          branding: {
            company_name: 'Acme Agency',
            logo_url: null,
            primary_color: '#ff6b35',
            secondary_color: '#004e89',
            remove_rankwiz_branding: true,
          },
        },
      },
    };

    render(<View {...props} />);

    expect(screen.getByText(/Powered by/)).toBeInTheDocument();
    expect(screen.queryByText('RankWiz AI')).not.toBeInTheDocument();
  });

  it('shows view count badge', () => {
    render(<View {...baseProps} />);

    expect(screen.getByText('5 views')).toBeInTheDocument();
  });

  it('fires SHARED_REPORT_VIEWED via trackProductEvent on mount', () => {
    mockTrackProductEvent.mockClear();
    render(<View {...baseProps} />);

    expect(mockTrackProductEvent).toHaveBeenCalledWith(
      'shared_report_viewed',
      expect.objectContaining({ report_id: '1', is_authenticated: false }),
    );
  });

  it('fires CTA_CLICKED via trackProductEvent (not trackEvent) when banner CTA is clicked', async () => {
    const user = userEvent.setup();
    mockTrackProductEvent.mockClear();
    mockTrackEvent.mockClear();
    render(<View {...baseProps} />);

    await user.click(screen.getByText('Try RankWiz Free'));

    expect(mockTrackProductEvent).toHaveBeenCalledWith(
      'cta_clicked',
      expect.objectContaining({ cta_text: 'Try RankWiz Free', cta_location: 'shared_report_banner' }),
    );
    // trackEvent must not be called directly — all tracking routes through trackProductEvent
    expect(mockTrackEvent).not.toHaveBeenCalled();
  });

  it('fires CTA_CLICKED via trackProductEvent (not trackEvent) when footer link is clicked', async () => {
    const user = userEvent.setup();
    mockTrackProductEvent.mockClear();
    mockTrackEvent.mockClear();
    render(<View {...baseProps} />);

    // The page footer has implicit ARIA role "contentinfo" — target it specifically
    // so we click the tracked link, not the untracked one inside ReportPreview.
    const footer = screen.getByRole('contentinfo');
    await user.click(within(footer).getByText('RankWiz AI'));

    expect(mockTrackProductEvent).toHaveBeenCalledWith(
      'cta_clicked',
      expect.objectContaining({ cta_text: 'RankWiz AI', cta_location: 'shared_report_footer' }),
    );
    expect(mockTrackEvent).not.toHaveBeenCalled();
  });

  it('does not fire SHARED_REPORT_VIEWED when analytics consent is not granted', () => {
    mockHasAnalyticsConsent.mockReturnValueOnce(false);
    mockTrackProductEvent.mockClear();

    render(<View {...baseProps} />);

    expect(mockTrackProductEvent).not.toHaveBeenCalled();
  });

  it('does not call window.gtag or window.posthog directly for the view event', () => {
    const gtagSpy = vi.fn();
    const captureSpy = vi.fn();
    Object.defineProperty(window, 'gtag', { value: gtagSpy, writable: true, configurable: true });
    Object.defineProperty(window, 'posthog', {
      value: { capture: captureSpy },
      writable: true,
      configurable: true,
    });

    mockTrackProductEvent.mockClear();
    render(<View {...baseProps} />);

    // The component must delegate to trackProductEvent, not call gtag/posthog directly
    expect(mockTrackProductEvent).toHaveBeenCalledTimes(1);
    expect(gtagSpy).not.toHaveBeenCalled();
    expect(captureSpy).not.toHaveBeenCalled();

    // Restore
    Object.defineProperty(window, 'gtag', { value: undefined, writable: true, configurable: true });
    Object.defineProperty(window, 'posthog', {
      value: undefined,
      writable: true,
      configurable: true,
    });
  });
});
