"use client";

import { Fragment, type ReactNode, useActionState, useEffect, useState } from "react";
import { EstadoDocumento, RoleName, TipoDocumento } from "@prisma/client";
import { Check, Download, Eye, Trash2, Upload, X } from "lucide-react";
import { toast } from "sonner";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { nativeSelectClassName } from "@/components/fichas/form-fields";
import { deleteDocumentoFormAction, uploadDocumentoAction, validateDocumentoFormAction } from "@/server/actions/fichas";
import { initialState } from "@/server/actions/action-state";
import type { FichaDetail } from "@/server/queries/fichas";
import { cn } from "@/lib/utils";
import { formatDateCL, formatDateTimeCL } from "@/lib/date-format";
import { badgeClassForEstadoDocumento } from "@/lib/state-variants";

const tipoDocumentoOptions = [
  { value: TipoDocumento.RSH, label: "Registro Social de Hogares" },
  { value: TipoDocumento.CUENTA_LUZ, label: "Cuenta de luz" },
  { value: TipoDocumento.CEDULA_IDENTIDAD, label: "Cédula de identidad" },
  { value: TipoDocumento.ESCRITURA, label: "Escritura" },
  { value: TipoDocumento.RESOLUCION, label: "Resolucion" },
  { value: TipoDocumento.CERTIFICADO, label: "Certificado" },
  { value: TipoDocumento.FOTO_VIVIENDA, label: "Fotografía vivienda" },
  { value: TipoDocumento.FOTO_TERRENO, label: "Fotografía terreno" },
  { value: TipoDocumento.OTRO, label: "Otro documento" },
];

function formatBytes(value: number) {
  if (value < 1024) return `${value} B`;
  if (value < 1024 * 1024) return `${(value / 1024).toFixed(1)} KB`;
  return `${(value / 1024 / 1024).toFixed(1)} MB`;
}

function tipoDocumentoLabel(tipo: TipoDocumento) {
  return tipoDocumentoOptions.find((option) => option.value === tipo)?.label ?? tipo;
}

function saveDocumentsProgress() {
  toast.success("Avance guardado.");
}

function DocumentoActions({
  documento,
  currentUserId,
  currentUserRole,
  canUpload,
  setDocumentoToDelete,
}: {
  documento: FichaDetail["documentos"][number];
  currentUserId: string;
  currentUserRole: RoleName;
  canUpload: boolean;
  setDocumentoToDelete: (documento: { id: string; nombreArchivo: string }) => void;
}) {
  const actions: { key: string; node: ReactNode }[] = [
    {
      key: "ver",
      node: (
        <Button asChild size="sm" variant="secondary">
          <a href={`/api/documentos/${documento.id}/view`} target="_blank" rel="noopener noreferrer">
            <Eye className="h-4 w-4" />
            Ver
          </a>
        </Button>
      ),
    },
    {
      key: "descargar",
      node: (
        <Button asChild size="sm" variant="outline">
          <a href={`/api/documentos/${documento.id}/download`}>
            <Download className="h-4 w-4" />
            Descargar
          </a>
        </Button>
      ),
    },
  ];

  if (currentUserRole === RoleName.ADMIN || (canUpload && documento.uploadedBy.id === currentUserId)) {
    actions.push({
      key: "eliminar",
      node: (
        <Button
          type="button"
          size="sm"
          variant="destructive"
          onClick={() => setDocumentoToDelete({ id: documento.id, nombreArchivo: documento.nombreArchivo })}
        >
          <Trash2 className="h-4 w-4" />
          Eliminar
        </Button>
      ),
    });
  }

  return (
    <div className="flex flex-wrap gap-2 xl:justify-end">
      {actions.map((action) => (
        <Fragment key={action.key}>{action.node}</Fragment>
      ))}
    </div>
  );
}

