import { Plus, Trash2 } from "lucide-react";
import { useState } from "react";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Card } from "@/components/ui/card";
import { useUnitPreferences } from "@/hooks/useUnitPreferences";
import { toast } from "sonner";
import { 
  convertValueToMetric, 
  convertValueFromMetric, 
  detectUnitType,
  getMetricUnit,
  getDisplayUnit
} from "@/lib/units";
import { validateMetricUnit, METRIC_UNITS } from "@/lib/unitValidation";
import { getErrorMessage } from "@/lib/errorHandler";

interface TechnicalSpec {
  spec_name: string;
  spec_value: string;
  spec_type: 'string' | 'number' | 'boolean' | 'date';
  category?: string;
  unit?: string;
  display_order: number;
}

interface TechnicalSpecsEditorProps {
  specs: TechnicalSpec[];
  onChange: (specs: TechnicalSpec[]) => void;
  categories?: string[];
  commonSpecs?: string[];
}

const DEFAULT_CATEGORIES = ['Performance', 'Safety', 'Design', 'Capacity', 'Technical', 'Other'];

export function TechnicalSpecsEditor({ 
  specs, 
  onChange, 
  categories = DEFAULT_CATEGORIES,
  commonSpecs = []
}: TechnicalSpecsEditorProps) {
  const { preferences } = useUnitPreferences();
  const [unitErrors, setUnitErrors] = useState<Record<number, string>>({});
  
  const addSpec = () => {
    onChange([
      ...specs,
      {
        spec_name: '',
        spec_value: '',
        spec_type: 'string',
        category: categories[0],
        unit: '',
        display_order: specs.length
      }
    ]);
  };

  const removeSpec = (index: number) => {
    const newSpecs = specs.filter((_, i) => i !== index);
    // Reorder display_order
    onChange(newSpecs.map((spec, i) => ({ ...spec, display_order: i })));
  };

  const updateSpec = (index: number, field: keyof TechnicalSpec, value: string | number | boolean | null | undefined) => {
    const newSpecs = [...specs];
    
    // Ensure unit is metric when updating unit field
    if (field === 'unit' && value && typeof value === 'string') {
      try {
        validateMetricUnit(value, 'Unit');
        newSpecs[index] = { ...newSpecs[index], unit: value };
        // Clear error for this index
        setUnitErrors(prev => {
          const updated = { ...prev };
          delete updated[index];
          return updated;
        });
      } catch (error: unknown) {
        const message = getErrorMessage(error);
        toast.error(message);
        // Store error for visual feedback
        setUnitErrors(prev => ({ ...prev, [index]: message }));
        return;
      }
    } else {
      newSpecs[index] = { ...newSpecs[index], [field]: value };
    }
    
    onChange(newSpecs);
  };

  // Get display value (convert from metric to user's preferred units)
  const getDisplayValue = (spec: TechnicalSpec): string => {
    if (!spec.spec_value || !spec.unit || spec.spec_type !== 'number') return spec.spec_value;
    
    const numValue = parseFloat(spec.spec_value);
    if (isNaN(numValue)) return spec.spec_value;
    
    const unitType = detectUnitType(spec.unit);
    if (unitType === 'unknown') return spec.spec_value;
    
    // spec.unit is the metric unit (e.g., "km/h")
    // Get the display unit based on user preference (e.g., "mph" for imperial)
    const displayUnit = getDisplayUnit(spec.unit, preferences.measurement_system);
    
    // Convert from metric to display unit
    const displayValue = convertValueFromMetric(numValue, displayUnit, spec.unit);
    
    return String(displayValue);
  };

  const moveSpec = (index: number, direction: 'up' | 'down') => {
    if ((direction === 'up' && index === 0) || (direction === 'down' && index === specs.length - 1)) {
      return;
    }
    const newSpecs = [...specs];
    const swapIndex = direction === 'up' ? index - 1 : index + 1;
    [newSpecs[index], newSpecs[swapIndex]] = [newSpecs[swapIndex], newSpecs[index]];
    // Update display_order
    newSpecs[index].display_order = index;
    newSpecs[swapIndex].display_order = swapIndex;
    onChange(newSpecs);
  };

  return (
    <div className="space-y-4">
      <div className="flex items-center justify-between">
        <Label>Technical Specifications</Label>
        <Button type="button" variant="outline" size="sm" onClick={addSpec}>
          <Plus className="h-4 w-4 mr-2" />
          Add Specification
        </Button>
      </div>

      {specs.length === 0 ? (
        <Card className="p-6 text-center text-muted-foreground">
          No specifications added yet. Click "Add Specification" to get started.
        </Card>
      ) : (
        <div className="space-y-3">
          {specs.map((spec, index) => (
            <Card key={index} className="p-4">
              <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-6 gap-3">
                <div className="lg:col-span-2">
                  <Label className="text-xs">Specification Name</Label>
                  <Input
                    value={spec.spec_name}
                    onChange={(e) => updateSpec(index, 'spec_name', e.target.value)}
                    placeholder="e.g., Track Material"
                    list={`common-specs-${index}`}
                  />
                  {commonSpecs.length > 0 && (
                    <datalist id={`common-specs-${index}`}>
                      {commonSpecs.map(s => <option key={s} value={s} />)}
                    </datalist>
                  )}
                </div>

                <div>
                  <Label className="text-xs">Value</Label>
                  <Input
                    value={getDisplayValue(spec)}
                    onChange={(e) => {
                      const inputValue = e.target.value;
                      const numValue = parseFloat(inputValue);
                      
                      // If type is number and unit is recognized, convert to metric for storage
                      if (spec.spec_type === 'number' && spec.unit && !isNaN(numValue)) {
                        // Determine what unit the user is entering (based on their preference)
                        const displayUnit = getDisplayUnit(spec.unit, preferences.measurement_system);
                        // Convert from user's input unit to metric for storage
                        const metricValue = convertValueToMetric(numValue, displayUnit);
                        updateSpec(index, 'spec_value', String(metricValue));
                      } else {
                        updateSpec(index, 'spec_value', inputValue);
                      }
                    }}
                    placeholder="Value"
                    type={spec.spec_type === 'number' ? 'number' : 'text'}
                  />
                  {spec.spec_type === 'number' && spec.unit && detectUnitType(spec.unit) !== 'unknown' && (
                    <p className="text-xs text-muted-foreground mt-1">
                      Enter in {getDisplayUnit(spec.unit, preferences.measurement_system)}
                    </p>
                  )}
                </div>

                <div>
                  <Label className="text-xs">Type</Label>
                  <Select
                    value={spec.spec_type}
                    onValueChange={(value) => updateSpec(index, 'spec_type', value)}
                  >
                    <SelectTrigger>
                      <SelectValue />
                    </SelectTrigger>
                    <SelectContent>
                      <SelectItem value="string">Text</SelectItem>
                      <SelectItem value="number">Number</SelectItem>
                      <SelectItem value="boolean">Yes/No</SelectItem>
                      <SelectItem value="date">Date</SelectItem>
                    </SelectContent>
                  </Select>
                </div>

                <div>
                  <Label className="text-xs">Category</Label>
                  <Select
                    value={spec.category || ''}
                    onValueChange={(value) => updateSpec(index, 'category', value)}
                  >
                    <SelectTrigger>
                      <SelectValue placeholder="Select" />
                    </SelectTrigger>
                    <SelectContent>
                      {categories.map(cat => (
                        <SelectItem key={cat} value={cat}>{cat}</SelectItem>
                      ))}
                    </SelectContent>
                  </Select>
                </div>

                <div className="flex items-end gap-2">
                  <div className="flex-1">
                    <Label className="text-xs">Unit</Label>
                    <Input
                      value={spec.unit || ''}
                      onChange={(e) => updateSpec(index, 'unit', e.target.value)}
                      placeholder="Unit"
                      list={`units-${index}`}
                      className={unitErrors[index] ? 'border-destructive' : ''}
                    />
                    <datalist id={`units-${index}`}>
                      {METRIC_UNITS.map(u => <option key={u} value={u} />)}
                    </datalist>
                    {unitErrors[index] && (
                      <p className="text-xs text-destructive mt-1">{unitErrors[index]}</p>
                    )}
                    <p className="text-xs text-muted-foreground mt-1">
                      ⚠️ Metric units only
                    </p>
                  </div>
                  <Button
                    type="button"
                    variant="ghost"
                    size="sm"
                    onClick={() => removeSpec(index)}
                  >
                    <Trash2 className="h-4 w-4 text-destructive" />
                  </Button>
                </div>
              </div>
            </Card>
          ))}
        </div>
      )}
    </div>
  );
}

/**
 * Validates technical specs before submission
 */
export function validateTechnicalSpecs(specs: TechnicalSpec[]): { valid: boolean; errors: string[] } {
  const errors: string[] = [];
  
  specs.forEach((spec, index) => {
    if (!spec.spec_name?.trim()) {
      errors.push(`Spec ${index + 1}: Name is required`);
    }
    if (!spec.spec_value?.trim()) {
      errors.push(`Spec ${index + 1} (${spec.spec_name}): Value is required`);
    }
    if (spec.unit) {
      try {
        validateMetricUnit(spec.unit, `Spec ${index + 1} (${spec.spec_name})`);
      } catch (error: unknown) {
        errors.push(getErrorMessage(error));
      }
    }
  });
  
  return { valid: errors.length === 0, errors };
}
