"use client";

import { useState } from "react";
import { trpc } from "@/lib/trpc/client";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Textarea } from "@/components/ui/textarea";
import { Switch } from "@/components/ui/switch";
import { Badge } from "@/components/ui/badge";
import {
  Card,
  CardContent,
  CardDescription,
  CardHeader,
  CardTitle,
} from "@/components/ui/card";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import { toast } from "sonner";
import {
  Plus,
  Pencil,
  Trash2,
  GripVertical,
  ArrowUp,
  ArrowDown,
  FileText,
  Loader2,
} from "lucide-react";

const MIME_TYPE_PRESETS = [
  { label: "PDF", value: "application/pdf" },
  { label: "Images", value: "image/*" },
  { label: "Video", value: "video/*" },
  {
    label: "Word Documents",
    value:
      "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
  },
  {
    label: "Excel",
    value: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
  },
  {
    label: "PowerPoint",
    value:
      "application/vnd.openxmlformats-officedocument.presentationml.presentation",
  },
];

function getMimeLabel(mime: string): string {
  const preset = MIME_TYPE_PRESETS.find((p) => p.value === mime);
  if (preset) return preset.label;
  if (mime.endsWith("/*")) return mime.replace("/*", "");
  return mime;
}

interface FileRequirementsEditorProps {
  roundId: string;
}

interface RequirementFormData {
  name: string;
  description: string;
  acceptedMimeTypes: string[];
  maxSizeMB: string;
  isRequired: boolean;
}

const emptyForm: RequirementFormData = {
  name: "",
  description: "",
  acceptedMimeTypes: [],
  maxSizeMB: "",
  isRequired: true,
};

