"use client";

import { useCallback, useEffect, useState } from "react";
import Link from "next/link";
import { AlertCircle, CalendarClock, Filter, Handshake, Loader2, Plus, RefreshCw, Search } from "lucide-react";
import { motion } from "framer-motion";
import Button from "@/components/ui/Button";
import Input from "@/components/ui/Input";
import { cn } from "@/lib/cn";
import { listCrmOportunidades, updateCrmOportunidad, listCrmConfigSla } from "@/lib/pb/crm";
import { CRM_ESTADOS_KANBAN, crmEstimatedValue, groupCrmByEstado, isCrmFollowUpDue } from "@/lib/crm/domain";
import { ESTADO_CRM_LABELS, PRIORIDAD_CRM_LABELS, type CrmOportunidad, type EstadoCrm } from "@/lib/types/crm";
import { dateShort, money } from "@/lib/format";

export default function CrmPage() {
  const [items, setItems] = useState<CrmOportunidad[]>([]);
  const [slas, setSlas] = useState<Record<string, number>>({});
  const [estado, setEstado] = useState<EstadoCrm | "todos" | "activos">("activos");
  const [search, setSearch] = useState("");
  const [loading, setLoading] = useState(true);
  const [busyId, setBusyId] = useState("");
  const [err, setErr] = useState("");

  const reload = useCallback(async () => {
    setLoading(true);
    setErr("");
    try {
      const [res, slaList] = await Promise.all([
        listCrmOportunidades({ estado, search }),
        listCrmConfigSla(),
      ]);
      setItems(res.items);
      const map: Record<string, number> = {};
      slaList.forEach((s) => {
        map[s.estado] = s.horas_limite;
      });
      setSlas(map);
    } catch (e) {
      setErr((e as Error).message || "No se pudo cargar CRM");
    } finally {
      setLoading(false);
    }
  }, [estado, search]);

  useEffect(() => {
    const t = setTimeout(reload, search ? 250 : 0);
    return () => clearTimeout(t);
  }, [reload, search]);

  async function moveOportunidad(item: CrmOportunidad, nextEstado: EstadoCrm) {
    if (item.estado === nextEstado) return;
    setBusyId(item.id);
    setErr("");
    try {
      const updated = await updateCrmOportunidad(item.id, { estado: nextEstado });
      setItems((prev) => prev.map((current) => (current.id === item.id ? updated : current)));
    } catch (e) {
      setErr((e as Error).message || "No se pudo mover la oportunidad");
    } finally {
      setBusyId("");
    }
  }

  return (
    <div className="max-w-[1500px] space-y-4">
      <div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
        <div>
          <h1 className="flex items-center gap-2 text-2xl font-extrabold text-ink">
            <Handshake className="h-6 w-6 text-brand-dark" /> CRM
          </h1>
          <p className="text-sm text-ink-soft">
            Seguimientos comerciales antes y después del presupuesto.
          </p>
        </div>
        <div className="flex flex-wrap items-center gap-2">
          <Button type="button" variant="secondary" onClick={reload} loading={loading}>
            <RefreshCw size={16} /> Actualizar
          </Button>
          <Link href="/crm/nuevo">
            <Button><Plus size={16} /> Nueva oportunidad</Button>
          </Link>
        </div>
      </div>

      <div className="card flex flex-col gap-3 p-4 md:flex-row md:items-end">
        <div className="min-w-0 flex-1">
          <Input
            label="Buscar"
            placeholder="Cliente, celular o trabajo"
            prefix={<Search size={16} />}
            value={search}
            onChange={(e) => setSearch(e.target.value)}
          />
        </div>
        <label className="flex flex-col gap-1.5">
          <span className="text-sm font-medium text-ink-soft">Estado</span>
          <div className="flex h-11 items-center gap-2 rounded-xl border border-line bg-surface px-3">
            <Filter size={16} className="text-faint" />
            <select
              value={estado}
              onChange={(e) => setEstado(e.target.value as EstadoCrm | "todos" | "activos")}
              className="min-w-44 bg-transparent text-ink outline-none"
            >
              <option value="activos">Activos</option>
              <option value="todos">Todos</option>
              {Object.entries(ESTADO_CRM_LABELS).map(([value, label]) => (
                <option key={value} value={value}>{label}</option>
              ))}
            </select>
          </div>
        </label>
      </div>

      {err && <div className="rounded-xl border border-red-200 bg-red-50 px-4 py-3 text-sm text-bad">{err}</div>}

      {loading ? (
        <div className="grid place-items-center py-20 text-faint"><Loader2 className="h-6 w-6 animate-spin" /></div>
      ) : items.length === 0 ? (
        <div className="card p-16 text-center">
          <Handshake size={32} className="mx-auto mb-3 text-faint" />
          <p className="mb-4 text-ink-soft">Sin oportunidades para mostrar.</p>
          <Link href="/crm/nuevo"><Button><Plus size={16} /> Crear oportunidad</Button></Link>
        </div>
      ) : (
        <CrmPipeline items={items} busyId={busyId} slas={slas} onMove={moveOportunidad} />
      )}
    </div>
  );
}

