import React from 'react';
import '@testing-library/jest-dom';
import { fireEvent, render, screen, waitFor, within } from '@testing-library/react';
import { MemoryRouter, Route, Routes, useLocation } from 'react-router-dom';
import { ConfirmProvider } from './confirm';
import { PromptProvider } from './prompt';
import { ToastProvider } from './toast';
import { I18nProvider } from './i18n/I18nProvider';
import DashboardView from './components/DashboardView';
import RemindersView from './components/RemindersView';
import JobTable from './components/JobTable';
import { api } from './api';

const mockedApi = api as jest.Mocked<typeof api>;

const pagedJobs = {
  items: [
    {
      id: 42,
      jobTitle: 'Backend Developer',
      status: 'Waiting',
      dateApplied: new Date().toISOString(),
      daysSince: 10,
      company: { name: 'Acme' },
      companyId: 1,
      needsFollowUp: true,
      followUpReason: 'Follow-up due soon',
      shortSummary: 'Strong backend match',
      tailoredCvText: 'Saved CV',
      notes: 'Notes\n\n<<<APPLICATION_ANSWER_DRAFT>>>\nSaved answer\n<<<END_APPLICATION_ANSWER_DRAFT>>>',
      workflowSignal: {
        actionKey: 'follow-up',
        reason: 'Follow-up due soon',
        workspaceTab: 'follow-up',
        followMode: 'waiting-update',
        needsAttention: true,
        hasPackageGap: false,
        needsInterviewPrep: false,
        needsFollowUpAction: true,
        hasTailoredCv: true,
        hasSavedApplicationAnswerDraft: true,
        hasInterviewPrepNotes: true,
      },
    },
    {
      id: 43,
      jobTitle: 'Platform Engineer',
      status: 'Applied',
      dateApplied: new Date().toISOString(),
      daysSince: 4,
      company: { name: 'Beta' },
      companyId: 2,
      needsFollowUp: false,
      followUpReason: 'Tailored CV missing',
      shortSummary: 'Platform work',
      tailoredCvText: null,
      notes: null,
      workflowSignal: {
        actionKey: 'package-work',
        reason: 'Tailored CV missing for this role.',
        workspaceTab: 'tailored-cv',
        followMode: null,
        needsAttention: true,
        hasPackageGap: true,
        needsInterviewPrep: false,
        needsFollowUpAction: false,
        hasTailoredCv: false,
        hasSavedApplicationAnswerDraft: false,
        hasInterviewPrepNotes: false,
      },
    },
  ],
  total: 2,
  page: 1,
  pageSize: 15,
};

const reminderItems = [
  {
    id: 42,
    jobTitle: 'Backend Developer',
    status: 'Waiting',
    dateApplied: new Date().toISOString(),
    daysSince: 10,
    company: { name: 'Acme' },
    needsFollowUp: true,
    followUpReason: 'Follow-up due soon',
    tailoredCvText: 'Saved CV',
    followUpAt: new Date().toISOString(),
    workflowSignal: {
      actionKey: 'follow-up',
      reason: 'Follow-up due soon',
      workspaceTab: 'follow-up',
      followMode: 'waiting-update',
      needsAttention: true,
      hasPackageGap: false,
      needsInterviewPrep: false,
      needsFollowUpAction: true,
      hasTailoredCv: true,
      hasSavedApplicationAnswerDraft: true,
      hasInterviewPrepNotes: true,
    },
  },
  {
    id: 43,
    jobTitle: 'Platform Engineer',
    status: 'Applied',
    dateApplied: new Date().toISOString(),
    daysSince: 4,
    company: { name: 'Beta' },
    needsFollowUp: true,
    followUpReason: 'Tailored CV missing',
    tailoredCvText: null,
    followUpAt: new Date().toISOString(),
    workflowSignal: {
      actionKey: 'package-work',
      reason: 'Tailored CV missing for this role.',
      workspaceTab: 'tailored-cv',
      followMode: null,
      needsAttention: true,
      hasPackageGap: true,
      needsInterviewPrep: false,
      needsFollowUpAction: true,
      hasTailoredCv: false,
      hasSavedApplicationAnswerDraft: false,
      hasInterviewPrepNotes: false,
    },
  },
];

