/**
 * @ai-summary Hook to orchestrate maintenance receipt OCR extraction
 * @ai-context Mirrors useReceiptOcr pattern: capture -> OCR -> category suggestion -> review -> accept
 */

import { useState, useCallback } from 'react';
import { apiClient } from '../../../core/api/client';
import {
  ExtractedMaintenanceReceiptFields,
  ExtractedMaintenanceField,
  MappedMaintenanceFields,
  MaintenanceReceiptOcrResult,
  CategorySuggestion,
  UseMaintenanceReceiptOcrReturn,
} from '../types/maintenance-receipt.types';
import { MaintenanceCategory } from '../types/maintenance.types';

/** Confidence threshold for highlighting low-confidence fields */
export const LOW_CONFIDENCE_THRESHOLD = 0.7;

/** Keyword-to-category/subtype mapping for service name suggestion */
const SERVICE_KEYWORD_MAP: Array<{
  keywords: string[];
  category: MaintenanceCategory;
  subtypes: string[];
}> = [
  // Routine maintenance mappings
  { keywords: ['oil change', 'oil filter', 'engine oil', 'synthetic oil', 'conventional oil', 'oil & filter'],
    category: 'routine_maintenance', subtypes: ['Engine Oil'] },
  { keywords: ['tire rotation', 'tire balance', 'wheel balance', 'tire alignment', 'alignment'],
    category: 'routine_maintenance', subtypes: ['Tires'] },
  { keywords: ['brake pad', 'brake rotor', 'brake fluid', 'brake inspection', 'brake service', 'brakes'],
    category: 'routine_maintenance', subtypes: ['Brakes and Traction Control'] },
  { keywords: ['air filter', 'engine air filter'],
    category: 'routine_maintenance', subtypes: ['Air Filter Element'] },
  { keywords: ['cabin filter', 'cabin air', 'a/c filter'],
    category: 'routine_maintenance', subtypes: ['Cabin Air Filter / Purifier'] },
  { keywords: ['spark plug', 'ignition'],
    category: 'routine_maintenance', subtypes: ['Spark Plug'] },
  { keywords: ['coolant', 'antifreeze', 'radiator flush', 'cooling system'],
    category: 'routine_maintenance', subtypes: ['Coolant'] },
  { keywords: ['transmission fluid', 'trans fluid', 'atf'],
    category: 'routine_maintenance', subtypes: ['Fluid - A/T'] },
  { keywords: ['differential fluid', 'diff fluid'],
    category: 'routine_maintenance', subtypes: ['Fluid - Differential'] },
  { keywords: ['wiper blade', 'wiper', 'windshield wiper'],
    category: 'routine_maintenance', subtypes: ['Wiper Blade'] },
  { keywords: ['washer fluid', 'windshield washer'],
    category: 'routine_maintenance', subtypes: ['Washer Fluid'] },
  { keywords: ['drive belt', 'serpentine belt', 'timing belt', 'belt replacement'],
    category: 'routine_maintenance', subtypes: ['Drive Belt'] },
  { keywords: ['exhaust', 'muffler', 'catalytic'],
    category: 'routine_maintenance', subtypes: ['Exhaust System'] },
  { keywords: ['suspension', 'shock', 'strut', 'ball joint', 'tie rod'],
    category: 'routine_maintenance', subtypes: ['Steering and Suspension'] },
  { keywords: ['fuel filter', 'fuel injection', 'fuel system', 'fuel delivery'],
    category: 'routine_maintenance', subtypes: ['Fuel Delivery and Air Induction'] },
  { keywords: ['parking brake', 'e-brake', 'emergency brake'],
    category: 'routine_maintenance', subtypes: ['Parking Brake System'] },
  // Repair mappings
  { keywords: ['engine repair', 'engine rebuild', 'head gasket', 'valve cover'],
    category: 'repair', subtypes: ['Engine'] },
  { keywords: ['transmission repair', 'trans rebuild'],
    category: 'repair', subtypes: ['Transmission'] },
  { keywords: ['axle', 'cv joint', 'driveshaft', 'drivetrain'],
    category: 'repair', subtypes: ['Drivetrain'] },
  { keywords: ['body work', 'dent', 'paint', 'bumper', 'fender'],
    category: 'repair', subtypes: ['Exterior'] },
  { keywords: ['upholstery', 'dashboard', 'seat repair', 'interior repair'],
    category: 'repair', subtypes: ['Interior'] },
];

