'use client';

import { useCallback, useRef, useState } from 'react';

import { useRouter } from 'next/navigation';

import { Upload } from 'lucide-react';

import { uploadFile } from '@kit/module-builder/actions/file-actions';
import { Button } from '@kit/ui/button';
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogHeader,
  DialogTitle,
  DialogTrigger,
} from '@kit/ui/dialog';
import { useActionWithToast } from '@kit/ui/use-action-with-toast';

interface FileUploadDialogProps {
  accountId: string;
}

const MAX_FILE_SIZE = 10 * 1024 * 1024; // 10 MB

const ACCEPTED_TYPES = [
  'image/*',
  'application/pdf',
  'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
  'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
  'text/csv',
  'text/plain',
  'application/zip',
].join(',');

function formatFileSize(bytes: number): string {
  if (bytes >= 1024 * 1024) {
    return `${(bytes / 1024 / 1024).toFixed(1)} MB`;
  }

  return `${(bytes / 1024).toFixed(1)} KB`;
}

export function FileUploadDialog({ accountId }: FileUploadDialogProps) {
  const router = useRouter();
  const fileInputRef = useRef<HTMLInputElement>(null);
  const [open, setOpen] = useState(false);
  const [selectedFile, setSelectedFile] = useState<{
    name: string;
    type: string;
    size: number;
    base64: string;
  } | null>(null);
  const [error, setError] = useState<string | null>(null);

  const { execute, isPending } = useActionWithToast(uploadFile, {
    successMessage: 'Datei hochgeladen',
    onSuccess: () => {
      setOpen(false);
      setSelectedFile(null);
      setError(null);
      router.refresh();
    },
  });

  const handleFileSelect = useCallback(
    (e: React.ChangeEvent<HTMLInputElement>) => {
      setError(null);
      const file = e.target.files?.[0];

      if (!file) {
        setSelectedFile(null);
        return;
      }

      if (file.size > MAX_FILE_SIZE) {
        setError('Die Datei darf maximal 10 MB groß sein.');
        setSelectedFile(null);
        return;
      }

      const reader = new FileReader();

      reader.onload = () => {
        const result = reader.result as string;
        // Remove the data:...;base64, prefix
        const base64 = result.split(',')[1] ?? '';

        setSelectedFile({
          name: file.name,
          type: file.type || 'application/octet-stream',
          size: file.size,
          base64,
        });
      };

      reader.onerror = () => {
        setError('Fehler beim Lesen der Datei.');
        setSelectedFile(null);
      };

      reader.readAsDataURL(file);
    },
    [],
  );

  const handleUpload = useCallback(() => {
    if (!selectedFile) return;

    execute({
      accountId,
      fileName: selectedFile.name,
      fileType: selectedFile.type,
      fileSize: selectedFile.size,
      base64: selectedFile.base64,
    });
  }, [accountId, execute, selectedFile]);

  const handleOpenChange = useCallback(
    (isOpen: boolean) => {
      if (!isPending) {
        setOpen(isOpen);

        if (!isOpen) {
          setSelectedFile(null);
          setError(null);
        }
      }
    },
    [isPending],
  );

  return (
    <Dialog open={open} onOpenChange={handleOpenChange}>
      <DialogTrigger
        render={
          <Button size="sm" data-test="file-upload-btn">
            <Upload className="mr-2 h-4 w-4" />
            Datei hochladen
          </Button>
        }
      />
      <DialogContent showCloseButton={!isPending}>
        <DialogHeader>
          <DialogTitle>Datei hochladen</DialogTitle>
          <DialogDescription>
            Wählen Sie eine Datei aus (max. 10 MB).
          </DialogDescription>
        </DialogHeader>

        <div className="flex flex-col gap-4">
          <input
            ref={fileInputRef}
            type="file"
            accept={ACCEPTED_TYPES}
            onChange={handleFileSelect}
            className="file:bg-primary file:text-primary-foreground hover:file:bg-primary/90 block w-full text-sm file:mr-4 file:rounded-md file:border-0 file:px-4 file:py-2 file:text-sm file:font-medium"
            data-test="file-upload-input"
          />

          {error && <p className="text-destructive text-sm">{error}</p>}

          {selectedFile && (
            <div className="bg-muted rounded-md p-3">
              <p className="text-sm font-medium">{selectedFile.name}</p>
              <p className="text-muted-foreground text-xs">
                {selectedFile.type} &middot; {formatFileSize(selectedFile.size)}
              </p>
            </div>
          )}

          <Button
            onClick={handleUpload}
            disabled={!selectedFile || isPending}
            data-test="file-upload-submit"
          >
            {isPending ? 'Wird hochgeladen...' : 'Hochladen'}
          </Button>
        </div>
      </DialogContent>
    </Dialog>
  );
}