export function FileRequirementsEditor({
  roundId,
}: FileRequirementsEditorProps) {
  const utils = trpc.useUtils();

  const { data: requirements = [], isLoading } =
    trpc.file.listRequirements.useQuery({ roundId });
  const createMutation = trpc.file.createRequirement.useMutation({
    onSuccess: () => {
      utils.file.listRequirements.invalidate({ roundId });
      toast.success("Requirement created");
    },
    onError: (err) => toast.error(err.message),
  });
  const updateMutation = trpc.file.updateRequirement.useMutation({
    onSuccess: () => {
      utils.file.listRequirements.invalidate({ roundId });
      toast.success("Requirement updated");
    },
    onError: (err) => toast.error(err.message),
  });
  const deleteMutation = trpc.file.deleteRequirement.useMutation({
    onSuccess: () => {
      utils.file.listRequirements.invalidate({ roundId });
      toast.success("Requirement deleted");
    },
    onError: (err) => toast.error(err.message),
  });
  const reorderMutation = trpc.file.reorderRequirements.useMutation({
    onSuccess: () => utils.file.listRequirements.invalidate({ roundId }),
    onError: (err) => toast.error(err.message),
  });

  const [dialogOpen, setDialogOpen] = useState(false);
  const [editingId, setEditingId] = useState<string | null>(null);
  const [form, setForm] = useState<RequirementFormData>(emptyForm);

  const openCreate = () => {
    setEditingId(null);
    setForm(emptyForm);
    setDialogOpen(true);
  };

  const openEdit = (req: (typeof requirements)[number]) => {
    setEditingId(req.id);
    setForm({
      name: req.name,
      description: req.description || "",
      acceptedMimeTypes: req.acceptedMimeTypes,
      maxSizeMB: req.maxSizeMB?.toString() || "",
      isRequired: req.isRequired,
    });
    setDialogOpen(true);
  };

  const handleSave = async () => {
    if (!form.name.trim()) {
      toast.error("Name is required");
      return;
    }

    const maxSizeMB = form.maxSizeMB ? parseInt(form.maxSizeMB) : undefined;

    if (editingId) {
      await updateMutation.mutateAsync({
        id: editingId,
        name: form.name.trim(),
        description: form.description.trim() || null,
        acceptedMimeTypes: form.acceptedMimeTypes,
        maxSizeMB: maxSizeMB || null,
        isRequired: form.isRequired,
      });
    } else {
      await createMutation.mutateAsync({
        roundId,
        name: form.name.trim(),
        description: form.description.trim() || undefined,
        acceptedMimeTypes: form.acceptedMimeTypes,
        maxSizeMB,
        isRequired: form.isRequired,
        sortOrder: requirements.length,
      });
    }

    setDialogOpen(false);
  };

  const handleDelete = async (id: string) => {
    await deleteMutation.mutateAsync({ id });
  };

  const handleMove = async (index: number, direction: "up" | "down") => {
    const newOrder = [...requirements];
    const swapIndex = direction === "up" ? index - 1 : index + 1;
    if (swapIndex < 0 || swapIndex >= newOrder.length) return;
    [newOrder[index], newOrder[swapIndex]] = [
      newOrder[swapIndex],
      newOrder[index],
    ];
    await reorderMutation.mutateAsync({
      roundId,
      orderedIds: newOrder.map((r) => r.id),
    });
  };

  const toggleMimeType = (mime: string) => {
    setForm((prev) => ({
      ...prev,
      acceptedMimeTypes: prev.acceptedMimeTypes.includes(mime)
        ? prev.acceptedMimeTypes.filter((m) => m !== mime)
        : [...prev.acceptedMimeTypes, mime],
    }));
  };

  const isSaving = createMutation.isPending || updateMutation.isPending;

  return (
    <Card>
      <CardHeader>
        <div className="flex items-center justify-between">
          <div>
            <CardTitle className="flex items-center gap-2">
              <FileText className="h-5 w-5" />
              File Requirements
            </CardTitle>
            <CardDescription>
              Define required files applicants must upload for this round
            </CardDescription>
          </div>
          <Button type="button" onClick={openCreate} size="sm">
            <Plus className="mr-1 h-4 w-4" />
            Add Requirement
          </Button>
        </div>
      </CardHeader>
      <CardContent>
        {isLoading ? (
          <div className="flex items-center justify-center py-8">
            <Loader2 className="h-6 w-6 animate-spin text-muted-foreground" />
          </div>
        ) : requirements.length === 0 ? (
          <div className="text-center py-8 text-muted-foreground">
            No file requirements defined. Applicants can still upload files
            freely.
          </div>
        ) : (
          <div className="space-y-2">
            {requirements.map((req, index) => (
              <div
                key={req.id}
                className="flex items-center gap-3 rounded-lg border p-3 bg-background"
              >
                <div className="flex flex-col gap-0.5">
                  <Button
                    type="button"
                    variant="ghost"
                    size="icon"
                    className="h-6 w-6"
                    onClick={() => handleMove(index, "up")}
                    disabled={index === 0}
                  >
                    <ArrowUp className="h-3 w-3" />
                  </Button>
                  <Button
                    type="button"
                    variant="ghost"
                    size="icon"
                    className="h-6 w-6"
                    onClick={() => handleMove(index, "down")}
                    disabled={index === requirements.length - 1}
                  >
                    <ArrowDown className="h-3 w-3" />
                  </Button>
                </div>
                <GripVertical className="h-4 w-4 text-muted-foreground shrink-0" />
                <div className="flex-1 min-w-0">
                  <div className="flex items-center gap-2 mb-1">
                    <span className="font-medium truncate">{req.name}</span>
                    <Badge
                      variant={req.isRequired ? "destructive" : "secondary"}
                      className="text-xs shrink-0"
                    >
                      {req.isRequired ? "Required" : "Optional"}
                    </Badge>
                  </div>
                  {req.description && (
                    <p className="text-sm text-muted-foreground line-clamp-1">
                      {req.description}
                    </p>
                  )}
                  <div className="flex flex-wrap gap-1 mt-1">
                    {req.acceptedMimeTypes.map((mime) => (
                      <Badge key={mime} variant="outline" className="text-xs">
                        {getMimeLabel(mime)}
                      </Badge>
                    ))}
                    {req.maxSizeMB && (
                      <Badge variant="outline" className="text-xs">
                        Max {req.maxSizeMB}MB
                      </Badge>
                    )}
                  </div>
                </div>
                <div className="flex items-center gap-1 shrink-0">
                  <Button
                    type="button"
                    variant="ghost"
                    size="icon"
                    className="h-8 w-8"
                    onClick={() => openEdit(req)}
                  >
                    <Pencil className="h-4 w-4" />
                  </Button>
                  <Button
                    type="button"
                    variant="ghost"
                    size="icon"
                    className="h-8 w-8 text-destructive hover:text-destructive"
                    onClick={() => handleDelete(req.id)}
                    disabled={deleteMutation.isPending}
                  >
                    <Trash2 className="h-4 w-4" />
                  </Button>
                </div>
              </div>
            ))}
          </div>
        )}
      </CardContent>

      {/* Create/Edit Dialog */}
      <Dialog open={dialogOpen} onOpenChange={setDialogOpen}>
        <DialogContent className="max-w-md">
          <DialogHeader>
            <DialogTitle>
              {editingId ? "Edit" : "Add"} File Requirement
            </DialogTitle>
            <DialogDescription>
              Define what file applicants need to upload for this round.
            </DialogDescription>
          </DialogHeader>

          <div className="space-y-4">
            <div className="space-y-2">
              <Label htmlFor="req-name">Name *</Label>
              <Input
                id="req-name"
                value={form.name}
                onChange={(e) =>
                  setForm((p) => ({ ...p, name: e.target.value }))
                }
                placeholder="e.g., Executive Summary"
              />
            </div>

            <div className="space-y-2">
              <Label htmlFor="req-desc">Description</Label>
              <Textarea
                id="req-desc"
                value={form.description}
                onChange={(e) =>
                  setForm((p) => ({ ...p, description: e.target.value }))
                }
                placeholder="Describe what this file should contain..."
                rows={3}
              />
            </div>

            <div className="space-y-2">
              <Label>Accepted File Types</Label>
              <div className="flex flex-wrap gap-2">
                {MIME_TYPE_PRESETS.map((preset) => (
                  <Badge
                    key={preset.value}
                    variant={
                      form.acceptedMimeTypes.includes(preset.value)
                        ? "default"
                        : "outline"
                    }
                    className="cursor-pointer"
                    onClick={() => toggleMimeType(preset.value)}
                  >
                    {preset.label}
                  </Badge>
                ))}
              </div>
              <p className="text-xs text-muted-foreground">
                Leave empty to accept any file type
              </p>
            </div>

            <div className="space-y-2">
              <Label htmlFor="req-size">Max File Size (MB)</Label>
              <Input
                id="req-size"
                type="number"
                value={form.maxSizeMB}
                onChange={(e) =>
                  setForm((p) => ({ ...p, maxSizeMB: e.target.value }))
                }
                placeholder="No limit"
                min={1}
                max={5000}
              />
            </div>

            <div className="flex items-center justify-between">
              <div>
                <Label htmlFor="req-required">Required</Label>
                <p className="text-xs text-muted-foreground">
                  Applicants must upload this file
                </p>
              </div>
              <Switch
                id="req-required"
                checked={form.isRequired}
                onCheckedChange={(checked) =>
                  setForm((p) => ({ ...p, isRequired: checked }))
                }
              />
            </div>
          </div>

          <DialogFooter>
            <Button
              type="button"
              variant="outline"
              onClick={() => setDialogOpen(false)}
            >
              Cancel
            </Button>
            <Button type="button" onClick={handleSave} disabled={isSaving}>
              {isSaving && <Loader2 className="mr-2 h-4 w-4 animate-spin" />}
              {editingId ? "Update" : "Create"}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </Card>
  );
}
