"use client";

import { useCallback, useEffect, useState } from "react";
import { AppShell } from "@/components/AppShell";
import { useCan } from "@/lib/abilities";
import { formatDateTime } from "@/lib/labels";
import {
  NOTIFICATION_STATUS_COLORS,
  NOTIFICATION_STATUS_LABELS,
  NOTIFICATION_SERVICIO_LABELS,
  NOTIFICATION_TYPE_LABELS,
} from "@/lib/labels";
import {
  getNotificationStats,
  listNotificationLog,
  runAccountStatus,
  runOutstandingPayments,
  runPaymentConfirmation,
  runTrustConfirmation,
} from "@/lib/api";
import type {
  NotificationFlags,
  NotificationJobResponse,
  NotificationLogPage,
  NotificationStats,
  NotificationStatus,
} from "@/lib/api";

/**
 * Mass email notifications UI. Manual triggers for the four jobs plus a
 * paged log browser. The page is gated on `notification:send`; a STAFF
 * viewer sees the read-only log table but not the trigger buttons.
 */

export default function NotificacionesPage() {
  return (
    <AppShell>
      <Notificaciones />
    </AppShell>
  );
}

type JobKind = "outstanding" | "payment" | "account" | "trust";

interface JobDef {
  kind: JobKind;
  title: string;
  endpoint: string;
  description: string;
  servicio: "Clientes" | "Fideicomiso";
  flagsHint?: string;
}

const JOBS: JobDef[] = [
  {
    kind: "outstanding",
    title: "Pagos pendientes",
    endpoint: "sendOutstandingPaymentAlerts",
    servicio: "Clientes",
    description:
      "Clientes con al menos un movimiento marcado como pendiente (outstanding). Equivale a la columna NOPAGO=1 del antiguo datosfreak.",
  },
  {
    kind: "payment",
    title: "Confirmación de pago",
    endpoint: "sendPaymentConfirmation",
    servicio: "Clientes",
    description:
      "Clientes con un crédito (abono) en las últimas 24 horas. Un correo por cliente con el pago más reciente.",
  },
  {
    kind: "account",
    title: "Estado de cuenta",
    endpoint: "sendAccountStatus",
    servicio: "Clientes",
    description:
      "Alerta amarilla (DEBAJO DEL TIPO) los miércoles y roja (EN ROJO) lunes/miércoles/viernes. El flag ignoreDayRestriction salta los gates.",
    flagsHint: "Solo este job respeta ignoreDayRestriction y useEmailLimit.",
  },
  {
    kind: "trust",
    title: "Confirmación fideicomiso",
    endpoint: "sendConfirmTrustPayment",
    servicio: "Fideicomiso",
    description:
      "Clientes con TrustAccount que recibieron un crédito en el dominio TRUST en las últimas 24 horas.",
  },
];

