/**
 * QR Data Validator
 * Zod schemas for validating QR calculator data
 */

import { z } from 'zod';
import { QRCalculatorData, QRValidationResult } from '../types';

// Vessel information schema (optional)
const VesselSchema = z.object({
  imo: z.string().optional(),
  name: z.string().optional(),
  type: z.string().optional(),
  enginePower: z.number().positive().optional(),
}).optional();

// Base schema with common fields
const BaseQRDataSchema = z.object({
  calculationType: z.enum(['fuel', 'distance', 'custom']),
  vessel: VesselSchema,
  timestamp: z.string().optional(),
  source: z.string().optional(),
});

// Fuel-based calculation schema
const FuelCalculationSchema = BaseQRDataSchema.extend({
  calculationType: z.literal('fuel'),
  fuelAmount: z.number().positive('Fuel amount must be positive'),
  fuelUnit: z.enum(['liters', 'gallons']),
  // Other fields should not be present for fuel calculation
  distance: z.undefined().optional(),
  speed: z.undefined().optional(),
  fuelRate: z.undefined().optional(),
  customAmount: z.undefined().optional(),
});

// Distance-based calculation schema
const DistanceCalculationSchema = BaseQRDataSchema.extend({
  calculationType: z.literal('distance'),
  distance: z.number().positive('Distance must be positive'),
  speed: z.number().positive('Speed must be positive'),
  fuelRate: z.number().positive('Fuel rate must be positive'),
  // Other fields should not be present for distance calculation
  fuelAmount: z.undefined().optional(),
  fuelUnit: z.undefined().optional(),
  customAmount: z.undefined().optional(),
});

// Custom amount calculation schema
const CustomCalculationSchema = BaseQRDataSchema.extend({
  calculationType: z.literal('custom'),
  customAmount: z.number().positive('Custom amount must be positive'),
  // Other fields should not be present for custom calculation
  distance: z.undefined().optional(),
  speed: z.undefined().optional(),
  fuelRate: z.undefined().optional(),
  fuelAmount: z.undefined().optional(),
  fuelUnit: z.undefined().optional(),
});

// Union schema that validates based on calculationType
const QRCalculatorDataSchema = z.discriminatedUnion('calculationType', [
  FuelCalculationSchema,
  DistanceCalculationSchema,
  CustomCalculationSchema,
]);

/**
 * Validate QR calculator data against schema
 * @param data Data to validate
 * @returns Validation result with success status and errors
 */
export function validateQRData(data: unknown): QRValidationResult {
  try {
    const validated = QRCalculatorDataSchema.parse(data);
    return {
      valid: true,
      data: validated as QRCalculatorData,
    };
  } catch (error) {
    if (error instanceof z.ZodError) {
      const errorMessages = error.issues.map((err) => {
        const path = err.path.join('.');
        return `${path ? path + ': ' : ''}${err.message}`;
      });

      return {
        valid: false,
        error: `Validation failed: ${errorMessages.join(', ')}`,
      };
    }

    return {
      valid: false,
      error: 'Unknown validation error',
    };
  }
}

/**
 * Check if data has required fields for its calculation type
 * @param data QR calculator data
 * @returns True if data has all required fields
 */
export function hasRequiredFields(data: QRCalculatorData): boolean {
  switch (data.calculationType) {
    case 'fuel':
      return !!(data.fuelAmount && data.fuelUnit);
    case 'distance':
      return !!(data.distance && data.speed && data.fuelRate);
    case 'custom':
      return !!data.customAmount;
    default:
      return false;
  }
}

/**
 * Sanitize QR data by removing undefined/null values
 * @param data QR calculator data
 * @returns Cleaned data object
 */
export function sanitizeQRData(data: QRCalculatorData): QRCalculatorData {
  const cleaned: any = {
    calculationType: data.calculationType,
  };

  // Add type-specific fields
  if (data.calculationType === 'fuel' && data.fuelAmount && data.fuelUnit) {
    cleaned.fuelAmount = data.fuelAmount;
    cleaned.fuelUnit = data.fuelUnit;
  } else if (data.calculationType === 'distance' && data.distance && data.speed && data.fuelRate) {
    cleaned.distance = data.distance;
    cleaned.speed = data.speed;
    cleaned.fuelRate = data.fuelRate;
  } else if (data.calculationType === 'custom' && data.customAmount) {
    cleaned.customAmount = data.customAmount;
  }

  // Add optional vessel info if present
  if (data.vessel) {
    cleaned.vessel = {};
    if (data.vessel.imo) cleaned.vessel.imo = data.vessel.imo;
    if (data.vessel.name) cleaned.vessel.name = data.vessel.name;
    if (data.vessel.type) cleaned.vessel.type = data.vessel.type;
    if (data.vessel.enginePower) cleaned.vessel.enginePower = data.vessel.enginePower;
  }

  // Add metadata if present
  if (data.timestamp) cleaned.timestamp = data.timestamp;
  if (data.source) cleaned.source = data.source;

  return cleaned as QRCalculatorData;
}

/**
 * Get human-readable description of QR data
 * @param data QR calculator data
 * @returns String description of the calculation
 */
export function getQRDataDescription(data: QRCalculatorData): string {
  switch (data.calculationType) {
    case 'fuel':
      return `Fuel-based: ${data.fuelAmount} ${data.fuelUnit}`;
    case 'distance':
      return `Distance-based: ${data.distance} nm at ${data.speed} knots`;
    case 'custom':
      return `Custom: $${data.customAmount} USD`;
    default:
      return 'Unknown calculation type';
  }
}
