"use client";

import Link from "next/link";
import { useMemo, useRef, useState } from "react";
import type { ProposalView } from "@/lib/proposals/types";
import { getProposalStatusLabel } from "@/lib/proposals/status";
import { Button } from "@/components/ui/button";
import { Card, CardContent } from "@/components/ui/card";

type ProposalsManagementViewProps = {
  initialProposals: ProposalView[];
  initialSourceLicitationId?: string | null;
};

type ApiPayload = {
  ok?: boolean;
  error?: string;
  proposal?: ProposalView;
  proposals?: ProposalView[];
};

type DraftState = {
  title: string;
  issuingEntity: string;
  summary: string;
  status: ProposalView["status"];
};

const STATUS_OPTIONS: ProposalView["status"][] = ["DRAFT", "IN_PROGRESS", "SUBMITTED", "ARCHIVED"];

function statusTone(status: ProposalView["status"]) {
  if (status === "SUBMITTED") {
    return "border-[#bce5d1] bg-[#ebf9f1] text-[#1e8b63]";
  }

  if (status === "IN_PROGRESS") {
    return "border-[#c6d9f4] bg-[#ebf3ff] text-[#1f4f95]";
  }

  if (status === "ARCHIVED") {
    return "border-[#d8e0ed] bg-[#f3f6fb] text-[#566b8f]";
  }

  return "border-[#f0dfb8] bg-[#fff9ea] text-[#946807]";
}

function formatDate(value: string) {
  const parsed = new Date(value);
  if (Number.isNaN(parsed.getTime())) {
    return "Fecha no disponible";
  }

  return parsed.toLocaleString("es-MX", {
    day: "2-digit",
    month: "short",
    year: "numeric",
    hour: "2-digit",
    minute: "2-digit",
  });
}

