"use client";

import { useCallback, useEffect, useState } from "react";
import { useCan } from "@/lib/abilities";
import {
  getNotificationSchedules,
  setNotificationSchedule,
  type NotificationSchedule,
  type NotificationSchedules,
  type ScheduleKind,
} from "@/lib/api";
import { formatDateTime } from "@/lib/labels";

/**
 * When the two automatic envíos run.
 *
 * Both cadences used to be source code: pólizas barría a las 06:00 desde un
 * `@Cron` en el servidor y servicios no corría solo en absoluto. Cambiar
 * cualquiera de los dos era un redeploy. Ahora se guardan en `app_settings` y
 * el servidor reinstala el job al guardar — sin reinicio.
 *
 * Los flags de la tarjeta de arriba NO se aplican aquí: una corrida
 * automática siempre manda de verdad.
 */

const KIND_LABEL: Record<ScheduleKind, string> = {
  servicios: "Servicios",
  polizas: "Pólizas",
};

const KIND_HINT: Record<ScheduleKind, string> = {
  servicios:
    "Ejecuta los cuatro envíos en orden, igual que el botón «Ejecutar todos». El estado de cuenta sigue respetando sus gates de lunes/miércoles/viernes.",
  polizas:
    "Barrido de avisos de renovación: 30 y 15 días antes del vencimiento, y 7 días después.",
};

const DAYS = [
  { value: 0, label: "Dom" },
  { value: 1, label: "Lun" },
  { value: 2, label: "Mar" },
  { value: 3, label: "Mié" },
  { value: 4, label: "Jue" },
  { value: 5, label: "Vie" },
  { value: 6, label: "Sáb" },
];

function timeValue(s: NotificationSchedule): string {
  return `${String(s.hour).padStart(2, "0")}:${String(s.minute).padStart(2, "0")}`;
}

function describe(s: NotificationSchedule): string {
  if (!s.enabled) return "Desactivado — solo se envía manualmente.";
  const days = s.weekdays.length
    ? s.weekdays
        .map((d) => DAYS.find((x) => x.value === d)?.label ?? d)
        .join(", ")
    : "todos los días";
  return `${days} a las ${timeValue(s)} (hora de Tijuana).`;
}