function setupApiMocks() {
  mockedApi.get.mockImplementation((url: string) => {
    if (url === '/companies') return Promise.resolve({ data: [{ id: 1, name: 'Acme' }, { id: 2, name: 'Beta' }] } as any);
    if (url === '/jobapplications/reminders') return Promise.resolve({ data: reminderItems } as any);
    if (url === '/jobapplications') return Promise.resolve({ data: pagedJobs } as any);
    if (url === '/jobapplications/stats') return Promise.resolve({ data: { total: 2, active: 2, deleted: 0, byStatus: {}, appliedLast30Days: 2, averageDaysSinceApplied: 7 } } as any);
    if (url === '/jobapplications/analytics-overview') return Promise.resolve({ data: { funnel: [], responseRateBySource: [], topCompanies: [], totalResponses: 1, totalActive: 2 } } as any);
    if (url === '/jobapplications/analytics' || url === '/jobapplications/tags') return Promise.resolve({ data: [] } as any);
    if (url === '/jobapplications/tag-trends') return Promise.resolve({ data: { months: [], series: [] } } as any);
    if (url === '/jobapplications/42') {
      return Promise.resolve({ data: { id: 42, jobTitle: 'Backend Developer', status: 'Waiting', dateApplied: new Date().toISOString(), daysSince: 10, company: { name: 'Acme', recruiterEmail: 'maria@acme.test' }, tailoredCvText: 'Saved CV', coverLetterText: 'Saved cover letter', recruiterMessageDraft: 'Saved recruiter message', notes: 'Notes\n\n<<<APPLICATION_ANSWER_DRAFT>>>\nSaved answer\n<<<END_APPLICATION_ANSWER_DRAFT>>>', shortSummary: 'Strong backend match' } } as any);
    }
    if (url === '/jobapplications/43') {
      return Promise.resolve({ data: { id: 43, jobTitle: 'Platform Engineer', status: 'Applied', dateApplied: new Date().toISOString(), daysSince: 4, company: { name: 'Beta', recruiterEmail: 'recruiter@beta.test' }, tailoredCvText: '', coverLetterText: '', recruiterMessageDraft: '', notes: '', shortSummary: 'Platform work' } } as any);
    }
    if (url === '/jobapplications/42/history' || url === '/jobapplications/43/history') return Promise.resolve({ data: [] } as any);
    if (url === '/attachments/42' || url === '/attachments/43') return Promise.resolve({ data: [] } as any);
    if (url === '/jobapplications/42/followup-draft') {
      return Promise.resolve({ data: { subject: 'Re: Backend Developer application update', body: 'Hi Maria,\n\nFollow-up draft.\n\nThanks,\nDemo', reason: 'Follow-up due soon', suggestedSendOn: new Date().toISOString(), contextSummary: 'Saved application package material is available for reuse.', contextSignals: ['Saved cover letter available'], threadSubject: 'Backend Developer application update', lastCorrespondenceFrom: 'Maria Recruiter <maria@acme.test>', lastCorrespondenceAt: new Date().toISOString() } } as any);
    }
    return Promise.resolve({ data: [] } as any);
  });
}

function LocationIndicator() {
  const location = useLocation();
  return <div data-testid="location-indicator">{location.pathname}{location.search}</div>;
}

function renderLoop(initialPath: string) {
  return render(
    <ToastProvider>
      <I18nProvider>
        <ConfirmProvider>
          <PromptProvider>
            <MemoryRouter initialEntries={[initialPath]}>
              <LocationIndicator />
              <Routes>
                <Route path="/dashboard" element={<DashboardView />} />
                <Route path="/reminders" element={<RemindersView />} />
                <Route path="/jobs" element={<JobTable refreshToken={0} pageSize={15} onPageSizeChange={() => {}} columns={{ status: true, dateApplied: true, daysSince: true, jobUrl: false }} onColumnsChange={() => {}} mode="jobs" />} />
                <Route path="/jobs/:id" element={<div data-testid="application-workspace" />} />
              </Routes>
            </MemoryRouter>
          </PromptProvider>
        </ConfirmProvider>
      </I18nProvider>
    </ToastProvider>,
  );
}

