"use client";

import { useState } from "react";
import { Check, Download, FileImage, FileText, Pencil, Star, Trash2, X } from "lucide-react";
import { toast } from "sonner";
import type { FileDto } from "@use2pdf/shared-types";
import { Button } from "@/components/ui/button";
import { apiFetch, ApiRequestError, downloadFile } from "@/lib/api-client";
import { formatBytes, formatDate } from "@/lib/format";

interface FileListProps {
  files: FileDto[];
  onDeleted: (fileId: string) => void;
  onUpdated?: (file: FileDto) => void;
  selectable?: boolean;
  selectedIds?: string[];
  onSelectionChange?: (ids: string[]) => void;
}

function FileIcon({ mimeType }: { mimeType: string }) {
  if (mimeType.startsWith("image/")) return <FileImage className="h-8 w-8 shrink-0 text-blue-500" />;
  if (mimeType === "text/plain") return <FileText className="h-8 w-8 shrink-0 text-slate-400" />;
  return <FileText className="h-8 w-8 shrink-0 text-red-500" />;
}

export function FileList({
  files,
  onDeleted,
  onUpdated,
  selectable = false,
  selectedIds = [],
  onSelectionChange,
}: FileListProps) {
  const [busyFileId, setBusyFileId] = useState<string | null>(null);
  const [renamingId, setRenamingId] = useState<string | null>(null);
  const [renameValue, setRenameValue] = useState("");

  function toggleSelected(fileId: string) {
    if (!onSelectionChange) return;
    onSelectionChange(
      selectedIds.includes(fileId)
        ? selectedIds.filter((id) => id !== fileId)
        : [...selectedIds, fileId],
    );
  }

  async function handleDownload(file: FileDto) {
    setBusyFileId(file.id);
    try {
      await downloadFile(file.id, file.originalName);
    } catch (err) {
      toast.error(err instanceof ApiRequestError ? err.message : "Download failed");
    } finally {
      setBusyFileId(null);
    }
  }

  async function handleDelete(file: FileDto) {
    if (!window.confirm(`Delete ${file.originalName}? This cannot be undone.`)) return;
    setBusyFileId(file.id);
    try {
      await apiFetch(`/files/${file.id}`, { method: "DELETE" });
      toast.success(`Deleted ${file.originalName}`);
      onDeleted(file.id);
    } catch (err) {
      toast.error(err instanceof ApiRequestError ? err.message : "Delete failed");
    } finally {
      setBusyFileId(null);
    }
  }

  async function handleToggleFavorite(file: FileDto) {
    try {
      const res = await apiFetch<{ file: FileDto }>(`/files/${file.id}`, {
        method: "PATCH",
        body: { isFavorite: !file.isFavorite },
      });
      onUpdated?.(res.file);
    } catch (err) {
      toast.error(err instanceof ApiRequestError ? err.message : "Could not update favorite");
    }
  }

  async function submitRename(file: FileDto) {
    const name = renameValue.trim();
    setRenamingId(null);
    if (!name || name === file.originalName) return;
    try {
      const res = await apiFetch<{ file: FileDto }>(`/files/${file.id}`, {
        method: "PATCH",
        body: { name },
      });
      toast.success("Renamed");
      onUpdated?.(res.file);
    } catch (err) {
      toast.error(err instanceof ApiRequestError ? err.message : "Rename failed");
    }
  }

  if (files.length === 0) {
    return (
      <div className="flex flex-col items-center gap-2 py-12 text-center">
        <FileText className="h-10 w-10 text-slate-300 dark:text-slate-600" />
        <p className="font-medium text-slate-600 dark:text-slate-300">No files found</p>
        <p className="text-sm text-slate-400">Upload a file above to get started.</p>
      </div>
    );
  }

  return (
    <ul className="divide-y divide-slate-100 dark:divide-slate-700">
      {files.map((file) => (
        <li key={file.id} className="flex items-center gap-3 px-2 py-3">
          {selectable && (
            <input
              type="checkbox"
              aria-label={`Select ${file.originalName}`}
              className="h-4 w-4 rounded border-slate-300 text-brand-600 focus:ring-brand-500"
              checked={selectedIds.includes(file.id)}
              onChange={() => toggleSelected(file.id)}
            />
          )}
          <FileIcon mimeType={file.mimeType} />
          <div className="min-w-0 flex-1">
            {renamingId === file.id ? (
              <div className="flex items-center gap-1">
                <input
                  autoFocus
                  className="h-8 w-full max-w-xs rounded border border-brand-400 bg-white px-2 text-sm text-slate-900 focus:outline-none dark:bg-slate-900 dark:text-slate-100"
                  value={renameValue}
                  onChange={(e) => setRenameValue(e.target.value)}
                  onKeyDown={(e) => {
                    if (e.key === "Enter") submitRename(file);
                    if (e.key === "Escape") setRenamingId(null);
                  }}
                />
                <button aria-label="Confirm rename" className="text-green-600" onClick={() => submitRename(file)}>
                  <Check className="h-4 w-4" />
                </button>
                <button aria-label="Cancel rename" className="text-slate-400" onClick={() => setRenamingId(null)}>
                  <X className="h-4 w-4" />
                </button>
              </div>
            ) : (
              <p className="truncate font-medium text-slate-900 dark:text-slate-100">
                {file.originalName}
              </p>
            )}
            <p className="text-sm text-slate-500 dark:text-slate-400">
              {formatBytes(file.sizeBytes)} · {formatDate(file.createdAt)}
            </p>
          </div>
          <div className="flex shrink-0 items-center gap-1">
            <Button
              variant="ghost"
              size="sm"
              aria-label={file.isFavorite ? `Unfavorite ${file.originalName}` : `Favorite ${file.originalName}`}
              onClick={() => handleToggleFavorite(file)}
            >
              <Star
                className={
                  file.isFavorite
                    ? "h-4 w-4 fill-amber-400 text-amber-400"
                    : "h-4 w-4 text-slate-400"
                }
              />
            </Button>
            <Button
              variant="ghost"
              size="sm"
              aria-label={`Rename ${file.originalName}`}
              onClick={() => {
                setRenamingId(file.id);
                setRenameValue(file.originalName);
              }}
            >
              <Pencil className="h-4 w-4" />
            </Button>
            <Button
              variant="ghost"
              size="sm"
              aria-label={`Download ${file.originalName}`}
              onClick={() => handleDownload(file)}
              isLoading={busyFileId === file.id}
            >
              <Download className="h-4 w-4" />
            </Button>
            <Button
              variant="ghost"
              size="sm"
              aria-label={`Delete ${file.originalName}`}
              className="text-red-600 hover:bg-red-50 dark:hover:bg-red-950"
              onClick={() => handleDelete(file)}
              disabled={busyFileId === file.id}
            >
              <Trash2 className="h-4 w-4" />
            </Button>
          </div>
        </li>
      ))}
    </ul>
  );
}
