import React, { useState, useRef } from 'react';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';

import { Progress } from '@/components/ui/progress';
import { Dialog } from '@/components/ui/dialog';
import { Upload, X, Music, FileAudio } from 'lucide-react';
import { apiClient } from '@/services/api/client';
import { useToast } from '@/hooks/useToast';
import { logger } from '@/utils/logger';
import { parseApiError } from '@/utils/apiErrorHandler';

interface UploadModalProps {
  onUploadComplete?: () => void;
  children?: React.ReactNode;
  isOpen?: boolean;
  onClose?: () => void;
}

export function UploadModal({
  onUploadComplete,
  children,
  isOpen: controlledIsOpen,
  onClose,
}: UploadModalProps) {
  const [internalOpen, setInternalOpen] = useState(false);

  // Use controlled state if provided, otherwise use internal state
  const open = controlledIsOpen !== undefined ? controlledIsOpen : internalOpen;

  const handleClose = () => {
    if (onClose) {
      onClose();
    } else {
      setInternalOpen(false);
    }
  };

  // If children are provided, we need a way to open the dialog
  // But the Custom Dialog doesn't have a Trigger.
  // We might need to wrap children in a div that onclick sets open?
  // Or if used as controlled, parent handles it.
  // If uncontrolled with children, we expect children to contain a button that opens it?
  // Let's assume standard pattern: cloneElement to add onClick?
  // Or just render children and handling opening logic is up to parent if controlled.
  // If we want to support "Trigger" behavior, we need to add a click handler.

  const handleTriggerClick = () => {
    setInternalOpen(true);
  };

  const [uploading, setUploading] = useState(false);
  const [progress, setProgress] = useState(0);
  const [formData, setFormData] = useState({
    title: '',
    artist: '',
    album: '',
  });
  const [selectedFile, setSelectedFile] = useState<File | null>(null);
  const fileInputRef = useRef<HTMLInputElement>(null);
  const { success: showSuccess, error: showError } = useToast();

  const handleFileSelect = (event: React.ChangeEvent<HTMLInputElement>) => {
    const file = event.target.files?.[0];
    if (file) {
      const allowedTypes = [
        'audio/mpeg',
        'audio/mp3',
        'audio/wav',
        'audio/flac',
        'audio/aac',
        'audio/ogg',
      ];
      if (!allowedTypes.includes(file.type)) {
        showError(
          'Invalid file type: Please select an audio file (MP3, WAV, FLAC, AAC, OGG)',
        );
        return;
      }

      const maxSize = 500 * 1024 * 1024; // 500MB
      if (file.size > maxSize) {
        showError('File too large: Please select a file smaller than 500MB');
        return;
      }

      setSelectedFile(file);

      if (!formData.title) {
        const fileName = file.name.replace(/\.[^/.]+$/, '');
        setFormData((prev) => ({ ...prev, title: fileName }));
      }
    }
  };

  const handleInputChange =
    (field: keyof typeof formData) =>
    (event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
      setFormData((prev) => ({ ...prev, [field]: event.target.value }));
    };

  const handleUpload = async () => {
    if (!selectedFile || !formData.title || !formData.artist) {
      showError('Please fill in all required fields and select a file');
      return;
    }

    setUploading(true);
    setProgress(0);

    try {
      const progressInterval = setInterval(() => {
        setProgress((prev) => {
          if (prev >= 90) {
            clearInterval(progressInterval);
            return prev;
          }
          return prev + Math.random() * 10;
        });
      }, 200);

      const formDataToSend = new FormData();
      formDataToSend.append('file', selectedFile);
      formDataToSend.append('title', formData.title);
      formDataToSend.append('artist', formData.artist);
      if (formData.album) {
        formDataToSend.append('album', formData.album);
      }

      const response = await apiClient.post('/tracks', formDataToSend, {
        headers: {
          'Content-Type': 'multipart/form-data',
        },
      });
      const result = response.data;

      clearInterval(progressInterval);
      setProgress(100);

      showSuccess(`Track "${result.title}" uploaded successfully.`);

      // Reset
      setFormData({ title: '', artist: '', album: '' });
      setSelectedFile(null);
      if (fileInputRef.current) fileInputRef.current.value = '';

      handleClose();
      onUploadComplete?.();
    } catch (error: unknown) {
      const apiError = parseApiError(error);
      logger.error('Upload failed:', { message: apiError.message });
      showError(apiError.message);
    } finally {
      setUploading(false);
      setProgress(0);
    }
  };

  const handleCancel = () => {
    if (!uploading) {
      setFormData({ title: '', artist: '', album: '' });
      setSelectedFile(null);
      if (fileInputRef.current) fileInputRef.current.value = '';
      handleClose();
    }
  };

  const formatFileSize = (bytes: number): string => {
    if (bytes === 0) return '0 Bytes';
    const k = 1024;
    const sizes = ['Bytes', 'KB', 'MB', 'GB'];
    const i = Math.floor(Math.log(bytes) / Math.log(k));
    return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`;
  };

  return (
    <>
      {children && (
        <div
          onClick={handleTriggerClick}
          className="inline-block cursor-pointer"
        >
          {children}
        </div>
      )}

      <Dialog
        open={open}
        onClose={handleClose}
        title="Upload New Track"
        variant="default"
        footer={
          <div className="flex justify-end gap-2">
            <Button
              variant="outline"
              onClick={handleCancel}
              disabled={uploading}
            >
              Cancel
            </Button>
            <Button
              onClick={handleUpload}
              disabled={
                uploading ||
                !selectedFile ||
                !formData.title ||
                !formData.artist
              }
            >
              {uploading ? (
                <>
                  <Music className="w-4 h-4 mr-2 animate-spin" />
                  Uploading...
                </>
              ) : (
                <>
                  <Upload className="w-4 h-4 mr-2" />
                  Upload Track
                </>
              )}
            </Button>
          </div>
        }
      >
        <div className="space-y-4">
          <p className="text-sm text-muted-foreground">
            Upload an audio file to add it to your library. Supported formats:
            MP3, WAV, FLAC, AAC, OGG
          </p>

          {/* File Selection */}
          <div className="space-y-2">
            <Label htmlFor="file">Audio File *</Label>
            <div className="flex items-center space-x-2">
              <Input
                ref={fileInputRef}
                id="file"
                type="file"
                accept="audio/*"
                onChange={handleFileSelect}
                disabled={uploading}
                className="flex-1"
              />
              {selectedFile && (
                <Button
                  variant="outline"
                  size="sm"
                  onClick={() => {
                    setSelectedFile(null);
                    if (fileInputRef.current) fileInputRef.current.value = '';
                  }}
                  disabled={uploading}
                >
                  <X className="w-4 h-4" />
                </Button>
              )}
            </div>
            {selectedFile && (
              <div className="flex items-center space-x-2 text-sm text-muted-foreground">
                <FileAudio className="w-4 h-4" />
                <span>{selectedFile.name}</span>
                <span>({formatFileSize(selectedFile.size)})</span>
              </div>
            )}
          </div>

          {/* Track Information */}
          <div className="grid grid-cols-2 gap-4">
            <div className="space-y-2">
              <Label htmlFor="title">Title *</Label>
              <Input
                id="title"
                value={formData.title}
                onChange={handleInputChange('title')}
                placeholder="Track title"
                disabled={uploading}
              />
            </div>
            <div className="space-y-2">
              <Label htmlFor="artist">Artist *</Label>
              <Input
                id="artist"
                value={formData.artist}
                onChange={handleInputChange('artist')}
                placeholder="Artist name"
                disabled={uploading}
              />
            </div>
          </div>

          <div className="space-y-2">
            <Label htmlFor="album">Album</Label>
            <Input
              id="album"
              value={formData.album}
              onChange={handleInputChange('album')}
              placeholder="Album name (optional)"
              disabled={uploading}
            />
          </div>

          {/* Upload Progress */}
          {uploading && (
            <div className="space-y-2">
              <div className="flex items-center justify-between text-sm">
                <span>Uploading...</span>
                <span>{Math.round(progress)}%</span>
              </div>
              <Progress value={progress} className="w-full" />
            </div>
          )}
        </div>
      </Dialog>
    </>
  );
}