export function ProposalsManagementView({ initialProposals, initialSourceLicitationId }: ProposalsManagementViewProps) {
  const [proposals, setProposals] = useState<ProposalView[]>(initialProposals);
  const [query, setQuery] = useState("");
  const [isCreateOpen, setIsCreateOpen] = useState(false);
  const [isSubmitting, setIsSubmitting] = useState(false);
  const [message, setMessage] = useState<string | null>(null);
  const [errorMessage, setErrorMessage] = useState<string | null>(null);
  const [drafts, setDrafts] = useState<Record<string, DraftState>>(() =>
    Object.fromEntries(
      initialProposals.map((proposal) => [
        proposal.id,
        {
          title: proposal.title,
          issuingEntity: proposal.issuingEntity,
          summary: proposal.summary,
          status: proposal.status,
        },
      ]),
    ),
  );

  const [newProposal, setNewProposal] = useState({
    title: "",
    issuingEntity: "",
    summary: "",
    sourceLicitationId: initialSourceLicitationId ?? "",
  });

  const inputRefs = useRef<Record<string, HTMLInputElement | null>>({});

  const filteredProposals = useMemo(() => {
    const normalized = query.trim().toLowerCase();

    if (!normalized) {
      return proposals;
    }

    return proposals.filter((proposal) => {
      const composed = `${proposal.title} ${proposal.issuingEntity} ${proposal.summary}`.toLowerCase();
      return composed.includes(normalized);
    });
  }, [proposals, query]);

  function setDraftField(id: string, field: keyof DraftState, value: string) {
    setDrafts((previous) => ({
      ...previous,
      [id]: {
        ...(previous[id] ?? {
          title: "",
          issuingEntity: "",
          summary: "",
          status: "DRAFT",
        }),
        [field]: value,
      },
    }));
  }

  async function reloadProposals(nextQuery = "") {
    const response = await fetch(`/api/proposals?q=${encodeURIComponent(nextQuery)}`);
    const payload = (await response.json().catch(() => ({}))) as ApiPayload;

    if (!response.ok || !payload.ok || !payload.proposals) {
      throw new Error(payload.error ?? "No fue posible obtener propuestas.");
    }

    setProposals(payload.proposals);
    setDrafts(
      Object.fromEntries(
        payload.proposals.map((proposal) => [
          proposal.id,
          {
            title: proposal.title,
            issuingEntity: proposal.issuingEntity,
            summary: proposal.summary,
            status: proposal.status,
          },
        ]),
      ),
    );
  }

  async function createProposal() {
    setErrorMessage(null);
    setMessage(null);
    setIsSubmitting(true);

    try {
      const response = await fetch("/api/proposals", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify(newProposal),
      });

      const payload = (await response.json().catch(() => ({}))) as ApiPayload;

      if (!response.ok || !payload.ok || !payload.proposal) {
        setErrorMessage(payload.error ?? "No fue posible crear la propuesta.");
        return;
      }

      const createdProposal = payload.proposal as ProposalView;
      setProposals((previous) => [createdProposal, ...previous]);
      setDrafts((previous) => ({
        ...previous,
        [createdProposal.id]: {
          title: createdProposal.title,
          issuingEntity: createdProposal.issuingEntity,
          summary: createdProposal.summary,
          status: createdProposal.status,
        },
      }));
      setNewProposal({
        title: "",
        issuingEntity: "",
        summary: "",
        sourceLicitationId: initialSourceLicitationId ?? "",
      });
      setIsCreateOpen(false);
      setMessage("Propuesta creada correctamente.");
    } catch {
      setErrorMessage("No fue posible crear la propuesta.");
    } finally {
      setIsSubmitting(false);
    }
  }

  async function saveProposal(id: string) {
    const draft = drafts[id];

    if (!draft) {
      return;
    }

    setErrorMessage(null);
    setMessage(null);

    try {
      const response = await fetch(`/api/proposals/${id}`, {
        method: "PATCH",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify(draft),
      });

      const payload = (await response.json().catch(() => ({}))) as ApiPayload;

      if (!response.ok || !payload.ok || !payload.proposal) {
        setErrorMessage(payload.error ?? "No fue posible guardar cambios.");
        return;
      }

      const updatedProposal = payload.proposal as ProposalView;
      setProposals((previous) => previous.map((proposal) => (proposal.id === id ? updatedProposal : proposal)));
      setMessage("Cambios guardados.");
    } catch {
      setErrorMessage("No fue posible guardar cambios.");
    }
  }

  async function deleteProposal(id: string) {
    setErrorMessage(null);
    setMessage(null);

    try {
      const response = await fetch(`/api/proposals/${id}`, {
        method: "DELETE",
      });

      const payload = (await response.json().catch(() => ({}))) as ApiPayload;

      if (!response.ok || !payload.ok) {
        setErrorMessage(payload.error ?? "No fue posible eliminar la propuesta.");
        return;
      }

      setProposals((previous) => previous.filter((proposal) => proposal.id !== id));
      setDrafts((previous) => {
        const next = { ...previous };
        delete next[id];
        return next;
      });
      setMessage("Propuesta eliminada.");
    } catch {
      setErrorMessage("No fue posible eliminar la propuesta.");
    }
  }

  async function uploadDocument(id: string, file: File) {
    setErrorMessage(null);
    setMessage(null);

    try {
      const formData = new FormData();
      formData.append("file", file);

      const response = await fetch(`/api/proposals/${id}/documents`, {
        method: "POST",
        body: formData,
      });

      const payload = (await response.json().catch(() => ({}))) as ApiPayload;

      if (!response.ok || !payload.ok || !payload.proposal) {
        setErrorMessage(payload.error ?? "No fue posible subir el documento.");
        return;
      }

      const updatedProposal = payload.proposal as ProposalView;
      setProposals((previous) => previous.map((proposal) => (proposal.id === id ? updatedProposal : proposal)));
      setDrafts((previous) => ({
        ...previous,
        [id]: {
          ...(previous[id] ?? {
            title: updatedProposal.title,
            issuingEntity: updatedProposal.issuingEntity,
            summary: updatedProposal.summary,
            status: updatedProposal.status,
          }),
          status: updatedProposal.status,
        },
      }));
      setMessage("Documento subido correctamente.");
    } catch {
      setErrorMessage("No fue posible subir el documento.");
    }
  }

  async function deleteDocument(proposalId: string, documentId: string) {
    setErrorMessage(null);
    setMessage(null);

    try {
      const response = await fetch(`/api/proposals/${proposalId}/documents/${documentId}`, {
        method: "DELETE",
      });
      const payload = (await response.json().catch(() => ({}))) as ApiPayload;

      if (!response.ok || !payload.ok) {
        setErrorMessage(payload.error ?? "No fue posible eliminar el documento.");
        return;
      }

      await reloadProposals(query);
      setMessage("Documento eliminado.");
    } catch {
      setErrorMessage("No fue posible eliminar el documento.");
    }
  }

  return (
    <div className="space-y-4">
      <section className="flex flex-wrap items-center justify-between gap-3">
        <label className="w-full max-w-2xl space-y-1 text-sm font-semibold text-[#314764]">
          Buscar por titulo o entidad
          <input
            value={query}
            onChange={(event) => setQuery(event.target.value)}
            placeholder="Buscar por titulo o entidad..."
            className="h-12 w-full rounded-xl border border-[#cfd8e6] bg-white px-4 text-base"
          />
        </label>

        <Button size="lg" className="rounded-2xl px-6" onClick={() => setIsCreateOpen(true)}>
          + Nueva Propuesta
        </Button>
      </section>

      {errorMessage ? <p className="rounded-xl border border-[#efc4c4] bg-[#fff1f1] px-3 py-2 text-sm text-[#ad3f3f]">{errorMessage}</p> : null}
      {message ? <p className="rounded-xl border border-[#bde5ce] bg-[#ecf9f1] px-3 py-2 text-sm text-[#1f7f4f]">{message}</p> : null}

      {filteredProposals.length === 0 ? (
        <Card className="border-[#cfd8e7]">
          <CardContent className="py-16 text-center">
            <p className="text-3xl font-semibold text-[#162748] [font-family:var(--font-display)] md:text-4xl">No hay propuestas</p>
            <p className="mx-auto mt-2 max-w-3xl text-base text-[#5f7090] md:text-lg">Comienza creando tu primera propuesta de licitacion. El asistente te guiara paso a paso.</p>
            <Button className="mt-6 rounded-2xl px-8" size="lg" onClick={() => setIsCreateOpen(true)}>
              + Crear Primera Propuesta
            </Button>
          </CardContent>
        </Card>
      ) : (
        <section className="grid gap-4 xl:grid-cols-2">
          {filteredProposals.map((proposal) => {
            const draft = drafts[proposal.id] ?? {
              title: proposal.title,
              issuingEntity: proposal.issuingEntity,
              summary: proposal.summary,
              status: proposal.status,
            };

            return (
              <article key={proposal.id} className="rounded-2xl border border-[#d7dfed] bg-white p-5">
                <div className="flex flex-wrap items-start justify-between gap-3">
                  <div>
                    <p className="text-xs font-semibold uppercase tracking-[0.08em] text-[#5d7091]">Actualizada {formatDate(proposal.updatedAt)}</p>
                    <h3 className="mt-1 text-2xl font-semibold text-[#14264a]">{proposal.title}</h3>
                    <p className="mt-1 text-xs font-semibold text-[#60718f]">
                      Paso {proposal.currentStep}/6 · {proposal.completionPercent}% completado
                    </p>
                    {proposal.readyForSubmissionAt ? (
                      <p className="mt-1 text-xs font-semibold text-[#1f8b63]">Lista para envio desde {formatDate(proposal.readyForSubmissionAt)}</p>
                    ) : null}
                  </div>
                  <span className={`inline-flex rounded-full border px-3 py-1 text-sm font-semibold ${statusTone(draft.status)}`}>
                    {getProposalStatusLabel(draft.status)}
                  </span>
                </div>

                <div className="mt-4 grid gap-3">
                  <label className="space-y-1 text-sm font-semibold text-[#33415c]">
                    Titulo
                    <input
                      value={draft.title}
                      onChange={(event) => setDraftField(proposal.id, "title", event.target.value)}
                      className="h-10 w-full rounded-lg border border-[#cfd8e6] px-3 text-sm"
                    />
                  </label>

                  <label className="space-y-1 text-sm font-semibold text-[#33415c]">
                    Entidad emisora
                    <input
                      value={draft.issuingEntity}
                      onChange={(event) => setDraftField(proposal.id, "issuingEntity", event.target.value)}
                      className="h-10 w-full rounded-lg border border-[#cfd8e6] px-3 text-sm"
                    />
                  </label>

                  <label className="space-y-1 text-sm font-semibold text-[#33415c]">
                    Resumen
                    <textarea
                      value={draft.summary}
                      onChange={(event) => setDraftField(proposal.id, "summary", event.target.value)}
                      rows={3}
                      className="w-full rounded-lg border border-[#cfd8e6] px-3 py-2 text-sm"
                    />
                  </label>

                  <label className="space-y-1 text-sm font-semibold text-[#33415c]">
                    Estatus
                    <select
                      value={draft.status}
                      onChange={(event) => setDraftField(proposal.id, "status", event.target.value)}
                      className="h-10 w-full rounded-lg border border-[#cfd8e6] px-3 text-sm"
                    >
                      {STATUS_OPTIONS.map((statusOption) => (
                        <option key={statusOption} value={statusOption}>
                          {getProposalStatusLabel(statusOption)}
                        </option>
                      ))}
                    </select>
                  </label>
                </div>

                <div className="mt-4 rounded-xl border border-[#d9e1ee] bg-[#f8fbff] p-3">
                  <div
                    className="flex min-h-[110px] cursor-pointer flex-col items-center justify-center rounded-xl border-2 border-dashed border-[#ccd7ea] bg-white text-center"
                    onDragOver={(event) => {
                      event.preventDefault();
                    }}
                    onDrop={(event) => {
                      event.preventDefault();
                      const dropped = event.dataTransfer.files?.[0];
                      if (dropped) {
                        void uploadDocument(proposal.id, dropped);
                      }
                    }}
                    onClick={() => inputRefs.current[proposal.id]?.click()}
                  >
                    <p className="text-sm font-semibold text-[#1f3051]">Arrastra un documento aqui</p>
                    <p className="text-xs text-[#627391]">o haz clic para seleccionar (PDF, DOC, DOCX, XLSX, JPG, PNG)</p>
                  </div>
                  <input
                    ref={(element) => {
                      inputRefs.current[proposal.id] = element;
                    }}
                    type="file"
                    className="hidden"
                    accept=".pdf,.doc,.docx,.xlsx,.jpg,.jpeg,.png"
                    onChange={(event) => {
                      const file = event.target.files?.[0];
                      if (file) {
                        void uploadDocument(proposal.id, file);
                      }
                      event.target.value = "";
                    }}
                  />

                  {proposal.documents.length > 0 ? (
                    <ul className="mt-3 space-y-2 text-sm text-[#4a5f84]">
                      {proposal.documents.map((document) => (
                        <li key={document.id} className="flex items-center justify-between gap-2 rounded-lg border border-[#d8e2ef] bg-white px-3 py-2">
                          <span>{document.fileName}</span>
                          <button
                            type="button"
                            className="text-xs font-semibold text-[#b23f50]"
                            onClick={() => {
                              void deleteDocument(proposal.id, document.id);
                            }}
                          >
                            Eliminar
                          </button>
                        </li>
                      ))}
                    </ul>
                  ) : (
                    <p className="mt-3 text-xs text-[#627391]">Sin documentos cargados.</p>
                  )}
                </div>

                <div className="mt-4 flex flex-wrap gap-2">
                  <Link href={`/gestion-licitaciones/${encodeURIComponent(proposal.id)}?autofill=1`}>
                    <Button size="sm">Continuar</Button>
                  </Link>
                  <Link href={`/gestion-contratos?proposalId=${encodeURIComponent(proposal.id)}&autocreate=1`}>
                    <Button size="sm" variant="secondary">
                      Crear contrato M8
                    </Button>
                  </Link>
                  <Button size="sm" onClick={() => void saveProposal(proposal.id)}>
                    Guardar cambios
                  </Button>
                  <Button size="sm" variant="secondary" onClick={() => void deleteProposal(proposal.id)}>
                    Eliminar propuesta
                  </Button>
                </div>
              </article>
            );
          })}
        </section>
      )}

      {isCreateOpen ? (
        <div className="fixed inset-0 z-50 flex items-center justify-center bg-[#0c1731]/55 p-4" role="dialog" aria-modal="true">
          <div className="w-full max-w-2xl rounded-2xl bg-white p-5">
            <h3 className="text-3xl font-semibold text-[#14264a] [font-family:var(--font-display)]">Nueva Propuesta</h3>

            <div className="mt-4 grid gap-3">
              <label className="space-y-1 text-sm font-semibold text-[#33415c]">
                Titulo
                <input
                  value={newProposal.title}
                  onChange={(event) => setNewProposal((previous) => ({ ...previous, title: event.target.value }))}
                  className="h-10 w-full rounded-lg border border-[#cfd8e6] px-3 text-sm"
                />
              </label>

              <label className="space-y-1 text-sm font-semibold text-[#33415c]">
                Entidad emisora
                <input
                  value={newProposal.issuingEntity}
                  onChange={(event) => setNewProposal((previous) => ({ ...previous, issuingEntity: event.target.value }))}
                  className="h-10 w-full rounded-lg border border-[#cfd8e6] px-3 text-sm"
                />
              </label>

              <label className="space-y-1 text-sm font-semibold text-[#33415c]">
                Resumen
                <textarea
                  value={newProposal.summary}
                  onChange={(event) => setNewProposal((previous) => ({ ...previous, summary: event.target.value }))}
                  rows={4}
                  className="w-full rounded-lg border border-[#cfd8e6] px-3 py-2 text-sm"
                />
              </label>

              <label className="space-y-1 text-sm font-semibold text-[#33415c]">
                ID de oportunidad origen (opcional)
                <input
                  value={newProposal.sourceLicitationId}
                  onChange={(event) => setNewProposal((previous) => ({ ...previous, sourceLicitationId: event.target.value }))}
                  className="h-10 w-full rounded-lg border border-[#cfd8e6] px-3 text-sm"
                  placeholder="Se autocompleta si vienes desde Modulo 3"
                />
              </label>
            </div>

            <div className="mt-5 flex justify-end gap-2">
              <Button variant="secondary" onClick={() => setIsCreateOpen(false)}>
                Cancelar
              </Button>
              <Button onClick={() => void createProposal()} disabled={isSubmitting}>
                {isSubmitting ? "Creando..." : "Crear propuesta"}
              </Button>
            </div>
          </div>
        </div>
      ) : null}
    </div>
  );
}