function Notificaciones() {
  const allowed = useCan("notification:send");

  const [flags, setFlags] = useState<NotificationFlags>({ debug: true });
  const [stats, setStats] = useState<NotificationStats | null>(null);
  const [log, setLog] = useState<NotificationLogPage | null>(null);
  const [logFilter, setLogFilter] = useState<{
    status?: NotificationStatus;
    view: "all" | "sent" | "failed" | "skipped";
  }>({ view: "all" });
  const [logPage, setLogPage] = useState(1);
  const [busy, setBusy] = useState<JobKind | null>(null);
  const [lastResult, setLastResult] = useState<NotificationJobResponse | null>(null);
  const [error, setError] = useState<string | null>(null);

  const refresh = useCallback(async () => {
    try {
      const [s, l] = await Promise.all([
        getNotificationStats(),
        listNotificationLog({
          page: logPage,
          pageSize: 50,
          status: logFilter.status,
          view: logFilter.view === "all" ? undefined : logFilter.view,
        }),
      ]);
      setStats(s);
      setLog(l);
      setError(null);
    } catch (e) {
      setError(e instanceof Error ? e.message : String(e));
    }
  }, [logPage, logFilter]);

  useEffect(() => {
    void refresh();
  }, [refresh]);

  const run = useCallback(
    async (job: JobDef) => {
      if (!allowed) return;
      setBusy(job.kind);
      setError(null);
      try {
        let res: NotificationJobResponse;
        if (job.kind === "outstanding") res = await runOutstandingPayments(flags);
        else if (job.kind === "payment") res = await runPaymentConfirmation(flags);
        else if (job.kind === "account") res = await runAccountStatus(flags);
        else res = await runTrustConfirmation(flags);
        setLastResult(res);
        await refresh();
      } catch (e) {
        setError(e instanceof Error ? e.message : String(e));
      } finally {
        setBusy(null);
      }
    },
    [allowed, flags, refresh],
  );

  return (
    <div style={{ display: "grid", gap: 24, padding: 24 }}>
      <header>
        <h1 style={{ margin: 0 }}>Notificaciones masivas</h1>
        <p style={{ color: "#666", marginTop: 4 }}>
          Disparo manual de los cuatro envíos equivalentes a los scripts PHP
          de <code>email.notifications/</code>. Cada ejecución registra todas
          las filas (enviado, fallido, omitido) en <code>email_notification_log</code>.
        </p>
      </header>

      <section
        style={{
          background: "#fff",
          border: "1px solid #ddd",
          borderRadius: 8,
          padding: 16,
          display: "grid",
          gap: 12,
        }}
      >
        <strong>Flags del envío</strong>
        <label style={{ display: "flex", gap: 8, alignItems: "center" }}>
          <input
            type="checkbox"
            checked={!!flags.debug}
            disabled={!allowed}
            onChange={(e) => setFlags((f) => ({ ...f, debug: e.target.checked }))}
          />
          <span>
            <strong>debug</strong> — reescribe todos los destinatarios a{" "}
            <code>rmancinas@freakma.net</code>. Ningún cliente real recibe el
            correo mientras esté activo.
          </span>
        </label>
        <label style={{ display: "flex", gap: 8, alignItems: "center" }}>
          <input
            type="checkbox"
            checked={!!flags.ignoreDayRestriction}
            disabled={!allowed}
            onChange={(e) =>
              setFlags((f) => ({ ...f, ignoreDayRestriction: e.target.checked }))
            }
          />
          <span>
            <strong>ignoreDayRestriction</strong> — salta los gates de
            Mon/Wed/Fri del estado de cuenta (job 3). Útil para disparar en
            cualquier día sin esperar a la próxima corrida.
          </span>
        </label>
        <label style={{ display: "flex", gap: 8, alignItems: "center" }}>
          <input
            type="checkbox"
            checked={!!flags.useEmailLimit}
            disabled={!allowed}
            onChange={(e) =>
              setFlags((f) => ({ ...f, useEmailLimit: e.target.checked }))
            }
          />
          <span>
            <strong>useEmailLimit</strong> — pausa el job 3 cada 100 correos
            durante 1 hora. Vestigio de la era SMTP; SES no lo necesita.
          </span>
        </label>
      </section>

      <section
        style={{
          display: "grid",
          gridTemplateColumns: "repeat(auto-fit, minmax(280px, 1fr))",
          gap: 12,
        }}
      >
        {JOBS.map((j) => (
          <article
            key={j.kind}
            style={{
              background: "#fff",
              border: "1px solid #ddd",
              borderRadius: 8,
              padding: 16,
              display: "grid",
              gap: 8,
            }}
          >
            <header style={{ display: "flex", justifyContent: "space-between" }}>
              <strong>{j.title}</strong>
              <span style={{ fontSize: 12, color: "#666" }}>{j.servicio}</span>
            </header>
            <p style={{ margin: 0, color: "#444", fontSize: 13 }}>{j.description}</p>
            {j.flagsHint && (
              <p style={{ margin: 0, color: "#666", fontSize: 12, fontStyle: "italic" }}>
                {j.flagsHint}
              </p>
            )}
            <button
              type="button"
              disabled={!allowed || busy !== null}
              onClick={() => void run(j)}
              style={{
                padding: "8px 12px",
                background: !allowed || busy !== null ? "#bbb" : "#1f4eaf",
                color: "#fff",
                border: "none",
                borderRadius: 6,
                cursor: !allowed || busy !== null ? "not-allowed" : "pointer",
                fontWeight: 600,
              }}
            >
              {busy === j.kind ? "Ejecutando…" : "Ejecutar"}
            </button>
          </article>
        ))}
      </section>

      {!allowed && (
        <div
          style={{
            background: "#fff8e1",
            border: "1px solid #f1c40f",
            borderRadius: 8,
            padding: 12,
          }}
        >
          Tu rol no incluye <code>notification:send</code>. Solo puedes ver el
          registro. Para disparar envíos pide a un MANAGER/ADMIN.
        </div>
      )}

      {stats && (
        <section
          style={{
            background: "#fff",
            border: "1px solid #ddd",
            borderRadius: 8,
            padding: 16,
          }}
        >
          <strong>Estado del transporte</strong>
          <ul style={{ marginTop: 8, marginBottom: 0 }}>
            <li>
              SES configurado:{" "}
              <strong style={{ color: stats.transport.available ? "#1f7a3a" : "#b3261e" }}>
                {stats.transport.available ? "sí" : "no"}
              </strong>
              {stats.transport.devFallback && " (fallback dev: stdout)"}
            </li>
            <li>Último envío registrado: {stats.lastRun ? `${NOTIFICATION_TYPE_LABELS[stats.lastRun.notificationType]} — ${formatDateTime(stats.lastRun.sendDate)}` : "—"}</li>
            <li>
              Totales:{" "}
              {stats.byStatus.map((s) => (
                <span key={s.status} style={{ marginRight: 12 }}>
                  {NOTIFICATION_STATUS_LABELS[s.status]}: {s._count._all}
                </span>
              ))}
            </li>
          </ul>
        </section>
      )}

      {lastResult && (
        <section
          style={{
            background: "#eef6ff",
            border: "1px solid #b3d4fc",
            borderRadius: 8,
            padding: 12,
          }}
        >
          <strong>Última respuesta</strong>
          <pre style={{ margin: 0, fontSize: 12, overflow: "auto" }}>
            {JSON.stringify(lastResult, null, 2)}
          </pre>
        </section>
      )}

      {error && (
        <div
          style={{
            background: "#fdecea",
            border: "1px solid #b3261e",
            borderRadius: 8,
            padding: 12,
            color: "#b3261e",
          }}
        >
          {error}
        </div>
      )}

      <section
        style={{
          background: "#fff",
          border: "1px solid #ddd",
          borderRadius: 8,
          padding: 16,
        }}
      >
        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center" }}>
          <strong>Registro de envíos</strong>
          <div style={{ display: "flex", gap: 8 }}>
            {(["all", "sent", "failed", "skipped"] as const).map((v) => (
              <button
                key={v}
                type="button"
                onClick={() => {
                  setLogFilter({ view: v });
                  setLogPage(1);
                }}
                style={{
                  padding: "4px 10px",
                  background: logFilter.view === v ? "#1f4eaf" : "#eee",
                  color: logFilter.view === v ? "#fff" : "#333",
                  border: "none",
                  borderRadius: 4,
                  cursor: "pointer",
                  fontSize: 12,
                }}
              >
                {v === "all" ? "Todos" : v === "sent" ? "Enviados" : v === "failed" ? "Fallidos" : "Omitidos"}
              </button>
            ))}
          </div>
        </div>

        <table style={{ width: "100%", borderCollapse: "collapse", marginTop: 12 }}>
          <thead>
            <tr style={{ borderBottom: "2px solid #ddd" }}>
              <th style={{ textAlign: "left", padding: 6 }}>Fecha</th>
              <th style={{ textAlign: "left", padding: 6 }}>Tipo</th>
              <th style={{ textAlign: "left", padding: 6 }}>Servicio</th>
              <th style={{ textAlign: "left", padding: 6 }}>Cliente</th>
              <th style={{ textAlign: "left", padding: 6 }}>Email</th>
              <th style={{ textAlign: "left", padding: 6 }}>Estado</th>
              <th style={{ textAlign: "left", padding: 6 }}>Asunto</th>
              <th style={{ textAlign: "left", padding: 6 }}>Provider</th>
            </tr>
          </thead>
          <tbody>
            {log?.items.map((row) => (
              <tr key={row.id} style={{ borderBottom: "1px solid #eee" }}>
                <td style={{ padding: 6, fontSize: 12 }}>{formatDateTime(row.sendDate)}</td>
                <td style={{ padding: 6, fontSize: 12 }}>
                  {NOTIFICATION_TYPE_LABELS[row.notificationType]}
                  {row.level !== null && (row.level === 0 ? " (amarilla)" : " (roja)")}
                </td>
                <td style={{ padding: 6, fontSize: 12 }}>{NOTIFICATION_SERVICIO_LABELS[row.servicio]}</td>
                <td style={{ padding: 6, fontSize: 12 }}>{row.customerName}{row.debug ? " · debug" : ""}</td>
                <td style={{ padding: 6, fontSize: 12 }}>{row.customerEmail}</td>
                <td style={{ padding: 6, fontSize: 12, color: NOTIFICATION_STATUS_COLORS[row.status] }}>
                  {NOTIFICATION_STATUS_LABELS[row.status]}
                </td>
                <td style={{ padding: 6, fontSize: 12 }}>{row.subject}</td>
                <td style={{ padding: 6, fontSize: 11, color: "#666" }}>
                  {row.providerMessageId ?? row.error ?? "—"}
                </td>
              </tr>
            ))}
            {log && log.items.length === 0 && (
              <tr>
                <td colSpan={8} style={{ padding: 12, color: "#666", textAlign: "center" }}>
                  Sin envíos con el filtro actual.
                </td>
              </tr>
            )}
          </tbody>
        </table>

        {log && log.pageCount > 1 && (
          <div style={{ marginTop: 8, display: "flex", justifyContent: "space-between", alignItems: "center" }}>
            <span style={{ fontSize: 12, color: "#666" }}>
              {log.total} fila{log.total === 1 ? "" : "s"} · página {log.page} de {log.pageCount}
            </span>
            <div style={{ display: "flex", gap: 4 }}>
              <button
                type="button"
                disabled={log.page <= 1}
                onClick={() => setLogPage((p) => Math.max(1, p - 1))}
              >
                ←
              </button>
              <button
                type="button"
                disabled={log.page >= log.pageCount}
                onClick={() => setLogPage((p) => Math.min(log.pageCount, p + 1))}
              >
                →
              </button>
            </div>
          </div>
        )}
      </section>
    </div>
  );
}
