'use client';

import AwsS3 from '@uppy/aws-s3';
import Uppy from '@uppy/core';
import clsx from 'clsx';
import { DragEvent, useCallback, useEffect, useRef, useState } from 'react';
import { twMerge } from 'tailwind-merge';

import { StarIcon } from '@/icons';
import { useApiClient } from '@/lib/apiClient';

interface CleffyModalProps {
  className?: string;
  initiallyExpanded?: boolean;
}

interface UploadedFile {
  file: File;
  type: 'audio' | 'text';
  uploadId?: string;
  uploading?: boolean;
  error?: string;
  textContent?: string;
}

const CleffyModal: React.FC<CleffyModalProps> = ({
  className,
  initiallyExpanded = false,
}) => {
  const apiClient = useApiClient();
  const [isExpanded, setIsExpanded] = useState(initiallyExpanded);
  const [isDragging, setIsDragging] = useState(false);
  const [uploadedFiles, setUploadedFiles] = useState<UploadedFile[]>([]);
  const [isProcessing, setIsProcessing] = useState(false);
  const [statusMessage, setStatusMessage] = useState<string>('');
  const uppyInstanceRef = useRef<Uppy | null>(null);

  // Initialize and cleanup Uppy
  useEffect(() => {
    return () => {
      if (uppyInstanceRef.current) {
        uppyInstanceRef.current.close();
      }
    };
  }, []);

  const toggleExpanded = () => {
    setIsExpanded(!isExpanded);
  };

  const isAudioFile = (file: File) => {
    return (
      file.type.startsWith('audio/') ||
      file.name.endsWith('.mp3') ||
      file.name.endsWith('.wav')
    );
  };

  const isTextFile = (file: File) => {
    return (
      file.type.startsWith('text/') ||
      file.name.endsWith('.txt') ||
      file.name.endsWith('.md') ||
      file.name.endsWith('.note')
    );
  };

  const handleDragEnter = useCallback((e: DragEvent<HTMLDivElement>) => {
    e.preventDefault();
    e.stopPropagation();
    setIsDragging(true);
  }, []);

  const handleDragLeave = useCallback((e: DragEvent<HTMLDivElement>) => {
    e.preventDefault();
    e.stopPropagation();
    setIsDragging(false);
  }, []);

  const handleDragOver = useCallback((e: DragEvent<HTMLDivElement>) => {
    e.preventDefault();
    e.stopPropagation();
  }, []);

  const handleDrop = useCallback((e: DragEvent<HTMLDivElement>) => {
    e.preventDefault();
    e.stopPropagation();
    setIsDragging(false);

    const files = Array.from(e.dataTransfer.files);
    const newFiles: UploadedFile[] = [];

    files.forEach((file) => {
      if (isAudioFile(file)) {
        newFiles.push({ file, type: 'audio' });
      } else if (isTextFile(file)) {
        newFiles.push({ file, type: 'text' });
      }
    });

    setUploadedFiles((prev) => [...prev, ...newFiles]);
  }, []);

  const handleFileInputChange = useCallback(
    (e: React.ChangeEvent<HTMLInputElement>) => {
      const files = Array.from(e.target.files || []);
      const newFiles: UploadedFile[] = [];

      files.forEach((file) => {
        if (isAudioFile(file)) {
          newFiles.push({ file, type: 'audio' });
        } else if (isTextFile(file)) {
          newFiles.push({ file, type: 'text' });
        }
      });

      setUploadedFiles((prev) => [...prev, ...newFiles]);
    },
    []
  );

  const removeFile = useCallback((index: number) => {
    setUploadedFiles((prev) => prev.filter((_, i) => i !== index));
  }, []);

  const pollUploadStatus = useCallback(
    async (uploadId: string, retries = 75): Promise<void> => {
      const { data } = await apiClient.GET('/api/uploads/audio/{upload_id}/', {
        params: { path: { upload_id: uploadId } },
      });

      console.log(
        `Poll status for ${uploadId}:`,
        data?.status,
        's3_id:',
        data?.s3_id
      );

      if (data?.status === 'error') {
        throw new Error(data?.error_message || 'Processing failed');
      }

      if (data?.status !== 'complete') {
        if (retries > 0) {
          await new Promise((resolve) => setTimeout(resolve, 4000));
          return pollUploadStatus(uploadId, retries - 1);
        } else {
          throw new Error('Upload processing timed out');
        }
      }

      // Upload completed successfully
      console.log(`Upload ${uploadId} completed with s3_id:`, data?.s3_id);
    },
    [apiClient]
  );

  const handleCreate = useCallback(async () => {
    console.log('Creating with files:', uploadedFiles);
    setIsProcessing(true);
    setStatusMessage('Uploading files...');

    try {
      const uploadedFilesWithIds: UploadedFile[] = [];

      // Process audio files with Uppy
      const audioFiles = uploadedFiles.filter((f) => f.type === 'audio');

      for (let i = 0; i < audioFiles.length; i++) {
        const audioFile = audioFiles[i];
        setStatusMessage(
          `Uploading audio file ${i + 1} of ${audioFiles.length}...`
        );
        if (audioFile.uploadId) {
          uploadedFilesWithIds.push(audioFile);
          continue;
        }

        // Create a new Uppy instance for this file
        const uppy = new Uppy({
          autoProceed: true,
          allowMultipleUploadBatches: false,
        });

        uppyInstanceRef.current = uppy;

        // Track upload ID
        let uploadId: string | undefined;

        // Configure S3 upload
        uppy.use(AwsS3, {
          getUploadParameters: async (_file) => {
            const extension = audioFile.file.name.split('.').pop() || 'mp3';
            const { data } = await apiClient.POST('/api/uploads/audio/', {
              body: { extension, is_stem_mix: false },
            });

            if (!data) {
              throw new Error('Failed to get upload parameters');
            }

            uploadId = data.id;

            return {
              url: data.url,
              fields: data.fields as Record<string, never>,
            };
          },
        });

        // Add file to Uppy
        uppy.addFile({
          name: audioFile.file.name,
          type: audioFile.file.type,
          data: audioFile.file,
        });

        // Wait for upload to complete
        await new Promise<void>((resolve, reject) => {
          uppy.on('complete', async (_result) => {
            try {
              if (!uploadId) {
                throw new Error('Upload ID not set');
              }

              // Mark upload as finished
              const finishResponse = await apiClient.POST(
                '/api/uploads/audio/{upload_id}/upload-finish/',
                {
                  params: { path: { upload_id: uploadId } },
                  body: {
                    upload_type: 'studio_file_upload',
                    upload_filename: audioFile.file.name,
                  },
                }
              );

              if (finishResponse.data) {
                setStatusMessage('Processing uploaded audio...');
                // Poll until the upload is fully processed
                await pollUploadStatus(uploadId);
              }

              resolve();
            } catch (error) {
              reject(error);
            }
          });

          uppy.on('upload-error', (file, error) => {
            reject(error);
          });

          uppy.on('error', (error) => {
            reject(error);
          });
        });

        uploadedFilesWithIds.push({
          ...audioFile,
          uploadId,
          uploading: false,
        });

        uppy.close();
      }

      // Process text files (no change needed)
      const textFiles = uploadedFiles.filter((f) => f.type === 'text');
      for (let i = 0; i < textFiles.length; i++) {
        const textFile = textFiles[i];
        if (textFile.uploadId) {
          uploadedFilesWithIds.push(textFile);
          continue;
        }

        const text = await textFile.file.text();
        const textId = `text_${Date.now()}_${i}`;

        uploadedFilesWithIds.push({
          ...textFile,
          uploadId: textId,
          textContent: text,
          uploading: false,
        });
      }

      const audioFileIds = uploadedFilesWithIds
        .filter((f) => f.type === 'audio' && f.uploadId)
        .map((f) => f.uploadId!);

      const textFileIds = uploadedFilesWithIds
        .filter((f) => f.type === 'text' && f.uploadId)
        .map((f) => f.uploadId!);

      // Collect text content to send in metadata
      const textContents = uploadedFilesWithIds
        .filter((f) => f.type === 'text' && f.textContent)
        .map((f) => ({
          id: f.uploadId!,
          filename: f.file.name,
          content: f.textContent!,
        }));

      console.log('Calling sunote processing with:', {
        audioFileIds,
        textFileIds,
        textContents,
      });
      console.log(
        'Audio file IDs type check:',
        audioFileIds.map((id) => ({ id, type: typeof id }))
      );

      setStatusMessage('Processing audio...');

      const sunoteResponse = await apiClient.POST(
        '/api/generate/sunote/process',
        {
          body: {
            audio_file_ids: audioFileIds,
            text_file_ids: textFileIds,
            metadata: {
              text_contents: textContents,
            },
          },
        }
      );

      console.log('Sunote response:', sunoteResponse);

      if (!sunoteResponse.data) {
        throw new Error('Sunote processing failed: No response data');
      }

      console.log('Sunote processing completed:', sunoteResponse.data);
      setStatusMessage(
        `Success! Created ${sunoteResponse.data.count || 'new'} song ideas`
      );

      // Clear files after successful processing
      setTimeout(() => {
        setUploadedFiles([]);
        setStatusMessage('');
        setIsProcessing(false);
      }, 3000);
    } catch (error) {
      console.error('Failed to create:', error);
      setStatusMessage(
        `Error: ${error instanceof Error ? error.message : 'Unknown error'}`
      );
      setIsProcessing(false);
    }
  }, [uploadedFiles, apiClient, pollUploadStatus]);

  return (
    <div
      className={twMerge(
        'fixed right-4 bottom-4 z-[99999] transition-all duration-300 ease-in-out',
        className
      )}
    >
      {/* Collapsed State - Just the icon/button */}
      {!isExpanded && (
        <button
          onClick={toggleExpanded}
          className={clsx(
            'flex h-16 w-16 items-center justify-center rounded-full',
            'bg-cover bg-center',
            'shadow-lg hover:shadow-xl',
            'transform transition-all duration-200 hover:scale-110',
            'text-white'
          )}
          style={{
            backgroundImage:
              'url(https://cdn-o.suno.com/auras-v2/Aura-1-horizontal.png)',
          }}
          aria-label='Expand helper'
        >
          {/* Cleffy-style icon */}
          <StarIcon className='h-8 w-8 text-white' />
        </button>
      )}

      {/* Expanded State - The full modal */}
      {isExpanded && (
        <div
          className={clsx(
            'flex flex-col rounded-3xl bg-background-secondary',
            'shadow-2xl',
            'max-h-[500px] w-80',
            'border border-foreground-primary/10',
            'animate-slide-in-from-bottom'
          )}
        >
          {/* Header */}
          <div className='flex items-center justify-between p-4'>
            <div className='flex items-center gap-2'>
              <span className='font-sans text-lg font-medium text-foreground-primary'>
                What would you like to create?
              </span>
            </div>
            <button
              onClick={toggleExpanded}
              className='flex h-8 w-8 items-center justify-center rounded-full transition-colors hover:bg-foreground-primary/10'
              aria-label='Collapse helper'
            >
              <svg
                width='16'
                height='16'
                viewBox='0 0 24 24'
                fill='none'
                xmlns='http://www.w3.org/2000/svg'
                className='text-foreground-secondary'
              >
                <path
                  d='M19 9L12 16L5 9'
                  stroke='currentColor'
                  strokeWidth='2'
                  strokeLinecap='round'
                  strokeLinejoin='round'
                />
              </svg>
            </button>
          </div>

          {/* Content */}
          <div className='flex flex-1 flex-col overflow-hidden p-4'>
            {/* Drag and Drop Area */}
            <div
              onDragEnter={handleDragEnter}
              onDragLeave={handleDragLeave}
              onDragOver={handleDragOver}
              onDrop={handleDrop}
              className={clsx(
                'flex flex-1 flex-col items-center justify-center overflow-hidden rounded-2xl border-2 border-dashed transition-all',
                {
                  'border-[#FF8C42]': isDragging,
                  'border-foreground-primary/20 bg-background-primary':
                    !isDragging,
                }
              )}
              style={
                isDragging
                  ? {
                      backgroundImage:
                        'url(https://cdn-o.suno.com/auras-v2/Aura-1-horizontal.png)',
                      backgroundSize: 'cover',
                      backgroundPosition: 'center',
                      opacity: 0.9,
                    }
                  : undefined
              }
            >
              {uploadedFiles.length === 0 ? (
                <div className='flex flex-col items-center gap-3 p-6 text-center'>
                  <svg
                    width='48'
                    height='48'
                    viewBox='0 0 24 24'
                    fill='none'
                    xmlns='http://www.w3.org/2000/svg'
                    className='text-foreground-tertiary'
                  >
                    <path
                      d='M21 15V19C21 19.5304 20.7893 20.0391 20.4142 20.4142C20.0391 20.7893 19.5304 21 19 21H5C4.46957 21 3.96086 20.7893 3.58579 20.4142C3.21071 20.0391 3 19.5304 3 19V15'
                      stroke='currentColor'
                      strokeWidth='2'
                      strokeLinecap='round'
                      strokeLinejoin='round'
                    />
                    <path
                      d='M17 8L12 3L7 8'
                      stroke='currentColor'
                      strokeWidth='2'
                      strokeLinecap='round'
                      strokeLinejoin='round'
                    />
                    <path
                      d='M12 3V15'
                      stroke='currentColor'
                      strokeWidth='2'
                      strokeLinecap='round'
                      strokeLinejoin='round'
                    />
                  </svg>
                  <div className='space-y-1'>
                    <p className='font-sans text-sm font-medium text-foreground-primary'>
                      Drop files here
                    </p>
                    <p className='font-sans text-xs text-foreground-tertiary'>
                      MP3, WAV, TXT, or MD files
                    </p>
                  </div>
                  <label className='cursor-pointer'>
                    <input
                      type='file'
                      multiple
                      accept='.mp3,.wav,.txt,.md,.note,audio/*,text/*'
                      onChange={handleFileInputChange}
                      className='hidden'
                    />
                    <span
                      className='inline-block rounded-full bg-cover bg-center px-4 py-2 font-sans text-xs font-medium text-white transition-all hover:shadow-lg'
                      style={{
                        backgroundImage:
                          'url(https://cdn-o.suno.com/auras-v2/Aura-1-horizontal.png)',
                      }}
                    >
                      Or browse files
                    </span>
                  </label>
                </div>
              ) : (
                <div className='flex h-full w-full flex-col gap-2 overflow-y-auto p-3'>
                  {uploadedFiles.map((uploadedFile, index) => (
                    <div
                      key={index}
                      className='flex items-center justify-between gap-2 rounded-xl bg-background-secondary p-3'
                    >
                      <div className='flex min-w-0 flex-1 items-center gap-3'>
                        {uploadedFile.type === 'audio' ? (
                          <div className='flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-lg bg-[#FF8C42]/20'>
                            <svg
                              width='20'
                              height='20'
                              viewBox='0 0 24 24'
                              fill='none'
                              xmlns='http://www.w3.org/2000/svg'
                              className='text-[#FF8C42]'
                            >
                              <path
                                d='M9 18V5L21 3V16'
                                stroke='currentColor'
                                strokeWidth='2'
                                strokeLinecap='round'
                                strokeLinejoin='round'
                              />
                              <circle
                                cx='6'
                                cy='18'
                                r='3'
                                stroke='currentColor'
                                strokeWidth='2'
                              />
                              <circle
                                cx='18'
                                cy='16'
                                r='3'
                                stroke='currentColor'
                                strokeWidth='2'
                              />
                            </svg>
                          </div>
                        ) : (
                          <div className='flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-lg bg-[#FF4B8C]/20'>
                            <svg
                              width='20'
                              height='20'
                              viewBox='0 0 24 24'
                              fill='none'
                              xmlns='http://www.w3.org/2000/svg'
                              className='text-[#FF4B8C]'
                            >
                              <path
                                d='M14 2H6C5.46957 2 4.96086 2.21071 4.58579 2.58579C4.21071 2.96086 4 3.46957 4 4V20C4 20.5304 4.21071 21.0391 4.58579 21.4142C4.96086 21.7893 5.46957 22 6 22H18C18.5304 22 19.0391 21.7893 19.4142 21.4142C19.7893 21.0391 20 20.5304 20 20V8L14 2Z'
                                stroke='currentColor'
                                strokeWidth='2'
                                strokeLinecap='round'
                                strokeLinejoin='round'
                              />
                              <path
                                d='M14 2V8H20'
                                stroke='currentColor'
                                strokeWidth='2'
                                strokeLinecap='round'
                                strokeLinejoin='round'
                              />
                            </svg>
                          </div>
                        )}
                        <div className='flex min-w-0 flex-1 flex-col'>
                          <span className='truncate font-sans text-sm text-foreground-primary'>
                            {uploadedFile.file.name}
                          </span>
                          <span className='font-sans text-xs text-foreground-tertiary'>
                            {(uploadedFile.file.size / 1024).toFixed(1)} KB
                          </span>
                        </div>
                      </div>
                      <button
                        onClick={() => removeFile(index)}
                        className='flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-full transition-colors hover:bg-foreground-primary/10'
                        aria-label='Remove file'
                      >
                        <svg
                          width='16'
                          height='16'
                          viewBox='0 0 24 24'
                          fill='none'
                          xmlns='http://www.w3.org/2000/svg'
                          className='text-foreground-tertiary'
                        >
                          <path
                            d='M18 6L6 18'
                            stroke='currentColor'
                            strokeWidth='2'
                            strokeLinecap='round'
                            strokeLinejoin='round'
                          />
                          <path
                            d='M6 6L18 18'
                            stroke='currentColor'
                            strokeWidth='2'
                            strokeLinecap='round'
                            strokeLinejoin='round'
                          />
                        </svg>
                      </button>
                    </div>
                  ))}
                  <label className='flex cursor-pointer items-center justify-center rounded-xl border border-dashed border-foreground-primary/20 p-3 transition-colors hover:border-foreground-primary/40 hover:bg-foreground-primary/5'>
                    <input
                      type='file'
                      multiple
                      accept='.mp3,.wav,.txt,.md,.note,audio/*,text/*'
                      onChange={handleFileInputChange}
                      className='hidden'
                    />
                    <span className='font-sans text-xs text-foreground-secondary'>
                      + Add more files
                    </span>
                  </label>
                </div>
              )}
            </div>

            {/* Status Message */}
            {statusMessage && (
              <div className='mt-2 rounded-lg bg-background-primary p-3 text-center'>
                <p
                  className={clsx('font-sans text-xs', {
                    'text-foreground-primary':
                      !statusMessage.startsWith('Error'),
                    'text-accent-error': statusMessage.startsWith('Error'),
                    'text-accent-success': statusMessage.startsWith('Success'),
                  })}
                >
                  {statusMessage}
                </p>
              </div>
            )}

            {/* Create Button */}
            <button
              onClick={handleCreate}
              disabled={uploadedFiles.length === 0 || isProcessing}
              className={clsx(
                'mt-4 w-full rounded-full py-3 font-sans text-sm font-medium transition-all',
                {
                  'bg-cover bg-center text-white shadow-lg hover:scale-[1.02] hover:shadow-xl':
                    uploadedFiles.length > 0 && !isProcessing,
                  'cursor-not-allowed bg-foreground-primary/10 text-foreground-tertiary':
                    uploadedFiles.length === 0 || isProcessing,
                }
              )}
              style={
                uploadedFiles.length > 0 && !isProcessing
                  ? {
                      backgroundImage:
                        'url(https://cdn-o.suno.com/auras-v2/Aura-1-horizontal.png)',
                    }
                  : undefined
              }
            >
              {isProcessing ? 'Processing...' : 'Create'}
            </button>
          </div>
        </div>
      )}
    </div>
  );
};

export default CleffyModal;