/** Suggest category and subtypes from service name using keyword matching */
function suggestCategory(serviceName: string | number | null): CategorySuggestion | null {
  if (!serviceName) return null;
  const normalized = String(serviceName).toLowerCase().trim();
  if (!normalized) return null;

  for (const mapping of SERVICE_KEYWORD_MAP) {
    for (const keyword of mapping.keywords) {
      if (normalized.includes(keyword)) {
        return {
          category: mapping.category,
          subtypes: mapping.subtypes,
          confidence: 0.8,
        };
      }
    }
  }

  // No match found - default to routine_maintenance with no subtypes
  return null;
}

/** Parse date string to YYYY-MM-DD format */
function parseServiceDate(value: string | number | null): string | undefined {
  if (!value) return undefined;

  const dateStr = String(value);

  // Already in YYYY-MM-DD format
  if (/^\d{4}-\d{2}-\d{2}$/.test(dateStr)) {
    const date = new Date(dateStr + 'T00:00:00');
    if (!isNaN(date.getTime())) return dateStr;
  }

  // Try standard parsing
  const date = new Date(dateStr);
  if (!isNaN(date.getTime())) {
    return date.toISOString().split('T')[0];
  }

  // Try MM/DD/YYYY format
  const mdyMatch = dateStr.match(/(\d{1,2})\/(\d{1,2})\/(\d{4})/);
  if (mdyMatch) {
    const [, month, day, year] = mdyMatch;
    const parsed = new Date(parseInt(year), parseInt(month) - 1, parseInt(day));
    if (!isNaN(parsed.getTime())) {
      return parsed.toISOString().split('T')[0];
    }
  }

  return undefined;
}

/** Parse numeric value */
function parseNumber(value: string | number | null): number | undefined {
  if (value === null || value === undefined) return undefined;
  if (typeof value === 'number') return value;

  const cleaned = value.replace(/[$,\s]/g, '');
  const num = parseFloat(cleaned);
  return isNaN(num) ? undefined : num;
}

/** Extract maintenance receipt data from image via OCR service */
async function extractMaintenanceReceiptFromImage(file: File): Promise<{
  extractedFields: ExtractedMaintenanceReceiptFields;
  rawText: string;
  confidence: number;
}> {
  const formData = new FormData();
  formData.append('file', file);

  const response = await apiClient.post('/ocr/extract/maintenance-receipt', formData, {
    headers: { 'Content-Type': 'multipart/form-data' },
    timeout: 30000,
  });

  const data = response.data;

  if (!data.success) {
    throw new Error('Maintenance receipt OCR extraction failed');
  }

  const fields = data.extractedFields || {};

  const makeField = (key: string): ExtractedMaintenanceField => ({
    value: fields[key]?.value ?? null,
    confidence: fields[key]?.confidence ?? 0,
  });

  const extractedFields: ExtractedMaintenanceReceiptFields = {
    serviceName: makeField('serviceName'),
    serviceDate: makeField('serviceDate'),
    totalCost: makeField('totalCost'),
    shopName: makeField('shopName'),
    laborCost: makeField('laborCost'),
    partsCost: makeField('partsCost'),
    odometerReading: makeField('odometerReading'),
    vehicleInfo: makeField('vehicleInfo'),
  };

  return {
    extractedFields,
    rawText: data.rawText || '',
    confidence: data.confidence || 0,
  };
}

/** Map extracted fields to maintenance record form fields */
function mapFieldsToMaintenanceRecord(
  fields: ExtractedMaintenanceReceiptFields,
  categorySuggestion: CategorySuggestion | null
): MappedMaintenanceFields {
  // Build notes from supplementary fields
  const noteParts: string[] = [];
  if (fields.laborCost.value !== null) {
    noteParts.push(`Labor: $${parseNumber(fields.laborCost.value)?.toFixed(2) ?? fields.laborCost.value}`);
  }
  if (fields.partsCost.value !== null) {
    noteParts.push(`Parts: $${parseNumber(fields.partsCost.value)?.toFixed(2) ?? fields.partsCost.value}`);
  }
  if (fields.vehicleInfo.value !== null) {
    noteParts.push(`Vehicle: ${fields.vehicleInfo.value}`);
  }

  return {
    date: parseServiceDate(fields.serviceDate.value),
    cost: parseNumber(fields.totalCost.value),
    shopName: fields.shopName.value ? String(fields.shopName.value) : undefined,
    odometerReading: parseNumber(fields.odometerReading.value),
    category: categorySuggestion?.category,
    subtypes: categorySuggestion?.subtypes,
    notes: noteParts.length > 0 ? noteParts.join(' | ') : undefined,
  };
}

