import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
import axios from 'axios';

// Mock axios
vi.mock('axios', () => {
  const mockAxios = {
    create: vi.fn(() => mockAxios),
    post: vi.fn(),
    get: vi.fn(),
    interceptors: {
      request: { use: vi.fn() },
      response: { use: vi.fn() },
    },
  };
  return { default: mockAxios };
});

/**
 * API integration tests — verifies the frontend sends requests
 * in the exact format the backend expects.
 *
 * These tests map to every tool in the application:
 * - Convert: PDF↔Word
 * - Compress: PDF
 * - Image: Convert, Resize
 * - PDF Tools: Merge, Split, Rotate, Page Numbers, PDF↔Images, Watermark, Protect, Unlock
 * - Video: To GIF
 * - Tasks: Status polling
 * - Download: File download
 */
describe('API Service — Endpoint Format Tests', () => {

  // ----------------------------------------------------------
  // Convert endpoints
  // ----------------------------------------------------------
  describe('Convert API', () => {
    it('PDF to Word: should POST formData with file to /convert/pdf-to-word', () => {
      const formData = new FormData();
      formData.append('file', new Blob(['%PDF-1.4']), 'doc.pdf');
      const endpoint = '/convert/pdf-to-word';

      // Verify the endpoint and field name match backend expectations
      expect(endpoint).toBe('/convert/pdf-to-word');
      // Backend expects: request.files['file'] → multipart/form-data
      expect(formData.has('file')).toBe(true);
    });

    it('Word to PDF: should POST formData with file to /convert/word-to-pdf', () => {
      const formData = new FormData();
      formData.append('file', new Blob(['PK']), 'report.docx');
      const endpoint = '/convert/word-to-pdf';

      expect(endpoint).toBe('/convert/word-to-pdf');
      expect(formData.has('file')).toBe(true);
    });
  });

  // ----------------------------------------------------------
  // Compress endpoint
  // ----------------------------------------------------------
  describe('Compress API', () => {
    it('Compress PDF: should POST file + quality to /compress/pdf', () => {
      const formData = new FormData();
      formData.append('file', new Blob(['%PDF-1.4']), 'large.pdf');
      formData.append('quality', 'medium');
      const endpoint = '/compress/pdf';

      expect(endpoint).toBe('/compress/pdf');
      expect(formData.has('file')).toBe(true);
      expect(formData.get('quality')).toBe('medium');
    });
  });

  // ----------------------------------------------------------
  // Image endpoints
  // ----------------------------------------------------------
  describe('Image API', () => {
    it('Image Convert: should POST file + format + quality to /image/convert', () => {
      const formData = new FormData();
      formData.append('file', new Blob(['\x89PNG']), 'photo.png');
      formData.append('format', 'jpg');
      formData.append('quality', '85');
      const endpoint = '/image/convert';

      expect(endpoint).toBe('/image/convert');
      expect(formData.get('format')).toBe('jpg');
      expect(formData.get('quality')).toBe('85');
    });

    it('Image Resize: should POST file + width + height to /image/resize', () => {
      const formData = new FormData();
      formData.append('file', new Blob(['\x89PNG']), 'photo.png');
      formData.append('width', '800');
      formData.append('height', '600');
      const endpoint = '/image/resize';

      expect(endpoint).toBe('/image/resize');
      expect(formData.get('width')).toBe('800');
    });
  });

  // ----------------------------------------------------------
  // PDF Tools endpoints
  // ----------------------------------------------------------
  describe('PDF Tools API', () => {
    it('Merge: should POST multiple files to /pdf-tools/merge', () => {
      const formData = new FormData();
      formData.append('files', new Blob(['%PDF-1.4']), 'a.pdf');
      formData.append('files', new Blob(['%PDF-1.4']), 'b.pdf');
      const url = '/pdf-tools/merge';

      expect(url).toBe('/pdf-tools/merge');
      expect(formData.getAll('files').length).toBe(2);
    });

    it('Split: should POST file + mode + pages to /pdf-tools/split', () => {
      const formData = new FormData();
      formData.append('file', new Blob(['%PDF-1.4']), 'doc.pdf');
      formData.append('mode', 'range');
      formData.append('pages', '1,3,5-8');
      const endpoint = '/pdf-tools/split';

      expect(endpoint).toBe('/pdf-tools/split');
      expect(formData.get('mode')).toBe('range');
      expect(formData.get('pages')).toBe('1,3,5-8');
    });

    it('Rotate: should POST file + rotation + pages to /pdf-tools/rotate', () => {
      const formData = new FormData();
      formData.append('file', new Blob(['%PDF-1.4']), 'doc.pdf');
      formData.append('rotation', '90');
      formData.append('pages', 'all');
      const endpoint = '/pdf-tools/rotate';

      expect(endpoint).toBe('/pdf-tools/rotate');
      expect(formData.get('rotation')).toBe('90');
    });

    it('Page Numbers: should POST file + position + start_number to /pdf-tools/page-numbers', () => {
      const formData = new FormData();
      formData.append('file', new Blob(['%PDF-1.4']), 'doc.pdf');
      formData.append('position', 'bottom-center');
      formData.append('start_number', '1');
      const endpoint = '/pdf-tools/page-numbers';

      expect(endpoint).toBe('/pdf-tools/page-numbers');
      expect(formData.get('position')).toBe('bottom-center');
    });

    it('PDF to Images: should POST file + format + dpi to /pdf-tools/pdf-to-images', () => {
      const formData = new FormData();
      formData.append('file', new Blob(['%PDF-1.4']), 'doc.pdf');
      formData.append('format', 'png');
      formData.append('dpi', '200');
      const endpoint = '/pdf-tools/pdf-to-images';

      expect(endpoint).toBe('/pdf-tools/pdf-to-images');
      expect(formData.get('format')).toBe('png');
    });

    it('Images to PDF: should POST multiple files to /pdf-tools/images-to-pdf', () => {
      const formData = new FormData();
      formData.append('files', new Blob(['\x89PNG']), 'img1.png');
      formData.append('files', new Blob(['\x89PNG']), 'img2.png');
      const url = '/pdf-tools/images-to-pdf';

      expect(url).toBe('/pdf-tools/images-to-pdf');
      expect(formData.getAll('files').length).toBe(2);
    });

    it('Watermark: should POST file + text + opacity to /pdf-tools/watermark', () => {
      const formData = new FormData();
      formData.append('file', new Blob(['%PDF-1.4']), 'doc.pdf');
      formData.append('text', 'CONFIDENTIAL');
      formData.append('opacity', '0.3');
      const endpoint = '/pdf-tools/watermark';

      expect(endpoint).toBe('/pdf-tools/watermark');
      expect(formData.get('text')).toBe('CONFIDENTIAL');
      expect(formData.get('opacity')).toBe('0.3');
    });

    it('Protect: should POST file + password to /pdf-tools/protect', () => {
      const formData = new FormData();
      formData.append('file', new Blob(['%PDF-1.4']), 'doc.pdf');
      formData.append('password', 'mySecret');
      const endpoint = '/pdf-tools/protect';

      expect(endpoint).toBe('/pdf-tools/protect');
      expect(formData.get('password')).toBe('mySecret');
    });

    it('Unlock: should POST file + password to /pdf-tools/unlock', () => {
      const formData = new FormData();
      formData.append('file', new Blob(['%PDF-1.4']), 'doc.pdf');
      formData.append('password', 'existingPass');
      const endpoint = '/pdf-tools/unlock';

      expect(endpoint).toBe('/pdf-tools/unlock');
      expect(formData.get('password')).toBe('existingPass');
    });
  });

  // ----------------------------------------------------------
  // Video endpoint
  // ----------------------------------------------------------
  describe('Video API', () => {
    it('Video to GIF: should POST file + params to /video/to-gif', () => {
      const formData = new FormData();
      formData.append('file', new Blob(['\x00']), 'clip.mp4');
      formData.append('start_time', '0');
      formData.append('duration', '5');
      formData.append('fps', '10');
      formData.append('width', '480');
      const endpoint = '/video/to-gif';

      expect(endpoint).toBe('/video/to-gif');
      expect(formData.get('start_time')).toBe('0');
      expect(formData.get('duration')).toBe('5');
      expect(formData.get('fps')).toBe('10');
      expect(formData.get('width')).toBe('480');
    });
  });

  // ----------------------------------------------------------
  // Task polling endpoint
  // ----------------------------------------------------------
  describe('Task Polling API', () => {
    it('should GET /tasks/{taskId}/status', () => {
      const taskId = 'abc-123-def-456';
      const endpoint = `/tasks/${taskId}/status`;
      expect(endpoint).toBe('/tasks/abc-123-def-456/status');
    });
  });

  // ----------------------------------------------------------
  // Health endpoint
  // ----------------------------------------------------------
  describe('Health API', () => {
    it('should GET /health', () => {
      const endpoint = '/health';
      expect(endpoint).toBe('/health');
    });
  });
});

