/**
 * Diagnostic Service
 * Mecánicas Diesel - ERP Suite
 *
 * Business logic for vehicle diagnostics.
 */

import { Repository, DataSource } from 'typeorm';
import {
  Diagnostic,
  DiagnosticType,
  DiagnosticResult,
} from '../entities/diagnostic.entity';

// DTOs
export interface CreateDiagnosticDto {
  vehicleId: string;
  orderId?: string;
  diagnosticType: DiagnosticType;
  equipment?: string;
  performedBy?: string;
  summary?: string;
  rawData?: Record<string, unknown>;
}

export interface DiagnosticItemDto {
  itemType: 'dtc_code' | 'test_result' | 'measurement' | 'observation';
  code?: string;
  description?: string;
  severity?: 'critical' | 'warning' | 'info';
  parameter?: string;
  value?: number;
  unit?: string;
  minRef?: number;
  maxRef?: number;
  status?: 'ok' | 'warning' | 'fail' | 'no_reference';
  component?: string;
  cylinder?: number;
  notes?: string;
}

export interface DiagnosticRecommendationDto {
  description: string;
  priority: 'critical' | 'high' | 'medium' | 'low';
  urgency: 'immediate' | 'soon' | 'scheduled' | 'preventive';
  suggestedServiceId?: string;
  estimatedCost?: number;
  notes?: string;
}

export class DiagnosticService {
  private diagnosticRepository: Repository<Diagnostic>;

  constructor(private dataSource: DataSource) {
    this.diagnosticRepository = dataSource.getRepository(Diagnostic);
  }

  /**
   * Create a new diagnostic
   */
  async create(tenantId: string, dto: CreateDiagnosticDto): Promise<Diagnostic> {
    const diagnostic = this.diagnosticRepository.create({
      tenantId,
      vehicleId: dto.vehicleId,
      orderId: dto.orderId,
      diagnosticType: dto.diagnosticType,
      equipment: dto.equipment,
      performedBy: dto.performedBy,
      summary: dto.summary,
      rawData: dto.rawData,
      performedAt: new Date(),
    });

    return this.diagnosticRepository.save(diagnostic);
  }

  /**
   * Find diagnostic by ID
   */
  async findById(tenantId: string, id: string): Promise<Diagnostic | null> {
    return this.diagnosticRepository.findOne({
      where: { id, tenantId },
    });
  }

  /**
   * Find diagnostics by vehicle
   */
  async findByVehicle(tenantId: string, vehicleId: string): Promise<Diagnostic[]> {
    return this.diagnosticRepository.find({
      where: { tenantId, vehicleId },
      order: { performedAt: 'DESC' },
    });
  }

  /**
   * Find diagnostics by order
   */
  async findByOrder(tenantId: string, orderId: string): Promise<Diagnostic[]> {
    return this.diagnosticRepository.find({
      where: { tenantId, orderId },
      order: { performedAt: 'DESC' },
    });
  }

  /**
   * Update diagnostic result
   */
  async updateResult(
    tenantId: string,
    id: string,
    result: DiagnosticResult,
    summary?: string
  ): Promise<Diagnostic | null> {
    const diagnostic = await this.findById(tenantId, id);
    if (!diagnostic) return null;

    diagnostic.result = result;
    if (summary) diagnostic.summary = summary;

    return this.diagnosticRepository.save(diagnostic);
  }

  /**
   * Get diagnostic statistics for a vehicle
   */
  async getVehicleStats(tenantId: string, vehicleId: string): Promise<{
    totalDiagnostics: number;
    lastDiagnosticDate: Date | null;
    diagnosticsByType: Record<DiagnosticType, number>;
    issuesFound: number;
  }> {
    const diagnostics = await this.findByVehicle(tenantId, vehicleId);

    const diagnosticsByType: Record<DiagnosticType, number> = {
      [DiagnosticType.SCANNER]: 0,
      [DiagnosticType.INJECTOR_TEST]: 0,
      [DiagnosticType.PUMP_TEST]: 0,
      [DiagnosticType.COMPRESSION]: 0,
      [DiagnosticType.TURBO_TEST]: 0,
      [DiagnosticType.OTHER]: 0,
    };

    let issuesFound = 0;

    for (const diag of diagnostics) {
      diagnosticsByType[diag.diagnosticType]++;
      if (diag.result === DiagnosticResult.FAIL || diag.result === DiagnosticResult.NEEDS_ATTENTION) {
        issuesFound++;
      }
    }

    return {
      totalDiagnostics: diagnostics.length,
      lastDiagnosticDate: diagnostics.length > 0 ? diagnostics[0].performedAt : null,
      diagnosticsByType,
      issuesFound,
    };
  }

