import React, { useState, useCallback, useRef, useEffect } from 'react';
import Cropper from 'react-easy-crop';
import type { Area } from 'react-easy-crop';
import { supabase } from '../lib/supabase';

interface ImageUploadCropperProps {
  currentImageUrl?: string;
  onImageChange: (imageUrl: string | null) => void;
  disabled?: boolean;
}

interface _CropData {
  x: number;
  y: number;
  width: number;
  height: number;
}

const ASPECT_RATIO = 1.91; // 1200x628 recommended
const MIN_CROP_WIDTH = 600;
const MIN_CROP_HEIGHT = 314;
const MAX_FILE_SIZE = 10 * 1024 * 1024; // 10MB before cropping
const MAX_FINAL_SIZE = 2 * 1024 * 1024; // 2MB after cropping
const ACCEPTED_TYPES = ['image/jpeg', 'image/png', 'image/webp'];

const createImage = (url: string): Promise<HTMLImageElement> =>
  new Promise((resolve, reject) => {
    const image = new Image();
    image.addEventListener('load', () => resolve(image));
    image.addEventListener('error', error => reject(error));
    image.setAttribute('crossOrigin', 'anonymous');
    image.src = url;
  });

const getCroppedImg = async (
  imageSrc: string,
  pixelCrop: Area,
  fileName: string
): Promise<{ file: File; dataUrl: string }> => {
  const image = await createImage(imageSrc);
  const canvas = document.createElement('canvas');
  const ctx = canvas.getContext('2d');

  if (!ctx) {
    throw new Error('Could not get canvas context');
  }

  canvas.width = pixelCrop.width;
  canvas.height = pixelCrop.height;

  ctx.drawImage(
    image,
    pixelCrop.x,
    pixelCrop.y,
    pixelCrop.width,
    pixelCrop.height,
    0,
    0,
    pixelCrop.width,
    pixelCrop.height
  );

  return new Promise((resolve, reject) => {
    canvas.toBlob(
      (blob) => {
        if (!blob) {
          reject(new Error('Canvas is empty'));
          return;
        }
        
        const file = new File([blob], fileName, {
          type: 'image/webp',
          lastModified: Date.now(),
        });
        
        const reader = new FileReader();
        reader.onload = () => {
          resolve({
            file,
            dataUrl: reader.result as string
          });
        };
        reader.onerror = reject;
        reader.readAsDataURL(file);
      },
      'image/webp',
      0.85 // Compression quality
    );
  });
};