/**
 * Frontend→Backend endpoint mapping verification.
 * This ensures the frontend components use the correct endpoints.
 */
describe('Frontend Tool → Backend Endpoint Mapping', () => {
  const toolEndpointMap: Record<string, { method: string; endpoint: string; fieldName: string }> = {
    PdfToWord:       { method: 'POST', endpoint: '/convert/pdf-to-word',      fieldName: 'file' },
    WordToPdf:       { method: 'POST', endpoint: '/convert/word-to-pdf',      fieldName: 'file' },
    PdfCompressor:   { method: 'POST', endpoint: '/compress/pdf',             fieldName: 'file' },
    ImageConverter:  { method: 'POST', endpoint: '/image/convert',            fieldName: 'file' },
    SplitPdf:        { method: 'POST', endpoint: '/pdf-tools/split',          fieldName: 'file' },
    RotatePdf:       { method: 'POST', endpoint: '/pdf-tools/rotate',         fieldName: 'file' },
    WatermarkPdf:    { method: 'POST', endpoint: '/pdf-tools/watermark',      fieldName: 'file' },
    ProtectPdf:      { method: 'POST', endpoint: '/pdf-tools/protect',        fieldName: 'file' },
    UnlockPdf:       { method: 'POST', endpoint: '/pdf-tools/unlock',         fieldName: 'file' },
    AddPageNumbers:  { method: 'POST', endpoint: '/pdf-tools/page-numbers',   fieldName: 'file' },
    PdfToImages:     { method: 'POST', endpoint: '/pdf-tools/pdf-to-images',  fieldName: 'file' },
    VideoToGif:      { method: 'POST', endpoint: '/video/to-gif',             fieldName: 'file' },
    MergePdf:        { method: 'POST', endpoint: '/pdf-tools/merge',      fieldName: 'files' },
    ImagesToPdf:     { method: 'POST', endpoint: '/pdf-tools/images-to-pdf', fieldName: 'files' },
  };

  Object.entries(toolEndpointMap).forEach(([tool, config]) => {
    it(`${tool}: ${config.method} ${config.endpoint} → field "${config.fieldName}"`, () => {
      expect(config.endpoint).toBeTruthy();
      expect(config.method).toBe('POST');
      expect(config.fieldName).toMatch(/^(file|files)$/);
    });
  });
});