function CrmPipeline({
  items,
  busyId,
  slas,
  onMove,
}: {
  items: CrmOportunidad[];
  busyId: string;
  slas: Record<string, number>;
  onMove: (item: CrmOportunidad, estado: EstadoCrm) => void;
}) {
  const grouped = groupCrmByEstado(items);
  return (
    <div className="flex gap-3 overflow-x-auto pb-3">
      {CRM_ESTADOS_KANBAN.map((estado) => (
        <section key={estado} className="min-h-52 w-72 shrink-0 rounded-xl border border-line bg-surface p-3">
          <div className="mb-3 flex items-center justify-between gap-2">
            <h2 className="text-sm font-extrabold text-ink">{ESTADO_CRM_LABELS[estado]}</h2>
            <span className="rounded-full bg-canvas px-2 py-0.5 text-xs font-bold text-faint">{grouped[estado].length}</span>
          </div>
          <div className="space-y-2">
            {grouped[estado].map((item, i) => (
              <CrmCard key={item.id} item={item} index={i} busy={busyId === item.id} slas={slas} onMove={onMove} />
            ))}
          </div>
        </section>
      ))}
    </div>
  );
}

function CrmCard({
  item,
  index,
  busy,
  slas,
  onMove,
}: {
  item: CrmOportunidad;
  index: number;
  busy: boolean;
  slas: Record<string, number>;
  onMove: (item: CrmOportunidad, estado: EstadoCrm) => void;
}) {
  const slaLimit = slas[item.estado] ?? null;

  // Format stage duration
  const ref = item.fecha_cambio_estado || item.created;
  let durationText = "0h";
  let hoursTotal = 0;
  if (ref) {
    const diffMs = Date.now() - new Date(ref).getTime();
    const diffHours = Math.max(0, Math.floor(diffMs / (1000 * 60 * 60)));
    hoursTotal = diffHours;
    if (diffHours < 24) {
      durationText = `${diffHours}h`;
    } else {
      const days = Math.floor(diffHours / 24);
      const remainingHours = diffHours % 24;
      durationText = `${days}d ${remainingHours}h`;
    }
  }

  // Check if warning / SLA is exceeded
  const isClosed = ["ganado", "perdido"].includes(item.estado);
  const isOverSla = !isClosed && slaLimit !== null && hoursTotal >= slaLimit;

  return (
    <motion.article
      initial={{ opacity: 0, y: 4 }}
      animate={{ opacity: 1, y: 0 }}
      transition={{ delay: index * 0.01 }}
      className={cn(
        "rounded-lg border p-3 transition-colors shadow-xs relative",
        isOverSla
          ? "border-bad/40 bg-[#fff5f5] dark:bg-red-950/20"
          : "border-line bg-canvas"
      )}
    >
      <div className="flex items-start justify-between gap-1">
        <Link href={`/crm/${item.id}`} className="block font-extrabold text-ink hover:underline">
          {item.titulo}
        </Link>
        {isOverSla && (
          <span
            title={`Superó el límite de ${slaLimit}h en esta etapa`}
            className="shrink-0 rounded-full bg-bad/10 text-bad p-0.5 animate-pulse"
          >
            <AlertCircle size={14} />
          </span>
        )}
      </div>
      <p className="mt-0.5 truncate text-xs text-ink-soft">
        {item.expand?.cliente?.nombre || "Sin cliente"}
        {item.expand?.cliente?.celular ? ` · ${item.expand.cliente.celular}` : ""}
      </p>
      <div className="mt-2 flex items-center justify-between gap-2 text-xs">
        <span className="rounded-full bg-brand-soft px-2 py-0.5 font-bold text-brand-dark">
          {PRIORIDAD_CRM_LABELS[item.prioridad]}
        </span>
        <span className="font-extrabold tabular-nums text-ink">{money(crmEstimatedValue(item))}</span>
      </div>
      <div className="mt-2 flex items-center justify-between gap-2 text-xs">
        <span className={isCrmFollowUpDue(item) ? "font-bold text-bad" : "font-semibold text-faint"}>
          <CalendarClock size={13} className="mr-1 inline" />
          {item.proximo_contacto ? dateShort(item.proximo_contacto) : "Sin seguimiento"}
        </span>
        <span className="truncate text-faint">{item.expand?.presupuesto?.codigo || ""}</span>
      </div>

      <div className="mt-2.5 pt-2 border-t border-line/40 flex items-center justify-between text-[10px] text-faint">
        <span className={cn("font-medium", isOverSla ? "text-bad font-semibold" : "")}>
          ⏳ {durationText}
        </span>
        {slaLimit !== null && (
          <span>Límite: {slaLimit}h</span>
        )}
      </div>

      <select
        disabled={busy}
        value={item.estado}
        onChange={(e) => onMove(item, e.target.value as EstadoCrm)}
        className="mt-2 h-9 w-full rounded-lg border border-line bg-surface px-2 text-xs font-semibold text-ink outline-none focus:border-brand"
      >
        {CRM_ESTADOS_KANBAN.map((estado) => (
          <option key={estado} value={estado}>{ESTADO_CRM_LABELS[estado]}</option>
        ))}
      </select>
    </motion.article>
  );
}
