import React from 'react';
import { fireEvent, render, screen, waitFor } from '@testing-library/react';

import AdminSystemPage from './views/AdminSystemPage';
import { I18nProvider } from './i18n/I18nProvider';
import { api } from './api';

jest.mock('./api', () => ({
  api: {
    get: jest.fn(),
    post: jest.fn(),
    put: jest.fn(),
    patch: jest.fn(),
    delete: jest.fn(),
    interceptors: { request: { use: jest.fn() }, response: { use: jest.fn() } },
  },
  getApiErrorMessage: (error: any, fallback?: string) => fallback || 'Request failed.',
}));

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

describe('AdminSystemPage', () => {
  beforeEach(() => {
    window.localStorage.clear();
    mockedApi.get.mockImplementation((url: string) => {
      if (url === '/admin/system') {
        return Promise.resolve({
          data: {
            environment: 'Production',
            contentRoot: '/app',
            version: '1.2.3',
            commitSha: 'abc1234',
            buildStamp: '2026-03-23 11:00 UTC',
            storage: { dataRoot: '/data', dbPath: '/data/jobtracker.db', dbExists: true, dbSizeBytes: 2048, companyCount: 3, jobCount: 7, deletedCount: 1 },
            email: { enabled: true, host: 'smtp.example.test', port: 587, enableSsl: true, from: 'noreply@example.test', fromName: 'Jobbjakt' },
            database: { provider: 'mariadb', looksConfigured: true, canConnect: true, target: 'server=db', usesFileStorage: false, warning: null },
            runtime: { framework: '.NET 9', osDescription: 'Linux', processArchitecture: 'X64', machineName: 'app-01' },
            auth: { required: true, hasJwtKey: true, googleConfigured: true, gmailConfigured: true },
            ai: {
              healthy: true,
              model: 'distilbart',
              device: 'cpu',
              gpuAvailable: false,
              gpuName: null,
              ocrAvailable: true,
              ocrLanguages: 'eng',
              ollamaConfigured: true,
              ollamaReachable: true,
              ollamaModel: 'qwen2.5:7b',
              ollamaModelAvailable: true,
              ollamaVersion: '0.7.0',
              ollamaInstalledModels: ['qwen2.5:7b', 'nomic-embed-text'],
              ollamaLoadedModels: ['qwen2.5:7b'],
              ollamaLoadedCount: 1,
              healthLatencyMs: 12.4,
              probeLatencyMs: 25.8,
              lastProbeAt: '2026-03-23T10:00:00Z',
              lastProbeSuccessAt: '2026-03-23T10:00:00Z',
              lastProbeFailureAt: null,
              probeFailures: 0,
              requests: 18,
              cacheHits: 9,
              cacheMisses: 9,
              failures: 0,
              averageLatencyMs: 42.2,
              ocrRequests: 5,
              ocrFailures: 0,
              averageOcrLatencyMs: 88.4,
              lastOcrSuccessAt: '2026-03-23T10:05:00Z',
              lastOcrFailureAt: null,
              lastSuccessAt: '2026-03-23T10:04:00Z',
              lastFailureAt: null,
              lastError: null,
            },
          },
        } as any);
      }
      if (url === '/admin/system/email-settings') {
        return Promise.resolve({
          data: {
            enabled: true,
            host: 'smtp.example.test',
            port: 587,
            user: 'mailer@example.test',
            from: 'noreply@example.test',
            fromName: 'Jobbjakt',
            enableSsl: true,
            timeoutMs: 15000,
            usesOverrides: false,
            hasPassword: true,
          },
        } as any);
      }
      if (url === '/admin/system/cv-benchmark') {
        return Promise.resolve({
          data: {
            rootPath: '/data/CvBenchmarks/latest',
            lastUpdatedAtUtc: '2026-03-23T10:10:00Z',
            reportMarkdown: '# CV benchmark report\n\n- Files: 4',
            indexJson: JSON.stringify({
              CorpusRoot: '/home/pi/cvs',
              OutputRoot: '/data/CvBenchmarks/latest',
              GeneratedAtUtc: '2026-03-23T10:10:00Z',
              TotalFiles: 4,
              AverageCoverage: 0.72,
              AverageConfidence: 0.66,
              AverageConsistency: 0.94,
              FilesWithSuspiciousLocations: 1,
              MissingApprovedFixtures: 4,
              Entries: [
                {
                  FileName: 'cv.txt',
                  Slug: 'cv-txt',
                  Extension: '.txt',
                  Characters: 2000,
                  OutputPath: '/data/CvBenchmarks/latest/outputs/cv-txt.json',
                  ApprovedFixturePath: null,
                  CandidateFixturePath: '/data/CvBenchmarks/latest/candidate-fixtures/cv-txt.json',
                  ContactLocation: 'San Francisco, Hobbies',
                  FirstJob: '* July',
                  FirstJobLocation: null,
                  FirstEducation: '* September',
                  FirstEducationLocation: null,
                  QualificationLevels: ['Other'],
                  SuspiciousLocations: [],
                  CoverageScore: 0.5,
                  ConfidenceScore: 0.65,
                  ConsistencyScore: 0.8,
                  DiffSummary: 'No approved fixture yet — candidate fixture written.',
                },
              ],
            }),
          },
        } as any);
      }
      return Promise.resolve({ data: {} } as any);
    });
    mockedApi.put.mockResolvedValue({
      data: {
        enabled: true,
        host: 'smtp.changed.test',
        port: 2525,
        user: 'mailer@example.test',
        from: 'noreply@example.test',
        fromName: 'Jobbjakt',
        enableSsl: true,
        timeoutMs: 15000,
        usesOverrides: true,
        hasPassword: true,
      },
    } as any);
  });

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

  it('renders AI service health, latency, and OCR readiness', async () => {
    render(
      <I18nProvider>
        <AdminSystemPage />
      </I18nProvider>,
    );

    await waitFor(() => {
      expect(screen.getByText('Production')).toBeTruthy();
    });

    expect(screen.getByText(/25.8 ms probe/i)).toBeTruthy();
    expect(screen.getByText('OCR eng')).toBeTruthy();
    expect(screen.getAllByText(/ollama configured/i).length).toBeGreaterThan(0);
    expect(screen.getByText(/ollama version/i)).toBeTruthy();
    expect(screen.getByText(/model · qwen2.5:7b/i)).toBeTruthy();
    expect(screen.getByText(/cv benchmark review/i)).toBeTruthy();
    expect(screen.getByText(/top parser findings/i)).toBeTruthy();
    expect(screen.getByText(/suspicious contact location: san francisco, hobbies/i)).toBeTruthy();
    expect(screen.getByText('OCR avg latency')).toBeTruthy();
    expect(screen.getByText('88.4 ms')).toBeTruthy();
  });

  it('loads and saves smtp settings from the settings tab', async () => {
    render(
      <I18nProvider>
        <AdminSystemPage />
      </I18nProvider>,
    );

    expect(await screen.findByText('AI service')).toBeTruthy();
    fireEvent.click(screen.getByRole('tab', { name: /settings/i }));

    const hostInput = await screen.findByLabelText(/host/i);
    fireEvent.change(hostInput, { target: { value: 'smtp.changed.test' } });
    fireEvent.change(screen.getByLabelText(/port/i), { target: { value: '2525' } });
    fireEvent.click(screen.getByRole('button', { name: /save settings/i }));

    await waitFor(() => {
      expect(mockedApi.put).toHaveBeenCalledWith('/admin/system/email-settings', expect.objectContaining({
        host: 'smtp.changed.test',
        port: 2525,
      }));
    });
  });

  it('localizes benchmark diagnostics without changing runtime values', async () => {
    window.localStorage.setItem('uiLanguage', 'nb');
    render(<I18nProvider><AdminSystemPage /></I18nProvider>);

    expect(await screen.findByText('Gjennomgang av CV-referansetest')).toBeTruthy();
    expect(screen.getByText(/Mistenkelig kontaktsted: san francisco, hobbies/i)).toBeTruthy();
    expect(screen.getByText('Production')).toBeTruthy();
    expect(screen.getByText(/Modell · qwen2.5:7b/i)).toBeTruthy();
    fireEvent.click(screen.getByRole('tab', { name: /innstillinger/i }));
    expect(await screen.findByDisplayValue('Dette er en test-e-post fra systempanelet i Jobbjakt.')).toBeTruthy();
  });
});
