'use client';

import * as React from 'react';
import { ArrowRight } from 'lucide-react';
import { Button } from '@/components/ui/Button';
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/Card';
import { FileUpload } from './FileUpload';
import { FormatSelector } from './FormatSelector';
import { ConversionPreview } from './ConversionPreview';
import { ConversionOptionsPanel } from './ConversionOptions';
import { FileInfo } from './FileInfo';
import { useToast } from '@/components/ui/Toast';
import {
  SUPPORTED_FORMATS,
  getFormatByExtension,
  getFormatByMimeType,
  getCompatibleFormats,
} from '@/lib/utils/formatMappings';
import { convertWithFFmpeg } from '@/lib/converters/ffmpegService';
import { convertWithImageMagick } from '@/lib/converters/imagemagickService';
import { addToHistory } from '@/lib/storage/history';
import type { ConversionJob, ConversionFormat, ConversionOptions } from '@/types/conversion';

export function FileConverter() {
  const { addToast } = useToast();

  const [selectedFile, setSelectedFile] = React.useState<File | undefined>();
  const [inputFormat, setInputFormat] = React.useState<ConversionFormat | undefined>();
  const [outputFormat, setOutputFormat] = React.useState<ConversionFormat | undefined>();
  const [compatibleFormats, setCompatibleFormats] = React.useState<ConversionFormat[]>([]);
  const [conversionJob, setConversionJob] = React.useState<ConversionJob | undefined>();
  const [conversionOptions, setConversionOptions] = React.useState<ConversionOptions>({});

  // Detect input format when file is selected
  React.useEffect(() => {
    if (!selectedFile) {
      setInputFormat(undefined);
      setOutputFormat(undefined);
      setCompatibleFormats([]);
      setConversionJob(undefined);
      return;
    }

    // Try to detect format from extension
    const ext = selectedFile.name.split('.').pop()?.toLowerCase();
    let format = ext ? getFormatByExtension(ext) : undefined;

    // Fallback to MIME type
    if (!format) {
      format = getFormatByMimeType(selectedFile.type);
    }

    if (format) {
      setInputFormat(format);
      const compatible = getCompatibleFormats(format);
      setCompatibleFormats(compatible);

      // Auto-select first compatible format
      if (compatible.length > 0 && !outputFormat) {
        setOutputFormat(compatible[0]);
      }

      addToast(`Detected format: ${format.name}`, 'success');
    } else {
      addToast('Could not detect file format', 'error');
      setInputFormat(undefined);
      setCompatibleFormats([]);
    }
  }, [selectedFile]);

  const handleConvert = async () => {
    if (!selectedFile || !inputFormat || !outputFormat) {
      addToast('Please select a file and output format', 'error');
      return;
    }

    // Create conversion job
    const job: ConversionJob = {
      id: Math.random().toString(36).substring(7),
      inputFile: selectedFile,
      inputFormat,
      outputFormat,
      options: conversionOptions,
      status: 'loading',
      progress: 0,
      startTime: Date.now(),
    };

    setConversionJob(job);

    try {
      // Update status to processing
      setConversionJob((prev) => prev && { ...prev, status: 'processing', progress: 10 });

      // Call appropriate converter
      let result;

      switch (outputFormat.converter) {
        case 'ffmpeg':
          result = await convertWithFFmpeg(selectedFile, outputFormat.extension, conversionOptions, (progress) => {
            setConversionJob((prev) => prev && { ...prev, progress });
          });
          break;

        case 'imagemagick':
          result = await convertWithImageMagick(
            selectedFile,
            outputFormat.extension,
            conversionOptions,
            (progress) => {
              setConversionJob((prev) => prev && { ...prev, progress });
            }
          );
          break;

        default:
          throw new Error(`Unknown converter: ${outputFormat.converter}`);
      }

      // Update job with result
      if (result.success && result.blob) {
        setConversionJob((prev) => prev && {
          ...prev,
          status: 'completed',
          progress: 100,
          result: result.blob,
          endTime: Date.now(),
        });

        addToast('Conversion completed successfully!', 'success');

        // Add to history
        addToHistory({
          inputFileName: selectedFile.name,
          inputFormat: inputFormat.name,
          outputFormat: outputFormat.name,
          outputFileName: `output.${outputFormat.extension}`,
          fileSize: result.blob.size,
          result: result.blob,
        });
      } else {
        setConversionJob((prev) => prev && {
          ...prev,
          status: 'error',
          error: result.error || 'Unknown error',
          endTime: Date.now(),
        });

        addToast(result.error || 'Conversion failed', 'error');
      }
    } catch (error) {
      const errorMessage = error instanceof Error ? error.message : 'Unknown error';

      setConversionJob((prev) => prev && {
        ...prev,
        status: 'error',
        error: errorMessage,
        endTime: Date.now(),
      });

      addToast(`Conversion failed: ${errorMessage}`, 'error');
    }
  };

  const handleReset = () => {
    setSelectedFile(undefined);
    setInputFormat(undefined);
    setOutputFormat(undefined);
    setCompatibleFormats([]);
    setConversionJob(undefined);
    setConversionOptions({});
  };

  const isConvertDisabled =
    !selectedFile || !outputFormat || conversionJob?.status === 'loading' || conversionJob?.status === 'processing';

  return (
    <div className="w-full max-w-4xl mx-auto space-y-6">
      {/* Header */}
      <Card>
        <CardHeader>
          <CardTitle>File Converter</CardTitle>
          <CardDescription>
            Convert videos, audio, and images directly in your browser using WebAssembly
          </CardDescription>
        </CardHeader>
        <CardContent className="space-y-6">
          {/* File upload */}
          <FileUpload
            onFileSelect={setSelectedFile}
            onFileRemove={handleReset}
            selectedFile={selectedFile}
            disabled={conversionJob?.status === 'processing' || conversionJob?.status === 'loading'}
          />

          {/* File Info */}
          {selectedFile && inputFormat && (
            <FileInfo file={selectedFile} format={inputFormat} />
          )}

          {/* Format selection */}
          {inputFormat && compatibleFormats.length > 0 && (
            <div className="grid grid-cols-1 md:grid-cols-[1fr_auto_1fr] gap-4 items-start">
              {/* Input format */}
              <div>
                <label className="text-sm font-medium text-foreground mb-2 block">Input Format</label>
                <Card className="p-4">
                  <p className="font-medium">{inputFormat.name}</p>
                  <p className="text-xs text-muted-foreground mt-1">{inputFormat.description}</p>
                </Card>
              </div>

              {/* Arrow */}
              <div className="hidden md:flex items-center justify-center pt-8">
                <ArrowRight className="h-5 w-5 text-muted-foreground" />
              </div>

              {/* Output format */}
              <FormatSelector
                formats={compatibleFormats}
                selectedFormat={outputFormat}
                onFormatSelect={setOutputFormat}
                label="Output Format"
                disabled={conversionJob?.status === 'processing' || conversionJob?.status === 'loading'}
              />
            </div>
          )}

          {/* Conversion Options */}
          {inputFormat && outputFormat && (
            <ConversionOptionsPanel
              inputFormat={inputFormat}
              outputFormat={outputFormat}
              options={conversionOptions}
              onOptionsChange={setConversionOptions}
              disabled={conversionJob?.status === 'processing' || conversionJob?.status === 'loading'}
            />
          )}

          {/* Convert button */}
          {inputFormat && outputFormat && (
            <div className="flex gap-3">
              <Button
                onClick={handleConvert}
                disabled={isConvertDisabled}
                className="flex-1"
                size="lg"
              >
                {conversionJob?.status === 'loading' || conversionJob?.status === 'processing'
                  ? 'Converting...'
                  : 'Convert'}
              </Button>
              <Button onClick={handleReset} variant="outline" size="lg">
                Reset
              </Button>
            </div>
          )}
        </CardContent>
      </Card>

      {/* Conversion preview */}
      {conversionJob && <ConversionPreview job={conversionJob} />}
    </div>
  );
}