export default function ImageUploadCropper({ 
  currentImageUrl, 
  onImageChange, 
  disabled = false 
}: ImageUploadCropperProps) {
  const [imageSrc, setImageSrc] = useState<string | null>(null);
  const [crop, setCrop] = useState({ x: 0, y: 0 });
  const [zoom, setZoom] = useState(1);
  const [croppedAreaPixels, setCroppedAreaPixels] = useState<Area | null>(null);
  const [isUploading, setIsUploading] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [showCropper, setShowCropper] = useState(false);
  const [originalFileName, setOriginalFileName] = useState<string>('');
  const fileInputRef = useRef<HTMLInputElement>(null);

  const onCropComplete = useCallback((croppedArea: Area, croppedAreaPixels: Area) => {
    setCroppedAreaPixels(croppedAreaPixels);
  }, []);

  // Handle keyboard shortcuts and scroll locking
  useEffect(() => {
    const handleKeydown = (e: KeyboardEvent) => {
      if (showCropper && e.key === 'Escape' && !isUploading) {
        handleCropCancel();
      }
    };

    if (showCropper) {
      // Lock body scroll when modal is open
      document.body.style.overflow = 'hidden';
      document.addEventListener('keydown', handleKeydown);
      
      return () => {
        // Restore body scroll when modal closes
        document.body.style.overflow = '';
        document.removeEventListener('keydown', handleKeydown);
      };
    }
  }, [showCropper, isUploading]);

  const handleFileSelect = (event: React.ChangeEvent<HTMLInputElement>) => {
    const file = event.target.files?.[0];
    if (!file) return;

    setError(null);

    // Validate file type
    if (!ACCEPTED_TYPES.includes(file.type)) {
      setError('Please select a JPG, PNG, or WebP image');
      return;
    }

    // Validate file size
    if (file.size > MAX_FILE_SIZE) {
      setError('File size must be less than 10MB');
      return;
    }

    setOriginalFileName(file.name);
    const reader = new FileReader();
    reader.onload = () => {
      setImageSrc(reader.result as string);
      setShowCropper(true);
    };
    reader.readAsDataURL(file);
  };

  const handleCropSave = async () => {
    if (!imageSrc || !croppedAreaPixels) {
      setError('Please select a crop area before saving');
      return;
    }

    setIsUploading(true);
    setError(null);

    try {
      // Validate minimum crop dimensions
      if (croppedAreaPixels.width < MIN_CROP_WIDTH || croppedAreaPixels.height < MIN_CROP_HEIGHT) {
        throw new Error(`Crop area too small. Minimum size: ${MIN_CROP_WIDTH}×${MIN_CROP_HEIGHT}px`);
      }

      const { file, dataUrl: _dataUrl } = await getCroppedImg(imageSrc, croppedAreaPixels, originalFileName);
      
      // Validate final file size
      if (file.size > MAX_FINAL_SIZE) {
        throw new Error('Compressed image is too large. Please crop a smaller area or use a different image.');
      }

      // Upload to Supabase Storage
      const formData = new FormData();
      formData.append('file', file);
      
      // Get current session token
      const { data: { session } } = await supabase.auth.getSession();
      
      if (!session?.access_token) {
        throw new Error('Authentication required. Please sign in again.');
      }

      const response = await fetch('/api/upload-event-image', {
        method: 'POST',
        body: formData,
        headers: {
          'Authorization': `Bearer ${session.access_token}`
        }
      });
      
      if (!response.ok) {
        const errorData = await response.json().catch(() => ({ error: 'Upload failed' }));
        throw new Error(errorData.error || `Upload failed with status ${response.status}`);
      }

      const { imageUrl } = await response.json();
      
      onImageChange(imageUrl);
      setShowCropper(false);
      setImageSrc(null);
      setCrop({ x: 0, y: 0 });
      setZoom(1);
      setCroppedAreaPixels(null);
      
    } catch (error) {
      setError(error instanceof Error ? error.message : 'An error occurred');
    } finally {
      setIsUploading(false);
    }
  };

  const handleCropCancel = () => {
    setShowCropper(false);
    setImageSrc(null);
    setError(null);
    setCrop({ x: 0, y: 0 });
    setZoom(1);
    setCroppedAreaPixels(null);
    if (fileInputRef.current) {
      fileInputRef.current.value = '';
    }
  };

  const handleRemoveImage = () => {
    onImageChange(null);
    setError(null);
  };

  return (
    <div className="space-y-4">
      {/* Current Image Preview */}
      {currentImageUrl && !showCropper && (
        <div className="relative group">
          <img
            src={currentImageUrl}
            alt="Event image"
            className="w-full h-32 object-cover rounded-lg"
          />
          <div className="absolute inset-0 bg-black bg-opacity-50 opacity-0 group-hover:opacity-100 transition-opacity rounded-lg flex items-center justify-center">
            <button
              type="button"
              onClick={handleRemoveImage}
              disabled={disabled}
              className="px-3 py-1 bg-red-600 text-white rounded text-sm hover:bg-red-700 disabled:opacity-50"
            >
              Remove
            </button>
          </div>
        </div>
      )}

      {/* File Input */}
      {!currentImageUrl && !showCropper && (
        <div className="border-2 border-dashed border-white/20 rounded-2xl p-6 text-center bg-white/5 hover:bg-white/10 transition-colors duration-200">
          <input
            ref={fileInputRef}
            type="file"
            accept=".jpg,.jpeg,.png,.webp"
            onChange={handleFileSelect}
            disabled={disabled}
            className="hidden"
          />
          <button
            type="button"
            onClick={() => fileInputRef.current?.click()}
            disabled={disabled}
            className="px-6 py-3 bg-gradient-to-r from-blue-600 to-purple-600 hover:from-blue-700 hover:to-purple-700 text-white rounded-xl font-medium transition-all duration-200 shadow-lg hover:shadow-xl disabled:opacity-50"
          >
            Upload Image
          </button>
          <p className="text-sm text-white/60 mt-2">
            JPG, PNG, or WebP • Max 10MB • Recommended: 1200×628px
          </p>
        </div>
      )}

      {/* Replace Image Button */}
      {currentImageUrl && !showCropper && (
        <button
          type="button"
          onClick={() => fileInputRef.current?.click()}
          disabled={disabled}
          className="px-6 py-3 bg-gradient-to-r from-blue-600 to-purple-600 hover:from-blue-700 hover:to-purple-700 text-white rounded-xl font-medium transition-all duration-200 shadow-lg hover:shadow-xl disabled:opacity-50"
        >
          Replace Image
        </button>
      )}

      {/* Cropper Modal */}
      {showCropper && (
        <div className="fixed inset-0 bg-black/90 backdrop-blur-xl flex items-center justify-center z-50">
          <div className="bg-gradient-to-br from-indigo-900/90 via-purple-900/90 to-slate-900/90 backdrop-blur-xl border border-white/20 rounded-3xl p-6 max-w-4xl w-full mx-4 max-h-[90vh] overflow-y-auto shadow-2xl">
            <div className="flex justify-between items-center mb-4">
              <h3 className="text-lg font-semibold text-white">Crop Your Image</h3>
              <button
                type="button"
                onClick={handleCropCancel}
                disabled={isUploading}
                className="text-gray-400 hover:text-white transition-colors disabled:opacity-50"
                aria-label="Close dialog"
              >
                <svg className="w-6 h-6" 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>
            
            <div className="relative h-96 bg-black/50 rounded-2xl overflow-hidden border border-white/10">
              {imageSrc && (
                <Cropper
                  image={imageSrc}
                  crop={crop}
                  zoom={zoom}
                  aspect={ASPECT_RATIO}
                  onCropChange={setCrop}
                  onZoomChange={setZoom}
                  onCropComplete={onCropComplete}
                  cropShape="rect"
                  showGrid={true}
                />
              )}
            </div>

            {/* Zoom Control */}
            <div className="mt-4">
              <label className="block text-sm font-medium mb-2 text-white/90">Zoom</label>
              <input
                type="range"
                min={1}
                max={3}
                step={0.1}
                value={zoom}
                onChange={(e) => setZoom(Number(e.target.value))}
                className="w-full h-2 bg-white/20 rounded-lg appearance-none cursor-pointer slider-thumb"
                disabled={isUploading}
              />
            </div>

            {/* Action Buttons */}
            <div className="flex justify-between mt-6">
              <button
                type="button"
                onClick={handleCropCancel}
                disabled={isUploading}
                className="px-6 py-3 border border-white/20 text-white/80 rounded-xl hover:bg-white/5 font-medium transition-all duration-200 disabled:opacity-50"
              >
                Cancel
              </button>
              <button
                type="button"
                onClick={handleCropSave}
                disabled={isUploading || !croppedAreaPixels}
                className="px-8 py-3 bg-gradient-to-r from-blue-600 to-purple-600 hover:from-blue-700 hover:to-purple-700 text-white rounded-xl font-medium transition-all duration-200 shadow-lg hover:shadow-xl disabled:opacity-50"
              >
                {isUploading ? 'Uploading...' : 'Save & Upload'}
              </button>
            </div>
          </div>
        </div>
      )}

      {/* Error Message */}
      {error && (
        <div className="bg-red-500/10 border border-red-400/20 text-red-400 px-4 py-3 rounded-xl">
          {error}
        </div>
      )}

      {/* Hidden file input for replace functionality */}
      <input
        ref={fileInputRef}
        type="file"
        accept=".jpg,.jpeg,.png,.webp"
        onChange={handleFileSelect}
        disabled={disabled}
        className="hidden"
      />
    </div>
  );
}