export function NotificationScheduleCard() {
  const canEdit = useCan("setting:manage");

  const [schedules, setSchedules] = useState<NotificationSchedules | null>(null);
  const [drafts, setDrafts] = useState<Partial<Record<ScheduleKind, NotificationSchedule>>>({});
  const [editing, setEditing] = useState<ScheduleKind | null>(null);
  const [saving, setSaving] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [saved, setSaved] = useState<ScheduleKind | null>(null);

  const load = useCallback(async () => {
    try {
      setSchedules(await getNotificationSchedules());
      setError(null);
    } catch (e) {
      setError(e instanceof Error ? e.message : String(e));
    }
  }, []);

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

  function startEdit(kind: ScheduleKind) {
    if (!schedules) return;
    setDrafts((d) => ({ ...d, [kind]: { ...schedules[kind].value } }));
    setEditing(kind);
    setSaved(null);
    setError(null);
  }

  async function save(kind: ScheduleKind) {
    const draft = drafts[kind];
    if (!draft) return;
    setSaving(true);
    setError(null);
    try {
      const result = await setNotificationSchedule(kind, draft);
      setSchedules((prev) => (prev ? { ...prev, [kind]: result } : prev));
      setEditing(null);
      setSaved(kind);
    } catch (e) {
      setError(e instanceof Error ? e.message : String(e));
    } finally {
      setSaving(false);
    }
  }

  if (!schedules) {
    return (
      <section className="card" style={{ padding: 20 }}>
        <h2 className="section-title">Programación de envíos</h2>
        {error ? (
          <div className="state-box state-error" style={{ marginTop: 12 }}>
            {error}
          </div>
        ) : (
          <p className="muted small" style={{ marginTop: 8, marginBottom: 0 }}>
            Cargando…
          </p>
        )}
      </section>
    );
  }

  return (
    <section className="card" style={{ padding: 20 }}>
      <h2 className="section-title">Programación de envíos</h2>
      <p className="muted small" style={{ marginTop: 4, marginBottom: 0, maxWidth: 660 }}>
        Cuándo corre solo cada envío. Los cambios aplican de inmediato, sin
        reiniciar el servidor. Una corrida automática nunca usa los flags de
        arriba: siempre manda a los clientes reales.
      </p>

      {error && (
        <div className="state-box state-error" style={{ marginTop: 12 }}>
          {error}
        </div>
      )}

      <div style={{ display: "grid", gap: 12, marginTop: 14 }}>
        {(Object.keys(KIND_LABEL) as ScheduleKind[]).map((kind) => {
          const current = schedules[kind];
          const draft = drafts[kind];
          const isEditing = editing === kind && draft;

          return (
            <article
              key={kind}
              style={{
                border: "1px solid var(--line)",
                borderRadius: "var(--radius-sm)",
                padding: 14,
              }}
            >
              <div
                style={{
                  display: "flex",
                  justifyContent: "space-between",
                  alignItems: "flex-start",
                  gap: 12,
                  flexWrap: "wrap",
                }}
              >
                <div>
                  <strong>{KIND_LABEL[kind]}</strong>
                  <p className="muted small" style={{ margin: "4px 0 0", maxWidth: 560 }}>
                    {KIND_HINT[kind]}
                  </p>
                </div>
                {canEdit && !isEditing && (
                  <button
                    type="button"
                    className="btn btn-outline btn-sm"
                    onClick={() => startEdit(kind)}
                  >
                    Editar
                  </button>
                )}
              </div>

              {isEditing ? (
                <div style={{ marginTop: 12 }}>
                  <label
                    className="field"
                    style={{ display: "flex", gap: 8, alignItems: "center", marginBottom: 10 }}
                  >
                    <input
                      type="checkbox"
                      checked={draft.enabled}
                      disabled={saving}
                      onChange={(e) =>
                        setDrafts((d) => ({
                          ...d,
                          [kind]: { ...draft, enabled: e.target.checked },
                        }))
                      }
                    />
                    <span className="small">
                      <strong>Corrida automática activada</strong>
                    </span>
                  </label>

                  <label className="field" style={{ maxWidth: 160, marginBottom: 10 }}>
                    <span className="field-label">Hora (Tijuana)</span>
                    <input
                      className="input"
                      type="time"
                      value={timeValue(draft)}
                      disabled={saving || !draft.enabled}
                      onChange={(e) => {
                        const [h, m] = e.target.value.split(":").map(Number);
                        setDrafts((d) => ({
                          ...d,
                          [kind]: {
                            ...draft,
                            hour: Number.isFinite(h) ? h : draft.hour,
                            minute: Number.isFinite(m) ? m : draft.minute,
                          },
                        }));
                      }}
                    />
                  </label>

                  <div className="field" style={{ marginBottom: 10 }}>
                    <span className="field-label">
                      Días (ninguno seleccionado = todos los días)
                    </span>
                    <div style={{ display: "flex", gap: 6, flexWrap: "wrap", marginTop: 4 }}>
                      {DAYS.map((d) => {
                        const on = draft.weekdays.includes(d.value);
                        return (
                          <button
                            key={d.value}
                            type="button"
                            className={`btn btn-sm ${on ? "btn-primary" : "btn-outline"}`}
                            disabled={saving || !draft.enabled}
                            onClick={() =>
                              setDrafts((prev) => ({
                                ...prev,
                                [kind]: {
                                  ...draft,
                                  weekdays: on
                                    ? draft.weekdays.filter((x) => x !== d.value)
                                    : [...draft.weekdays, d.value].sort(),
                                },
                              }))
                            }
                          >
                            {d.label}
                          </button>
                        );
                      })}
                    </div>
                  </div>

                  <div className="row-actions">
                    <button
                      type="button"
                      className="btn btn-primary btn-sm"
                      disabled={saving}
                      onClick={() => void save(kind)}
                    >
                      {saving ? "Guardando…" : "Guardar"}
                    </button>
                    <button
                      type="button"
                      className="btn btn-outline btn-sm"
                      disabled={saving}
                      onClick={() => {
                        setEditing(null);
                        setError(null);
                      }}
                    >
                      Cancelar
                    </button>
                  </div>
                </div>
              ) : (
                <div style={{ marginTop: 10 }}>
                  <p className="small" style={{ margin: 0 }}>
                    {describe(current.value)}
                  </p>
                  <p className="section-note" style={{ marginTop: 6, marginBottom: 0 }}>
                    <code>{current.cron}</code>
                    {current.nextRun &&
                      ` · próxima corrida: ${formatDateTime(current.nextRun)}`}
                    {current.source === "default" &&
                      " · valor por omisión, nadie lo ha cambiado"}
                    {current.updatedAt &&
                      ` · última edición: ${formatDateTime(current.updatedAt)}`}
                    {saved === kind && " · guardado"}
                  </p>
                </div>
              )}
            </article>
          );
        })}
      </div>

      {!canEdit && (
        <p className="section-note" style={{ marginTop: 12, marginBottom: 0 }}>
          Solo un ADMIN puede cambiar la programación.
        </p>
      )}
    </section>
  );
}