/**
 * Hook to orchestrate maintenance receipt photo capture and OCR extraction.
 * Mirrors useReceiptOcr pattern: startCapture -> processImage -> review -> acceptResult
 */
export function useMaintenanceReceiptOcr(): UseMaintenanceReceiptOcrReturn {
  const [isCapturing, setIsCapturing] = useState(false);
  const [isProcessing, setIsProcessing] = useState(false);
  const [result, setResult] = useState<MaintenanceReceiptOcrResult | null>(null);
  const [receiptImageUrl, setReceiptImageUrl] = useState<string | null>(null);
  const [error, setError] = useState<string | null>(null);

  const startCapture = useCallback(() => {
    setIsCapturing(true);
    setError(null);
    setResult(null);
  }, []);

  const cancelCapture = useCallback(() => {
    setIsCapturing(false);
    setError(null);
  }, []);

  const processImage = useCallback(async (file: File, croppedFile?: File) => {
    setIsCapturing(false);
    setIsProcessing(true);
    setError(null);
    setResult(null);

    const imageToProcess = croppedFile || file;
    const isPdf = imageToProcess.type === 'application/pdf' ||
      imageToProcess.name.toLowerCase().endsWith('.pdf');
    const imageUrl = isPdf ? null : URL.createObjectURL(imageToProcess);
    setReceiptImageUrl(imageUrl);

    try {
      const { extractedFields, rawText, confidence } = await extractMaintenanceReceiptFromImage(imageToProcess);

      const categorySuggestion = suggestCategory(extractedFields.serviceName.value);
      const mappedFields = mapFieldsToMaintenanceRecord(extractedFields, categorySuggestion);

      setResult({
        extractedFields,
        mappedFields,
        categorySuggestion,
        rawText,
        overallConfidence: confidence,
      });
    } catch (err: any) {
      console.error('Maintenance receipt OCR processing failed:', err);
      const message = err.response?.data?.message || err.message || 'Failed to process maintenance receipt image';
      setError(message);
      if (imageUrl) URL.revokeObjectURL(imageUrl);
      setReceiptImageUrl(null);
    } finally {
      setIsProcessing(false);
    }
  }, []);

  const updateField = useCallback((
    fieldName: keyof ExtractedMaintenanceReceiptFields,
    value: string | number | null
  ) => {
    setResult((prev) => {
      if (!prev) return null;

      const updatedFields = {
        ...prev.extractedFields,
        [fieldName]: {
          ...prev.extractedFields[fieldName],
          value,
          confidence: 1.0, // User-edited field has full confidence
        },
      };

      // Re-run category suggestion if service name was edited
      const categorySuggestion = fieldName === 'serviceName'
        ? suggestCategory(value)
        : prev.categorySuggestion;

      return {
        ...prev,
        extractedFields: updatedFields,
        categorySuggestion,
        mappedFields: mapFieldsToMaintenanceRecord(updatedFields, categorySuggestion),
      };
    });
  }, []);

  const acceptResult = useCallback(() => {
    if (!result) return null;

    const mappedFields = result.mappedFields;

    if (receiptImageUrl) {
      URL.revokeObjectURL(receiptImageUrl);
    }
    setResult(null);
    setReceiptImageUrl(null);

    return mappedFields;
  }, [result, receiptImageUrl]);

  const reset = useCallback(() => {
    setIsCapturing(false);
    setIsProcessing(false);
    if (receiptImageUrl) {
      URL.revokeObjectURL(receiptImageUrl);
    }
    setResult(null);
    setReceiptImageUrl(null);
    setError(null);
  }, [receiptImageUrl]);

  return {
    isCapturing,
    isProcessing,
    result,
    receiptImageUrl,
    error,
    startCapture,
    cancelCapture,
    processImage,
    acceptResult,
    reset,
    updateField,
  };
}