  /**
   * Parse DTC codes from scanner data
   */
  parseDTCCodes(rawData: Record<string, unknown>): DiagnosticItemDto[] {
    const items: DiagnosticItemDto[] = [];

    // Handle common scanner data formats
    const dtcCodes = rawData.dtc_codes || rawData.codes || rawData.faults || [];

    if (Array.isArray(dtcCodes)) {
      for (const code of dtcCodes) {
        if (typeof code === 'string') {
          items.push({
            itemType: 'dtc_code',
            code,
            description: this.getDTCDescription(code),
            severity: this.getDTCSeverity(code),
          });
        } else if (typeof code === 'object' && code !== null) {
          items.push({
            itemType: 'dtc_code',
            code: code.code || code.id,
            description: code.description || code.message || this.getDTCDescription(code.code),
            severity: code.severity || this.getDTCSeverity(code.code),
          });
        }
      }
    }

    return items;
  }

  /**
   * Get DTC code description (simplified lookup)
   */
  private getDTCDescription(code: string): string {
    // Common diesel DTC codes
    const descriptions: Record<string, string> = {
      'P0087': 'Fuel Rail/System Pressure - Too Low',
      'P0088': 'Fuel Rail/System Pressure - Too High',
      'P0093': 'Fuel System Leak Detected - Large Leak',
      'P0100': 'Mass Air Flow Circuit Malfunction',
      'P0101': 'Mass Air Flow Circuit Range/Performance',
      'P0102': 'Mass Air Flow Circuit Low',
      'P0103': 'Mass Air Flow Circuit High',
      'P0201': 'Injector Circuit/Open - Cylinder 1',
      'P0202': 'Injector Circuit/Open - Cylinder 2',
      'P0203': 'Injector Circuit/Open - Cylinder 3',
      'P0204': 'Injector Circuit/Open - Cylinder 4',
      'P0205': 'Injector Circuit/Open - Cylinder 5',
      'P0206': 'Injector Circuit/Open - Cylinder 6',
      'P0234': 'Turbocharger/Supercharger Overboost Condition',
      'P0299': 'Turbocharger/Supercharger Underboost',
      'P0401': 'Exhaust Gas Recirculation Flow Insufficient',
      'P0402': 'Exhaust Gas Recirculation Flow Excessive',
      'P0404': 'Exhaust Gas Recirculation Circuit Range/Performance',
      'P0405': 'Exhaust Gas Recirculation Sensor A Circuit Low',
      'P2002': 'Diesel Particulate Filter Efficiency Below Threshold',
      'P2003': 'Diesel Particulate Filter Efficiency Below Threshold Bank 2',
      'P242F': 'Diesel Particulate Filter Restriction - Ash Accumulation',
    };

    return descriptions[code] || `Unknown code: ${code}`;
  }

  /**
   * Determine DTC severity
   */
  private getDTCSeverity(code: string): 'critical' | 'warning' | 'info' {
    // P0xxx codes starting with certain numbers are more critical
    if (code.startsWith('P0087') || code.startsWith('P0088') || code.startsWith('P0093')) {
      return 'critical'; // Fuel system issues
    }
    if (code.startsWith('P02')) {
      return 'critical'; // Injector issues
    }
    if (code.startsWith('P0234') || code.startsWith('P0299')) {
      return 'warning'; // Turbo issues
    }
    if (code.startsWith('P04')) {
      return 'warning'; // EGR issues
    }
    if (code.startsWith('P2')) {
      return 'warning'; // DPF issues
    }

    return 'info';
  }

  /**
   * Analyze injector test results
   */
  analyzeInjectorTest(rawData: Record<string, unknown>): DiagnosticItemDto[] {
    const items: DiagnosticItemDto[] = [];
    const injectors = rawData.injectors || rawData.cylinders || [];

    if (Array.isArray(injectors)) {
      for (let i = 0; i < injectors.length; i++) {
        const injector = injectors[i];
        if (typeof injector === 'object' && injector !== null) {
          // Return quantity test
          if (injector.return_qty !== undefined) {
            items.push({
              itemType: 'measurement',
              parameter: 'Return Quantity',
              value: injector.return_qty,
              unit: 'ml/min',
              minRef: 0,
              maxRef: 50, // Typical max for healthy injector
              status: injector.return_qty > 50 ? 'fail' : 'ok',
              cylinder: i + 1,
            });
          }

          // Spray pattern
          if (injector.spray_pattern !== undefined) {
            items.push({
              itemType: 'observation',
              description: `Spray pattern: ${injector.spray_pattern}`,
              status: injector.spray_pattern === 'good' ? 'ok' : 'warning',
              cylinder: i + 1,
            });
          }
        }
      }
    }

    return items;
  }
}
