'use client';

import { useState, useCallback, useRef } from 'react';
import JSZip from 'jszip';
import type { WaypointType } from '@/types';
import {
  parseGoogleMapsGeoJSON,
  formatFileSize,
  type ParsedPlace,
} from '@/lib/googleMapsParser';

interface ImportModalProps {
  onClose: () => void;
  onImport: (places: ImportedPlace[]) => void;
}

export interface ImportedPlace {
  name: string;
  emoji: string;
  latitude: number;
  longitude: number;
  type: WaypointType;
  note?: string;
}

type ImportStep = 'upload' | 'preview' | 'success';

const MAX_FILE_SIZE = 50 * 1024 * 1024; // 50MB for ZIP files

export default function ImportModal({ onClose, onImport }: ImportModalProps) {
  const [step, setStep] = useState<ImportStep>('upload');
  const [error, setError] = useState<string | null>(null);
  const [isDragging, setIsDragging] = useState(false);
  const [isProcessing, setIsProcessing] = useState(false);
  const [parsedPlaces, setParsedPlaces] = useState<ParsedPlace[]>([]);
  const [selectedPlaces, setSelectedPlaces] = useState<Set<number>>(new Set());
  const [importedCount, setImportedCount] = useState(0);
  const fileInputRef = useRef<HTMLInputElement>(null);

  // Find JSON file with saved places in a ZIP
  const findSavedPlacesInZip = async (zip: JSZip): Promise<string | null> => {
    const possibleNames = [
      'Saved Places.json',
      'saved_places.json',
      'SavedPlaces.json',
    ];

    // First, try exact matches in common locations
    for (const name of possibleNames) {
      // Try root level
      if (zip.files[name]) {
        return await zip.files[name].async('string');
      }
      // Try in Takeout/Maps folder
      const takeoutPath = `Takeout/Maps (your places)/${name}`;
      if (zip.files[takeoutPath]) {
        return await zip.files[takeoutPath].async('string');
      }
      const takeoutPath2 = `Takeout/Maps/${name}`;
      if (zip.files[takeoutPath2]) {
        return await zip.files[takeoutPath2].async('string');
      }
    }

    // Search for any .json file that looks like saved places
    for (const [path, file] of Object.entries(zip.files)) {
      if (file.dir) continue;
      if (path.toLowerCase().includes('saved') && path.endsWith('.json')) {
        return await file.async('string');
      }
    }

    // Last resort: find any GeoJSON file
    for (const [path, file] of Object.entries(zip.files)) {
      if (file.dir) continue;
      if (path.endsWith('.json') || path.endsWith('.geojson')) {
        const content = await file.async('string');
        // Check if it's a FeatureCollection (GeoJSON)
        if (content.includes('"FeatureCollection"')) {
          return content;
        }
      }
    }

    return null;
  };

  // Process the uploaded file
  const processFile = useCallback(async (file: File) => {
    setError(null);
    setIsProcessing(true);

    // Validate file size
    if (file.size > MAX_FILE_SIZE) {
      setError(`File too large (${formatFileSize(file.size)}). Maximum size is ${formatFileSize(MAX_FILE_SIZE)}.`);
      setIsProcessing(false);
      return;
    }

    try {
      let jsonContent: string;

      if (file.name.endsWith('.zip')) {
        // Handle ZIP file
        const zip = await JSZip.loadAsync(file);
        const found = await findSavedPlacesInZip(zip);

        if (!found) {
          setError('Could not find saved places in this ZIP. Make sure you exported "Saved" from Google Maps.');
          setIsProcessing(false);
          return;
        }
        jsonContent = found;
      } else if (file.name.endsWith('.json') || file.name.endsWith('.geojson')) {
        // Handle direct JSON file
        jsonContent = await file.text();
      } else {
        setError('Please upload a .zip, .json, or .geojson file.');
        setIsProcessing(false);
        return;
      }

      const result = parseGoogleMapsGeoJSON(jsonContent);

      if (!result.success) {
        setError(result.error || 'Failed to parse file.');
        setIsProcessing(false);
        return;
      }

      setParsedPlaces(result.places);
      setSelectedPlaces(new Set(result.places.map((_, i) => i)));
      setStep('preview');
    } catch (err) {
      console.error('File processing error:', err);
      setError('Failed to read file. Please try again.');
    } finally {
      setIsProcessing(false);
    }
  }, []);

  // Handle file drop
  const handleDrop = useCallback(
    (e: React.DragEvent) => {
      e.preventDefault();
      setIsDragging(false);

      const files = e.dataTransfer.files;
      if (files.length > 0) {
        processFile(files[0]);
      }
    },
    [processFile]
  );

  const handleDragOver = (e: React.DragEvent) => {
    e.preventDefault();
    setIsDragging(true);
  };

  const handleDragLeave = (e: React.DragEvent) => {
    e.preventDefault();
    setIsDragging(false);
  };

  const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const files = e.target.files;
    if (files && files.length > 0) {
      processFile(files[0]);
    }
  };

  const togglePlace = (index: number) => {
    const newSelected = new Set(selectedPlaces);
    if (newSelected.has(index)) {
      newSelected.delete(index);
    } else {
      newSelected.add(index);
    }
    setSelectedPlaces(newSelected);
  };

  const toggleAll = () => {
    if (selectedPlaces.size === parsedPlaces.length) {
      setSelectedPlaces(new Set());
    } else {
      setSelectedPlaces(new Set(parsedPlaces.map((_, i) => i)));
    }
  };

  const handleImport = () => {
    const placesToImport: ImportedPlace[] = [];

    parsedPlaces.forEach((place, index) => {
      if (selectedPlaces.has(index)) {
        placesToImport.push({
          name: place.name,
          emoji: '📍',
          latitude: place.latitude,
          longitude: place.longitude,
          type: 'poi',
          note: place.note,
        });
      }
    });

    if (placesToImport.length > 0) {
      onImport(placesToImport);
      setImportedCount(placesToImport.length);
      setStep('success');
    }
  };

  const handleBack = () => {
    setStep('upload');
    setParsedPlaces([]);
    setSelectedPlaces(new Set());
    setError(null);
    if (fileInputRef.current) {
      fileInputRef.current.value = '';
    }
  };

  return (
    <div className="fixed inset-0 bg-black/60 backdrop-blur-sm flex items-center justify-center p-4 z-50">
      <div className="room-panel rounded-2xl p-6 w-full max-w-md max-h-[90vh] overflow-y-auto">
        {/* Header */}
        <div className="flex items-center justify-between mb-4">
          <h2 className="text-xl font-bold">Import from Google Maps</h2>
          <button
            onClick={onClose}
            className="p-1 rounded hover:bg-white/10 transition-colors"
          >
            <svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
              <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
            </svg>
          </button>
        </div>

        {/* Upload Step */}
        {step === 'upload' && (
          <div className="space-y-4">
            {/* Simple Instructions */}
            <div className="space-y-3">
              <div className="flex items-start gap-3">
                <div className="w-6 h-6 rounded-full bg-rmaps-primary/20 flex items-center justify-center flex-shrink-0 mt-0.5">
                  <span className="text-xs font-bold text-rmaps-primary">1</span>
                </div>
                <div>
                  <a
                    href="https://takeout.google.com/takeout/custom/maps"
                    target="_blank"
                    rel="noopener noreferrer"
                    className="text-rmaps-primary hover:underline font-medium"
                  >
                    Open Google Takeout →
                  </a>
                  <p className="text-white/50 text-sm">Select &quot;Saved Places&quot; and export</p>
                </div>
              </div>

              <div className="flex items-start gap-3">
                <div className="w-6 h-6 rounded-full bg-rmaps-primary/20 flex items-center justify-center flex-shrink-0 mt-0.5">
                  <span className="text-xs font-bold text-rmaps-primary">2</span>
                </div>
                <div>
                  <p className="font-medium">Download the ZIP file</p>
                  <p className="text-white/50 text-sm">Google will email you when ready</p>
                </div>
              </div>

              <div className="flex items-start gap-3">
                <div className="w-6 h-6 rounded-full bg-rmaps-primary/20 flex items-center justify-center flex-shrink-0 mt-0.5">
                  <span className="text-xs font-bold text-rmaps-primary">3</span>
                </div>
                <div>
                  <p className="font-medium">Upload the ZIP here</p>
                  <p className="text-white/50 text-sm">No need to extract it!</p>
                </div>
              </div>
            </div>

            {/* Drop zone */}
            <div
              onDrop={handleDrop}
              onDragOver={handleDragOver}
              onDragLeave={handleDragLeave}
              onClick={() => !isProcessing && fileInputRef.current?.click()}
              className={`border-2 border-dashed rounded-xl p-6 text-center cursor-pointer transition-all ${
                isProcessing
                  ? 'border-white/10 bg-white/5 cursor-wait'
                  : isDragging
                  ? 'border-rmaps-primary bg-rmaps-primary/10'
                  : 'border-white/20 hover:border-white/40 hover:bg-white/5'
              }`}
            >
              <input
                ref={fileInputRef}
                type="file"
                accept=".zip,.json,.geojson"
                onChange={handleFileChange}
                className="hidden"
                disabled={isProcessing}
              />
              {isProcessing ? (
                <>
                  <div className="w-8 h-8 border-2 border-rmaps-primary border-t-transparent rounded-full animate-spin mx-auto mb-2" />
                  <p className="text-white/60">Processing...</p>
                </>
              ) : (
                <>
                  <div className="text-4xl mb-2">📦</div>
                  <p className="text-white/80 font-medium">
                    {isDragging ? 'Drop file here' : 'Drop ZIP or click to upload'}
                  </p>
                  <p className="text-white/40 text-xs mt-1">
                    Accepts .zip, .json, or .geojson
                  </p>
                </>
              )}
            </div>

            {/* Error message */}
            {error && (
              <div className="bg-red-500/20 border border-red-500/40 rounded-lg p-3 text-sm text-red-300">
                {error}
              </div>
            )}

            {/* Cancel button */}
            <button onClick={onClose} className="btn-ghost w-full">
              Cancel
            </button>
          </div>
        )}

        {/* Preview Step */}
        {step === 'preview' && (
          <div className="space-y-4">
            <div className="flex items-center justify-between text-sm">
              <span className="text-white/60">
                Found {parsedPlaces.length} place{parsedPlaces.length !== 1 ? 's' : ''}
              </span>
              <button onClick={toggleAll} className="text-rmaps-primary hover:underline">
                {selectedPlaces.size === parsedPlaces.length ? 'Deselect all' : 'Select all'}
              </button>
            </div>

            <div className="bg-white/5 rounded-lg border border-white/10 max-h-64 overflow-y-auto">
              {parsedPlaces.map((place, index) => (
                <label
                  key={index}
                  className="flex items-center gap-3 p-3 hover:bg-white/5 cursor-pointer border-b border-white/5 last:border-0"
                >
                  <input
                    type="checkbox"
                    checked={selectedPlaces.has(index)}
                    onChange={() => togglePlace(index)}
                    className="w-4 h-4 rounded border-white/20 bg-white/10 text-rmaps-primary focus:ring-rmaps-primary focus:ring-offset-0"
                  />
                  <div className="flex-1 min-w-0">
                    <div className="font-medium truncate">{place.name}</div>
                    <div className="text-xs text-white/40">
                      {place.latitude.toFixed(4)}, {place.longitude.toFixed(4)}
                    </div>
                  </div>
                  <span className="text-xl">📍</span>
                </label>
              ))}
            </div>

            <div className="text-sm text-white/60 text-center">
              {selectedPlaces.size} of {parsedPlaces.length} selected
            </div>

            <div className="flex gap-3">
              <button onClick={handleBack} className="btn-ghost flex-1">
                Back
              </button>
              <button
                onClick={handleImport}
                disabled={selectedPlaces.size === 0}
                className="btn-primary flex-1 disabled:opacity-50 disabled:cursor-not-allowed"
              >
                Import {selectedPlaces.size > 0 ? `(${selectedPlaces.size})` : ''}
              </button>
            </div>
          </div>
        )}

        {/* Success Step */}
        {step === 'success' && (
          <div className="space-y-4 text-center">
            <div className="text-6xl">🎉</div>
            <div>
              <p className="text-lg font-medium">Import Complete!</p>
              <p className="text-white/60">
                Added {importedCount} place{importedCount !== 1 ? 's' : ''} to the map
              </p>
            </div>
            <button onClick={onClose} className="btn-primary w-full">
              Done
            </button>
          </div>
        )}
      </div>
    </div>
  );
}
