import { render, screen } 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/founder-dashboard',
      props: {
        auth: { user: { id: 1, name: 'Admin', email: 'admin@test.com', is_admin: true } },
        features: {
          billing: true,
          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(),
      visit: 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('recharts', () => ({
  ResponsiveContainer: ({ children }: { children: React.ReactNode }) => <div>{children}</div>,
  AreaChart: ({ children }: { children: React.ReactNode }) => <div>{children}</div>,
  BarChart: ({ children }: { children: React.ReactNode }) => <div>{children}</div>,
  PieChart: ({ children }: { children: React.ReactNode }) => <div>{children}</div>,
  LineChart: ({ children }: { children: React.ReactNode }) => <div>{children}</div>,
  Area: () => null,
  Bar: () => null,
  Pie: () => null,
  Line: () => null,
  Cell: () => null,
  XAxis: () => null,
  YAxis: () => null,
  CartesianGrid: () => null,
  Tooltip: () => null,
  Legend: () => null,
  ReferenceLine: () => null,
}));

vi.mock('@/Components/admin/NorthStarWidget', () => ({
  NorthStarWidget: () => <div data-testid="north-star-widget">North Star Widget</div>,
}));

vi.mock('@/Components/admin/CohortRetentionMatrix', () => ({
  CohortRetentionMatrix: () => <div data-testid="cohort-matrix">Cohort Matrix</div>,
}));

vi.mock('@/Components/admin/ConversionFunnelCard', () => ({
  ConversionFunnelCard: () => <div data-testid="conversion-funnel">Conversion Funnel</div>,
}));

import FounderDashboard from './FounderDashboard';

const defaultStats = {
  signups_today: 3,
  dau: 42,
  wau: 120,
  mau: 400,
  total_sites: 85,
  analyses_today: 12,
  analyses_week: 55,
  analyses_month: 210,
  drafts_today: 5,
  drafts_week: 22,
  drafts_month: 90,
  published_today: 2,
  published_week: 10,
  published_month: 35,
  active_subscriptions: 18,
  mrr_estimate: 45000,
  billing_enabled: true,
  queue_pending: 4,
  queue_failed_24h: 0,
  activation_rate: 62,
};

const defaultNorthStar = {
  weekly_active_recommenders: 20,
  active_sites: 55,
  total_weekly_runs: 80,
  baseline: 15,
  target: 50,
  trend: [],
};

const defaultTimeToValue = {
  median_hours: 24,
  p75_hours: 72,
  p95_hours: 168,
  sample_size: 100,
  goal_hours: 48,
};

const defaultConversionFunnel = {
  pricing_viewed: 50,
  upgrade_clicked: 20,
  subscription_started: 10,
  cancellation_initiated: 2,
};

const defaultNps = {
  score: 42,
  total: 80,
  promoters: 45,
  passives: 25,
  detractors: 10,
  by_type: {},
};

const defaultSerpAdoption = { users_with_key: 12, keywords_analyzed_7d: 88 };

const defaultOnboardingFunnel = {
  stages: [
    { name: 'Signup', users: 100, rate: 100.0 },
    { name: 'Site Added', users: 80, rate: 80.0 },
    { name: 'GSC Connected', users: 60, rate: 60.0 },
    { name: 'WP Connected', users: 40, rate: 40.0 },
  ],
  completion_rate: 40.0,
};

const defaultProps = {
  stats: defaultStats,
  top_users: [],
  funnel: { stages: [], activation_rate: 62 },
  cancellation_reasons: [],
  north_star: defaultNorthStar,
  cohort_matrix: [],
  time_to_value: defaultTimeToValue,
  engagement_trend: [],
  conversion_funnel: defaultConversionFunnel,
  monthly_churn: [],
  nps: defaultNps,
  serp_adoption: defaultSerpAdoption,
  acquisition_by_source: [],
  activation_funnel: {
    steps: [
      { label: 'Signup', count: 100, rate: 100.0 },
      { label: 'First Analysis', count: 60, rate: 60.0 },
      { label: 'First Draft', count: 40, rate: 40.0 },
      { label: 'First Publish', count: 20, rate: 20.0 },
    ],
  },
  onboarding_funnel: defaultOnboardingFunnel,
  recommendation_lifecycle: { stage_counts: {}, total: 0, applied_rate: 0.0 },
  data_quality: { score: null, total_events_7d: 0, validation_failures_7d: 0, computed_at: null },
  metric_errors: [] as string[],
  funnel_period: 90 as const,
  posthog_configured: false,
  last_refreshed_at: '2026-03-24T00:00:00Z',
  cache_ttl_seconds: 300,
};

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

  it('renders the Founder Dashboard heading', () => {
    render(<FounderDashboard {...defaultProps} />);
    expect(
      screen.getByRole('heading', { name: 'Founder Dashboard', level: 1 }),
    ).toBeInTheDocument();
  });

  it('shows PostHog warning when posthog_configured is false', () => {
    render(<FounderDashboard {...defaultProps} posthog_configured={false} />);
    expect(screen.getByRole('alert')).toBeInTheDocument();
    expect(screen.getByText(/PostHog not configured/)).toBeInTheDocument();
  });

  it('hides PostHog warning when posthog_configured is true', () => {
    render(<FounderDashboard {...defaultProps} posthog_configured={true} />);
    expect(screen.queryByRole('alert')).not.toBeInTheDocument();
  });

  it('renders engagement stat cards (DAU, WAU, MAU)', () => {
    render(<FounderDashboard {...defaultProps} />);
    expect(screen.getByText('DAU')).toBeInTheDocument();
    expect(screen.getByText('WAU')).toBeInTheDocument();
    expect(screen.getByText('MAU')).toBeInTheDocument();
  });

  it('renders signups_today stat', () => {
    render(<FounderDashboard {...defaultProps} stats={{ ...defaultStats, signups_today: 7 }} />);
    expect(screen.getByText('Signups Today')).toBeInTheDocument();
  });

  it('renders billing cards when billing is enabled', () => {
    render(
      <FounderDashboard
        {...defaultProps}
        stats={{
          ...defaultStats,
          billing_enabled: true,
          active_subscriptions: 18,
          mrr_estimate: 45000,
        }}
      />,
    );
    expect(screen.getByText('Active Subscriptions')).toBeInTheDocument();
    expect(screen.getByText('MRR Estimate')).toBeInTheDocument();
  });

  it('does not render billing cards when billing is disabled', () => {
    render(
      <FounderDashboard {...defaultProps} stats={{ ...defaultStats, billing_enabled: false }} />,
    );
    expect(screen.queryByText('Active Subscriptions')).not.toBeInTheDocument();
    expect(screen.queryByText('MRR Estimate')).not.toBeInTheDocument();
  });

  it('shows queue failed warning when queue_failed_24h > 0', () => {
    render(<FounderDashboard {...defaultProps} stats={{ ...defaultStats, queue_failed_24h: 3 }} />);
    expect(screen.getByText(/3 jobs? failed in the/)).toBeInTheDocument();
  });

  it('does not show queue failed warning when queue_failed_24h is 0', () => {
    render(<FounderDashboard {...defaultProps} stats={{ ...defaultStats, queue_failed_24h: 0 }} />);
    expect(screen.queryByText(/failed in the last 24h/)).not.toBeInTheDocument();
  });

  it('shows "No activity" message when top_users is empty', () => {
    render(<FounderDashboard {...defaultProps} top_users={[]} />);
    expect(screen.getByText(/No activity recorded in the last 7 days/)).toBeInTheDocument();
  });

  it('renders top users table when top_users is provided', () => {
    render(
      <FounderDashboard
        {...defaultProps}
        top_users={[
          { user_id: 1, name: 'Alice', email: 'alice@example.com', action_count: 150 },
          { user_id: 2, name: 'Bob', email: 'bob@example.com', action_count: 90 },
        ]}
      />,
    );
    expect(screen.getByText('Alice')).toBeInTheDocument();
    expect(screen.getByText('Bob')).toBeInTheDocument();
    expect(screen.getByText('alice@example.com')).toBeInTheDocument();
  });

  it('renders cancellation reasons when provided', () => {
    render(
      <FounderDashboard
        {...defaultProps}
        cancellation_reasons={[
          { reason: 'too_expensive', count: 5 },
          { reason: 'missing_features', count: 3 },
        ]}
      />,
    );
    expect(screen.getByText('Too Expensive')).toBeInTheDocument();
    expect(screen.getByText('Missing Features')).toBeInTheDocument();
  });

  it('does not render cancellation reasons section when empty', () => {
    render(<FounderDashboard {...defaultProps} cancellation_reasons={[]} />);
    expect(screen.queryByText('Cancellation Reasons')).not.toBeInTheDocument();
  });

  it('renders NPS section with score', () => {
    render(
      <FounderDashboard
        {...defaultProps}
        nps={{ score: 55, total: 100, promoters: 60, passives: 30, detractors: 10, by_type: {} }}
      />,
    );
    expect(screen.getByText('NPS Score')).toBeInTheDocument();
    expect(screen.getByText('+55')).toBeInTheDocument();
  });

  it('renders NPS section with "No responses yet" when total is 0', () => {
    render(
      <FounderDashboard
        {...defaultProps}
        nps={{ score: null, total: 0, promoters: 0, passives: 0, detractors: 0, by_type: {} }}
      />,
    );
    expect(screen.getByText('No responses yet.')).toBeInTheDocument();
  });

  it('renders SERP adoption section', () => {
    render(
      <FounderDashboard
        {...defaultProps}
        serp_adoption={{ users_with_key: 12, keywords_analyzed_7d: 88 }}
      />,
    );
    expect(screen.getByText('Users with SERP key')).toBeInTheDocument();
    expect(screen.getByText('Keywords analyzed (7d)')).toBeInTheDocument();
  });

  it('renders acquisition by source table when data is provided', () => {
    render(
      <FounderDashboard
        {...defaultProps}
        acquisition_by_source={[
          { source: 'google', signups: 50, activated: 30, drafted: 20, activation_rate: 60 },
        ]}
      />,
    );
    expect(screen.getByText('Acquisition by Source (90 days)')).toBeInTheDocument();
    expect(screen.getByText('google')).toBeInTheDocument();
  });

  it('does not render acquisition by source section when empty', () => {
    render(<FounderDashboard {...defaultProps} acquisition_by_source={[]} />);
    expect(screen.queryByText('Acquisition by Source (90 days)')).not.toBeInTheDocument();
  });

  it('renders engagement metrics when trend data is provided', () => {
    render(
      <FounderDashboard
        {...defaultProps}
        engagement_trend={[{ date: '2026-03-24', dau: 100, wau: 300, mau: 900 }]}
      />,
    );
    // EngagementMetricsCard shows DAU/WAU/MAU labels from audit log data
    expect(screen.getByText('Engagement (from audit log)')).toBeInTheDocument();
  });

  it('renders monthly churn data when provided', () => {
    render(
      <FounderDashboard
        {...defaultProps}
        monthly_churn={[{ month: '2026-03', churn_rate_pct: 3.5, churned_users: 7 }]}
      />,
    );
    expect(screen.getByText('3.5%')).toBeInTheDocument();
    expect(screen.getByText(/7 churned/)).toBeInTheDocument();
  });

  it('renders churn "not enabled" state when monthly_churn is empty', () => {
    render(<FounderDashboard {...defaultProps} monthly_churn={[]} />);
    expect(screen.getByText(/Billing not enabled or no data yet/)).toBeInTheDocument();
  });

  it('renders Time to Value widget', () => {
    render(<FounderDashboard {...defaultProps} />);
    // Section heading + card title both say "Time to Value" — use getAllByText
    expect(screen.getAllByText('Time to Value').length).toBeGreaterThanOrEqual(1);
    expect(screen.getByText('24h')).toBeInTheDocument();
  });

  it('renders activation funnel with stage data', () => {
    render(
      <FounderDashboard
        {...defaultProps}
        funnel={{
          stages: [
            { name: 'Registered', users: 1000, rate: 100 },
            { name: 'Connected GSC', users: 600, rate: 60 },
          ],
          activation_rate: 60,
        }}
      />,
    );
    expect(screen.getAllByText('Activation Funnel').length).toBeGreaterThanOrEqual(1);
    expect(screen.getByText('Registered')).toBeInTheDocument();
    expect(screen.getByText('Connected GSC')).toBeInTheDocument();
  });

  it('renders the NorthStar widget', () => {
    render(<FounderDashboard {...defaultProps} />);
    expect(screen.getByTestId('north-star-widget')).toBeInTheDocument();
  });

  it('renders the cohort retention section heading', () => {
    render(<FounderDashboard {...defaultProps} />);
    expect(screen.getByText('Cohort Retention')).toBeInTheDocument();
  });

  // DASH-003: metric error banner
  it('shows metric errors banner when metric_errors is non-empty', () => {
    render(<FounderDashboard {...defaultProps} metric_errors={['stats', 'north_star']} />);
    const alerts = screen.getAllByRole('alert');
    const errorAlert = alerts.find((el) => el.textContent?.includes('Some metrics failed to load'));
    expect(errorAlert).toBeDefined();
    expect(errorAlert?.textContent).toContain('stats');
    expect(errorAlert?.textContent).toContain('north_star');
  });

  it('does not show metric errors banner when metric_errors is empty', () => {
    render(<FounderDashboard {...defaultProps} metric_errors={[]} posthog_configured={true} />);
    expect(screen.queryByText(/Some metrics failed to load/)).not.toBeInTheDocument();
  });

  // FUNNEL-007: onboarding funnel section
  it('renders onboarding funnel section when stages are provided', () => {
    render(<FounderDashboard {...defaultProps} />);
    expect(screen.getByText('Onboarding Funnel')).toBeInTheDocument();
    expect(screen.getByText('Site Added')).toBeInTheDocument();
    expect(screen.getByText('GSC Connected')).toBeInTheDocument();
    expect(screen.getByText('WP Connected')).toBeInTheDocument();
    expect(screen.getByText(/reach full setup/)).toBeInTheDocument();
  });

  it('does not render onboarding funnel section when stages are empty', () => {
    render(
      <FounderDashboard {...defaultProps} onboarding_funnel={{ stages: [], completion_rate: 0 }} />,
    );
    expect(screen.queryByText('Onboarding Funnel')).not.toBeInTheDocument();
  });
});