export function DocumentosPanel({
  ficha,
  currentUserId,
  currentUserRole,
  canUpload,
  canValidate,
}: {
  ficha: FichaDetail;
  currentUserId: string;
  currentUserRole: RoleName;
  canUpload: boolean;
  canValidate: boolean;
}) {
  const [state, action] = useActionState(uploadDocumentoAction.bind(null, ficha.id), initialState);
  const [deleteState, deleteAction] = useActionState(deleteDocumentoFormAction, initialState);
  const [documentoToDelete, setDocumentoToDelete] = useState<{ id: string; nombreArchivo: string } | null>(null);

  useEffect(() => {
    if (!state.message) return;
    if (state.ok) toast.success(state.message);
    else toast.error(state.message);
  }, [state]);

  useEffect(() => {
    if (!deleteState.message) return;
    if (deleteState.ok) {
      toast.success(deleteState.message);
      window.setTimeout(() => setDocumentoToDelete(null), 0);
    } else {
      toast.error(deleteState.message);
    }
  }, [deleteState]);

  return (
    <Card>
      <CardHeader>
        <CardTitle>Documentos</CardTitle>
      </CardHeader>
      <CardContent className="space-y-4">
        {canUpload ? (
          <form action={action} className="grid gap-4 rounded-md border border-border bg-muted p-4 md:grid-cols-[240px_1fr_auto] md:items-end">
            <div className="space-y-2">
              <Label htmlFor="tipo">Tipo de documento</Label>
              <select id="tipo" name="tipo" defaultValue="" className={nativeSelectClassName}>
                <option value="">Seleccione</option>
                {tipoDocumentoOptions.map((option) => (
                  <option key={option.value} value={option.value}>
                    {option.label}
                  </option>
                ))}
              </select>
            </div>
            <div className="space-y-2">
              <Label htmlFor="archivo">Archivo</Label>
              <Input id="archivo" name="archivo" type="file" accept=".pdf,.jpg,.jpeg,.png,.docx,.xlsx" />
            </div>
            <Button type="submit">
              <Upload className="h-4 w-4" />
              Subir
            </Button>
          </form>
        ) : null}

        <div className="overflow-hidden rounded-md border border-border">
          <div className="grid grid-cols-1 divide-y divide-border bg-card">
            {ficha.documentos.length === 0 ? (
              <p className="p-4 text-sm text-muted-foreground">No hay documentos cargados.</p>
            ) : (
              ficha.documentos.map((documento) => (
                <div key={documento.id} className="grid gap-4 p-4 xl:grid-cols-[1fr_220px_320px] xl:items-start">
                  <div className="space-y-2">
                    <div className="flex flex-wrap items-center gap-2">
                      <p className="font-medium">{documento.nombreArchivo}</p>
                      <Badge className={cn("w-fit", badgeClassForEstadoDocumento(documento.estado))}>
                        {documento.estado}
                      </Badge>
                    </div>
                    <div className="grid gap-1 text-xs text-muted-foreground sm:grid-cols-2">
                      <p>Tipo: {tipoDocumentoLabel(documento.tipo)}</p>
                      <p>Tamaño: {formatBytes(documento.size)}</p>
                      <p>MIME: {documento.mimeType}</p>
                      <p>Fecha de subida: {formatDateCL(documento.createdAt)}</p>
                      <p>Subido por: {documento.uploadedBy.name}</p>
                      <p>{documento.validatedBy ? `Validador: ${documento.validatedBy.name}` : "Sin validar"}</p>
                      {documento.validatedAt ? (
                        <p>Fecha validación: {formatDateTimeCL(documento.validatedAt)}</p>
                      ) : null}
                    </div>
                    {documento.observacionValidador ? (
                      <p className="rounded-md bg-muted p-2 text-xs text-muted-foreground">
                        Observación: {documento.observacionValidador}
                      </p>
                    ) : null}
                  </div>

                  <DocumentoActions
                    documento={documento}
                    currentUserId={currentUserId}
                    currentUserRole={currentUserRole}
                    canUpload={canUpload}
                    setDocumentoToDelete={setDocumentoToDelete}
                  />

                  {canValidate ? (
                    <div className="grid gap-2">
                      <form action={validateDocumentoFormAction} className="grid gap-2 sm:grid-cols-[1fr_auto]">
                        <input type="hidden" name="documentoId" value={documento.id} />
                        <input type="hidden" name="estado" value={EstadoDocumento.VALIDADO} />
                        <Input name="observacion" placeholder="Observación de validación" className="h-9" />
                        <Button size="sm" type="submit">
                          <Check className="h-4 w-4" />
                          Validar
                        </Button>
                      </form>
                      <form action={validateDocumentoFormAction} className="grid gap-2 sm:grid-cols-[1fr_auto]">
                        <input type="hidden" name="documentoId" value={documento.id} />
                        <input type="hidden" name="estado" value={EstadoDocumento.RECHAZADO} />
                        <Input name="observacion" placeholder="Motivo de rechazo" className="h-9" />
                        <Button size="sm" variant="destructive" type="submit">
                          <X className="h-4 w-4" />
                          Rechazar
                        </Button>
                      </form>
                    </div>
                  ) : null}
                </div>
              ))
            )}
          </div>
        </div>

        <div className="flex justify-end">
          <Button type="button" onClick={saveDocumentsProgress}>
            Guardar avance
          </Button>
        </div>

        <Dialog open={Boolean(documentoToDelete)} onOpenChange={(open) => !open && setDocumentoToDelete(null)}>
          <DialogContent>
            <DialogHeader>
              <DialogTitle>¿Eliminar documento?</DialogTitle>
              <DialogDescription>
                Esta acción quitará el documento de la ficha, pero quedará registro en auditoría.
              </DialogDescription>
            </DialogHeader>
            {documentoToDelete ? <p className="text-sm font-medium text-foreground">{documentoToDelete.nombreArchivo}</p> : null}
            <DialogFooter className="flex-col gap-2 sm:flex-row sm:justify-end">
              <Button type="button" variant="outline" onClick={() => setDocumentoToDelete(null)}>
                Cancelar
              </Button>
              {documentoToDelete ? (
                <form action={deleteAction}>
                  <input type="hidden" name="documentoId" value={documentoToDelete.id} />
                  <Button type="submit" variant="destructive" className="w-full sm:w-auto">
                    <Trash2 className="h-4 w-4" />
                    Eliminar
                  </Button>
                </form>
              ) : null}
            </DialogFooter>
          </DialogContent>
        </Dialog>
      </CardContent>
    </Card>
  );
}