beforeEach(() => {
  window.localStorage.clear();
  setupApiMocks();
});

afterEach(() => {
  jest.clearAllMocks();
});

test('dashboard attention card opens follow-up workspace', async () => {
  renderLoop('/dashboard');

  expect(await screen.findByText(/^today$/i)).toBeInTheDocument();
  fireEvent.click(await screen.findByRole('button', { name: /follow up/i }));

  await waitFor(() => expect(screen.getByTestId('location-indicator')).toHaveTextContent('/jobs/42?section=communication&followMode=waiting-update'));
  expect(screen.getByTestId('application-workspace')).toBeInTheDocument();
});

test('empty dashboard prioritizes onboarding and suppresses meaningless analytics', async () => {
  mockedApi.get.mockImplementation((url: string) => {
    if (url === '/jobapplications/stats') return Promise.resolve({ data: { total: 0, active: 0, deleted: 0, byStatus: {}, appliedLast30Days: 0, averageDaysSinceApplied: 0 } } as any);
    if (url === '/jobapplications/analytics-overview') return Promise.resolve({ data: { funnel: Array.from({ length: 10 }, (_, index) => ({ label: `Stage ${index}`, count: 0 })), responseRateBySource: [], topCompanies: [], totalResponses: 0, totalActive: 0, timeInStage: [] } } as any);
    if (url === '/jobapplications/reminders' || url === '/jobapplications/analytics' || url === '/jobapplications/tags') return Promise.resolve({ data: [] } as any);
    if (url === '/jobapplications/tag-trends') return Promise.resolve({ data: { months: [], series: [] } } as any);
    return Promise.resolve({ data: {} } as any);
  });

  const view = renderLoop('/dashboard');

  expect(await screen.findByText(/get set up/i)).toBeInTheDocument();
  await waitFor(() => expect(screen.queryByText(/application activity/i)).not.toBeInTheDocument());
  expect(screen.queryByText(/conversion funnel/i)).not.toBeInTheDocument();
  expect(screen.queryByText(/median time in stage/i)).not.toBeInTheDocument();
  expect(screen.queryByText(/top companies by activity/i)).not.toBeInTheDocument();
  expect(screen.queryByText(/^top skills$/i)).not.toBeInTheDocument();

  fireEvent.click(screen.getByRole('button', { name: /dismiss setup checklist/i }));
  expect(screen.queryByText(/get set up/i)).not.toBeInTheDocument();
  view.unmount();

  renderLoop('/dashboard');
  await waitFor(() => expect(screen.queryByText(/get set up/i)).not.toBeInTheDocument());
});

test('reminders open action routes tailored-cv gaps into the tailored cv workspace', async () => {
  renderLoop('/reminders');

  expect(await screen.findByText(/missing tailored cv/i)).toBeInTheDocument();
  const platformJob = await screen.findByText(/platform engineer/i);
  const platformCard = platformJob.closest('.MuiPaper-root') ?? platformJob.parentElement?.parentElement;
  expect(platformCard).toBeTruthy();
  fireEvent.click(within(platformCard as HTMLElement).getByRole('button', { name: /build package/i }));

  await waitFor(() => expect(screen.getByTestId('location-indicator')).toHaveTextContent('/jobs/43?section=cv'));
  expect(screen.getByTestId('application-workspace')).toBeInTheDocument();
});

test('job table urgency signals and next actions route into the shared workspace flow', async () => {
  const firstRender = renderLoop('/jobs');

  fireEvent.click(await screen.findByRole('button', { name: /backend developer — follow up signal/i }));

  await waitFor(() => expect(screen.getByTestId('location-indicator')).toHaveTextContent('/jobs/42?section=communication&followMode=waiting-update'));
  expect(screen.getByTestId('application-workspace')).toBeInTheDocument();

  firstRender.unmount();
  renderLoop('/jobs');

  fireEvent.click(await screen.findByRole('button', { name: /platform engineer.*build package signal/i }));

  await waitFor(() => expect(screen.getByTestId('location-indicator')).toHaveTextContent('/jobs/43?section=cv'));
  expect(screen.getByTestId('application-workspace')).toBeInTheDocument();
});
