"use client";

import { FormEvent, useCallback, useEffect, useMemo, useRef, useState } from "react";
import { useRouter } from "next/navigation";
import AdminManagement from "./AdminManagement";
import DocumentsManagement from "./DocumentsManagement";
import MaintainersManagement from "./MaintainersManagement";
import BillingManagement from "./BillingManagement";
import OffersManagement from "./OffersManagement";
import MattersOverview from "./MattersManagement";
import PortalContentManagement from "./PortalContentManagement";
import TerritoryManagement from "./TerritoryManagement";
import EntityWorkspace, { WorkspaceHome } from "./EntityWorkspace";
import EditorialManagement from "./EditorialManagement";
import VerificationManagement from "./VerificationManagement";
import OperationsManagement from "./OperationsManagement";
import ReservationsManagement from "./ReservationsManagement";
import { dateTimeCL, panelLabel, panelValue } from "../lib/datetime";
import { userMessage } from "../lib/messages";

const apiBase = process.env.NEXT_PUBLIC_API_BASE_URL || "/api/v1";
type User = {
  id: number;
  email: string;
  nombres: string;
  apellidos: string;
  telefono?: string;
  roles: string[];
  permissions: string[];
  entidades?: { id: number; nombre_fantasia: string; capacidades?: string[]; rol_membresia?: string }[];
  notarias: { id: number; nombre_fantasia: string; rol_membresia?: string }[];
  contexto_entidad?: { entidad_id: number; capacidad: string } | null;
  mfa_habilitado: boolean;
  mfa_requerido: boolean;
};
type MenuKey =
  | "workspace"
  | "dashboard"
  | "documents"
  | "billing"
  | "admin"
  | "matters"
  | "offers"
  | "maintainers"
  | "content"
  | "editorial"
  | "verification"
  | "operations"
  | "reservations"
  | "territory"
  | "security"
  | "profile";
const AdminOverview = AdminManagement;

function workspaceCapabilityFromHost() {
  if (typeof window === "undefined") return "";
  return (
    {
      "notaria.documenta.cl": "NOTARIA",
      "cbr.documenta.cl": "CONSERVADOR",
      "archivero.documenta.cl": "ARCHIVERO",
    } as Record<string, string>
  )[window.location.hostname.toLowerCase()] || "";
}

function formatRutInput(value: string) {
  const clean = value.replace(/[^0-9kK]/g, "").toUpperCase();
  if (clean.length < 2) return clean;
  const body = clean.slice(0, -1).replace(/\B(?=(\d{3})+(?!\d))/g, ".");
  return `${body}-${clean.slice(-1)}`;
}
function apiMessage(
  detail: unknown,
  fallback = "No fue posible guardar los cambios.",
) {
  if (typeof detail === "string") return detail;
  if (Array.isArray(detail))
    return detail
      .map((item) => {
        if (!item || typeof item !== "object") return String(item);
        const row = item as { loc?: unknown[]; msg?: string };
        const field = row.loc?.at(-1);
        return `${field ? String(field).replaceAll("_", " ") + ": " : ""}${row.msg || "valor inválido"}`;
      })
      .join(" · ");
  if (detail && typeof detail === "object" && "message" in detail)
    return String((detail as { message: unknown }).message);
  return fallback;
}

export default function PanelPage() {
  const router = useRouter();
  const [user, setUser] = useState<User | null>(null);
  const [view, setView] = useState<MenuKey>("dashboard");
  const [data, setData] = useState<Record<string, unknown> | null>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState("");
  const [mfaSetup, setMfaSetup] = useState<{
    secret: string;
    provisioning_uri: string;
  } | null>(null);
  const [recovery, setRecovery] = useState<string[]>([]);
  const viewRef = useRef<MenuKey>("dashboard");
  const selectView = useCallback((next: MenuKey) => {
    // Al pulsar la vista actual no se dispara el efecto dependiente de `view`.
    // Activar el indicador de carga aquí la dejaría bloqueada indefinidamente.
    if (viewRef.current === next) return;
    viewRef.current = next;
    // Evita renderizar una sección con el payload perteneciente a la vista
    // anterior mientras comienza la nueva solicitud.
    setLoading(true);
    setData(null);
    setView(next);
  }, []);

  const csrf = useCallback(async () => {
    let token = sessionStorage.getItem("documenta:csrf");
    if (token) return token;
    const r = await fetch(`${apiBase}/auth/csrf`, { credentials: "include" });
    if (!r.ok) throw new Error("Sesión expirada");
    token = (await r.json()).csrf_token;
    sessionStorage.setItem("documenta:csrf", token!);
    return token!;
  }, []);
  const loadMe = useCallback(async () => {
    const r = await fetch(`${apiBase}/auth/me`, { credentials: "include" });
    if (!r.ok) {
      router.replace("/acceso");
      return;
    }
    const body = (await r.json()) as User;
    setUser(body);
    if (workspaceCapabilityFromHost()) selectView("workspace");
  }, [router, selectView]);
  useEffect(() => {
    const initialize = async () => {
      await Promise.resolve();
      await loadMe();
    };
    void initialize();
  }, [loadMe]);
  useEffect(() => {
    if (!error) return;
    const timer = window.setTimeout(() => setError(""), 4200);
    return () => window.clearTimeout(timer);
  }, [error]);
  const menus = useMemo(() => {
    if (!user) return [];
    const items: { key: MenuKey; label: string }[] = [];
    if (
      user.roles.includes("ADMIN_PLATAFORMA") ||
      Boolean(user.entidades?.length) ||
      user.permissions.includes("entidad.workspace")
    )
      items.push({ key: "workspace", label: "Gestión de la entidad" });
    items.push(
      { key: "dashboard", label: "Resumen" },
      {
        key: "documents",
        label: user.roles.includes("CLIENTE") ? "Mis documentos" : "Documentos",
      },
    );
    if (user.permissions.includes("facturacion.notaria"))
      items.push({ key: "billing", label: "Facturación" });
    if (user.permissions.includes("admin.global"))
      items.push({ key: "admin", label: "Administración" });
    if (user.permissions.includes("materias.admin"))
      items.push({ key: "matters", label: "Servicios" });
    if (
      user.roles.some((role) =>
        ["NOTARIA_ADMIN", "ADMIN_PLATAFORMA"].includes(role),
      )
    )
      items.push({ key: "offers", label: "Oferta de servicios" });
    if (user.roles.includes("ADMIN_PLATAFORMA") || user.notarias.some(n => n.rol_membresia === "ADMIN"))
      items.push({ key: "reservations", label: "Reservas" });
    if (user.permissions.includes("admin.global"))
      items.push({ key: "maintainers", label: "Mantenedores" });
    if (user.permissions.includes("contenido.admin"))
      items.push({ key: "content", label: "Portal público" });
    if (user.permissions.includes("contenido.editorial"))
      items.push({ key: "editorial", label: "Noticias y ayuda" });
    if (user.permissions.includes("verificacion.admin"))
      items.push({ key: "verification", label: "Verificación" });
    if (user.permissions.includes("operacion.monitoreo"))
      items.push({ key: "operations", label: "Operación" });
    if (user.permissions.includes("territorio.admin"))
      items.push({ key: "territory", label: "Territorio" });
    if (user.permissions.includes("seguridad.auditoria"))
      items.push({ key: "security", label: "Seguridad" });
    items.push({ key: "profile", label: "Mi perfil" });
    return items;
  }, [user]);
  useEffect(() => {
    if (!user) return;
    const loadView = async () => {
      await Promise.resolve();
      setLoading(true);
      const endpoint =
        view === "workspace"
          ? "workspace"
          : view === "dashboard"
          ? "dashboard"
          : view === "documents"
            ? "documents"
            : view === "billing"
              ? "billing"
              : view === "admin"
                ? "admin/overview"
                : view === "matters"
                  ? "admin/matters"
                  : view === "offers"
                    ? "offers"
                    : view === "maintainers"
                      ? "admin/maintainers"
                      : view === "content"
                        ? "admin/portal-content"
                      : view === "editorial"
                        ? null
                      : view === "verification"
                        ? null
                      : view === "operations"
                        ? null
                      : view === "reservations"
                        ? null
                      : view === "territory"
                        ? "admin/territory"
                      : view === "security"
                        ? "admin/security"
                        : null;
      if (!endpoint) {
        setData(null);
        setLoading(false);
        return;
      }
      try {
        const r = await fetch(`${apiBase}/panel/${endpoint}`, {
          credentials: "include",
          cache: "no-store",
          headers:
            view === "workspace" && workspaceCapabilityFromHost()
              ? {
                  "X-Documenta-Capability": workspaceCapabilityFromHost(),
                }
              : undefined,
        });
        const body = await r.json();
        if (r.status === 401) {
          sessionStorage.removeItem("documenta:csrf");
          router.replace("/acceso");
          return;
        }
        if (!r.ok)
          throw new Error(body.detail || "No fue posible cargar esta sección.");
        setData(body);
      } catch (reason) {
        setError(
          userMessage(reason, "No fue posible cargar esta sección."),
        );
      } finally {
        setLoading(false);
      }
    };
    void loadView();
  }, [router, user, view]);

  async function logout() {
    const token = await csrf();
    await fetch(`${apiBase}/auth/logout`, {
      method: "POST",
      headers: { "X-CSRF-Token": token },
      credentials: "include",
    });
    sessionStorage.removeItem("documenta:csrf");
    router.replace("/acceso");
  }
  async function saveProfile(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();
    const form = new FormData(event.currentTarget);
    const token = await csrf();
    const r = await fetch(`${apiBase}/auth/profile`, {
      method: "PUT",
      credentials: "include",
      headers: { "Content-Type": "application/json", "X-CSRF-Token": token },
      body: JSON.stringify({
        nombres: form.get("nombres"),
        apellidos: form.get("apellidos"),
        telefono: form.get("telefono") || null,
      }),
    });
    if (!r.ok) {
      setError((await r.json()).detail);
      return;
    }
    await loadMe();
    setError("Perfil actualizado correctamente.");
  }
  async function beginMfa() {
    const token = await csrf();
    const r = await fetch(`${apiBase}/auth/mfa/setup`, {
      method: "POST",
      credentials: "include",
      headers: { "X-CSRF-Token": token },
    });
    setMfaSetup(await r.json());
  }
  async function confirmMfa(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();
    const form = new FormData(event.currentTarget);
    const token = await csrf();
    const r = await fetch(`${apiBase}/auth/mfa/confirm`, {
      method: "POST",
      credentials: "include",
      headers: { "Content-Type": "application/json", "X-CSRF-Token": token },
      body: JSON.stringify({ code: form.get("code") }),
    });
    const body = await r.json();
    if (!r.ok) {
      setError(body.detail);
      return;
    }
    setRecovery(body.recovery_codes);
    setMfaSetup(null);
    await loadMe();
  }
  async function createInternalUser(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();
    setError("");
    const form = new FormData(event.currentTarget);
    const token = await csrf();
    const body = {
      email: form.get("email"),
      password: form.get("password"),
      nombres: form.get("nombres"),
      apellidos: form.get("apellidos"),
      rol: form.get("rol"),
      notaria_id: form.get("notaria_id")
        ? Number(form.get("notaria_id"))
        : null,
      activo: form.get("activo") === "on",
      mfa_requerido: form.get("mfa_requerido") === "on",
    };
    const r = await fetch(`${apiBase}/panel/admin/users`, {
      method: "POST",
      credentials: "include",
      headers: { "Content-Type": "application/json", "X-CSRF-Token": token },
      body: JSON.stringify(body),
    });
    const result = await r.json();
    if (!r.ok) {
      setError(result.detail || "No fue posible crear el usuario.");
      return;
    }
    setData((previous) =>
      previous
        ? {
            ...previous,
            users: [
              result.user,
              ...((previous.users || []) as Record<string, unknown>[]),
            ],
          }
        : previous,
    );
    event.currentTarget.reset();
    setError("Usuario creado correctamente.");
  }
  async function updateInternalUser(
    targetId: number,
    event: FormEvent<HTMLFormElement>,
  ) {
    event.preventDefault();
    setError("");
    const form = new FormData(event.currentTarget);
    const token = await csrf();
    const body = {
      email: form.get("email"),
      password: form.get("password") || null,
      nombres: form.get("nombres"),
      apellidos: form.get("apellidos"),
      rol: form.get("rol"),
      notaria_id: form.get("notaria_id")
        ? Number(form.get("notaria_id"))
        : null,
      activo: form.get("activo") === "on",
      mfa_requerido: form.get("mfa_requerido") === "on",
    };
    const r = await fetch(`${apiBase}/panel/admin/users/${targetId}`, {
      method: "PUT",
      credentials: "include",
      headers: { "Content-Type": "application/json", "X-CSRF-Token": token },
      body: JSON.stringify(body),
    });
    const result = await r.json();
    if (!r.ok) {
      setError(result.detail || "No fue posible actualizar el usuario.");
      return;
    }
    setData((previous) =>
      previous
        ? {
            ...previous,
            users: ((previous.users || []) as Record<string, unknown>[]).map(
              (item) => (Number(item.id) === targetId ? result.user : item),
            ),
          }
        : previous,
    );
    setError("Usuario actualizado correctamente.");
  }
  async function resetUserMfa(targetId: number) {
    setError("");
    const token = await csrf();
    const r = await fetch(`${apiBase}/panel/admin/users/${targetId}/mfa/reset`, {
      method: "POST",
      credentials: "include",
      headers: { "X-CSRF-Token": token },
    });
    const result = await r.json();
    if (!r.ok) {
      setError(result.detail || "No fue posible resetear el 2FA.");
      return;
    }
    if (targetId === user?.id) {
      sessionStorage.removeItem("documenta:csrf");
      router.replace("/acceso");
      return;
    }
    setData((previous) => previous ? {
      ...previous,
      users: ((previous.users || []) as Record<string, unknown>[]).map((item) =>
        Number(item.id) === targetId
          ? { ...item, mfa_habilitado: false, mfa_requerido: result.mfa_requerido }
          : item,
      ),
    } : previous);
    setError(`2FA reseteado. Se revocaron ${Number(result.sesiones_revocadas || 0)} sesiones.`);
  }
  async function saveNotary(
    targetId: number | null,
    event: FormEvent<HTMLFormElement>,
  ) {
    event.preventDefault();
    setError("");
    const form = new FormData(event.currentTarget);
    const logoFile = form.get("logo");
    const token = await csrf();
    const body = {
      rut: form.get("rut"),
      razon_social: form.get("razon_social"),
      nombre_fantasia: form.get("nombre_fantasia"),
      nombre_notario: form.get("nombre_notario") || null,
      comuna_id: Number(form.get("comuna_id")),
      direccion: form.get("direccion"),
      ciudad: form.get("ciudad") || null,
      telefono: form.get("telefono") || null,
      email_operaciones: form.get("email_operaciones"),
      email_notificaciones: form.get("email_notificaciones"),
      dias_vencimiento: Number(form.get("dias_vencimiento")),
      latitud: form.get("latitud") ? Number(form.get("latitud")) : null,
      longitud: form.get("longitud") ? Number(form.get("longitud")) : null,
      activa: form.get("activa") === "on",
      capacidades: form.getAll("capacidades").map(String),
    };
    const r = await fetch(
      `${apiBase}/panel/admin/entities${targetId ? `/${targetId}` : ""}`,
      {
        method: targetId ? "PUT" : "POST",
        credentials: "include",
        headers: { "Content-Type": "application/json", "X-CSRF-Token": token },
        body: JSON.stringify(body),
      },
    );
    const result = await r.json();
    if (!r.ok) {
      setError(result.detail || "No fue posible guardar la entidad.");
      return;
    }
    let logoError = "";
    if (logoFile instanceof File && logoFile.size > 0) {
      const logoBody = new FormData();
      logoBody.append("file", logoFile);
      const logoResponse = await fetch(
        `${apiBase}/panel/admin/entities/${Number(result.entidad.id)}/logo`,
        {
          method: "POST",
          credentials: "include",
          headers: { "X-CSRF-Token": token },
          body: logoBody,
        },
      );
      const logoResult = await logoResponse.json();
      if (!logoResponse.ok) {
        logoError = logoResult.detail || "La entidad se guardó, pero no fue posible guardar el logo.";
      } else {
        result.entidad = { ...result.entidad, logo_configurado: true };
      }
    }
    setData((previous) => {
      if (!previous) return previous;
      const list = (previous.entidades || previous.notarias || []) as Record<string, unknown>[];
      const updated = targetId
        ? list.map((item) =>
            Number(item.id) === targetId ? result.entidad : item,
          )
        : [result.entidad, ...list];
      return {
        ...previous,
        entidades: updated,
        notarias: updated,
      };
    });
    if (!targetId) event.currentTarget.reset();
    setError(logoError || `Entidad ${targetId ? "actualizada" : "creada"} correctamente.`);
  }
  async function saveCatalogEntity(
    catalogEntityId: number,
    event: FormEvent<HTMLFormElement>,
  ) {
    event.preventDefault();
    setError("");
    const form = new FormData(event.currentTarget);
    const token = await csrf();
    const body = {
      nombre_directorio: form.get("nombre_directorio"),
      cargo: form.get("cargo"),
      comuna_id: Number(form.get("comuna_id")),
      direccion: form.get("direccion") || null,
      telefono: form.get("telefono") || null,
      correo: form.get("correo") || null,
      sitio_web: form.get("sitio_web") || null,
      horario: form.get("horario") || null,
      estado_revision: form.get("estado_revision"),
      capacidades: form.getAll("capacidades").map(String),
    };
    const response = await fetch(
      `${apiBase}/panel/admin/entities/catalog/${catalogEntityId}`,
      {
        method: "PUT",
        credentials: "include",
        headers: { "Content-Type": "application/json", "X-CSRF-Token": token },
        body: JSON.stringify(body),
      },
    );
    const result = await response.json();
    if (!response.ok) {
      setError(apiMessage(result.detail, "No fue posible actualizar el catastro."));
      return false;
    }
    setData((previous) => {
      if (!previous) return previous;
      const rows = (previous.catastro_publico || []) as Record<string, unknown>[];
      return {
        ...previous,
        catastro_publico: rows.map((item) =>
          Number(item.id) === catalogEntityId ? result.entidad : item,
        ),
      };
    });
    setError("Registro del catastro actualizado correctamente.");
    return true;
  }
  async function rotateCredential(
    notaryId: number,
    event: FormEvent<HTMLFormElement>,
  ) {
    event.preventDefault();
    setError("");
    const form = new FormData(event.currentTarget);
    const token = await csrf();
    const body = {
      proveedor: form.get("proveedor"),
      ambiente: form.get("ambiente"),
      secreto: form.get("secreto"),
      identificador_publico: form.get("identificador_publico") || null,
      endpoint_base: form.get("endpoint_base") || null,
      fingerprint: form.get("fingerprint") || null,
      motivo: form.get("motivo"),
    };
    const r = await fetch(
      `${apiBase}/panel/admin/entities/${notaryId}/credentials`,
      {
        method: "POST",
        credentials: "include",
        headers: { "Content-Type": "application/json", "X-CSRF-Token": token },
        body: JSON.stringify(body),
      },
    );
    const result = await r.json();
    if (!r.ok) {
      setError(result.detail || "No fue posible guardar la credencial.");
      return;
    }
    setData((previous) =>
      previous
        ? {
            ...previous,
            credenciales: [
              result.credencial,
              ...(
                (previous.credenciales || []) as Record<string, unknown>[]
              ).filter(
                (item) =>
                  !(
                    Number(item.notaria_id) === notaryId &&
                    item.proveedor === body.proveedor
                  ),
              ),
            ],
          }
        : previous,
    );
    event.currentTarget.reset();
    setError("Credencial cifrada y rotada correctamente.");
  }
  async function deleteCredential(notaryId: number, provider: string) {
    const token = await csrf();
    const r = await fetch(
      `${apiBase}/panel/admin/entities/${notaryId}/credentials/${provider}`,
      {
        method: "DELETE",
        credentials: "include",
        headers: { "X-CSRF-Token": token },
      },
    );
    const result = await r.json();
    if (!r.ok) {
      setError(result.detail || "No fue posible eliminar la credencial.");
      return;
    }
    setData((previous) =>
      previous
        ? {
            ...previous,
            credenciales: (
              (previous.credenciales || []) as Record<string, unknown>[]
            ).filter(
              (item) =>
                !(
                  Number(item.notaria_id) === notaryId &&
                  item.proveedor === provider
                ),
            ),
          }
        : previous,
    );
    setError("Credencial eliminada correctamente.");
  }
  async function revokeSession(sessionId: number) {
    const token = await csrf();
    const r = await fetch(
      `${apiBase}/panel/admin/sessions/${sessionId}/revoke`,
      {
        method: "POST",
        credentials: "include",
        headers: { "X-CSRF-Token": token },
      },
    );
    const result = await r.json();
    if (!r.ok) {
      setError(result.detail || "No fue posible revocar la sesión.");
      return;
    }
    setData((previous) =>
      previous
        ? {
            ...previous,
            sessions: (
              (previous.sessions || []) as Record<string, unknown>[]
            ).map((item) =>
              Number(item.id) === sessionId
                ? { ...item, revocada_en: result.revocada_en }
                : item,
            ),
          }
        : previous,
    );
    setError("Sesión revocada correctamente.");
  }
  async function testGesnot(notaryId: number) {
    const token = await csrf();
    const r = await fetch(
      `${apiBase}/panel/admin/entities/${notaryId}/credentials/gesnot/test`,
      {
        method: "POST",
        credentials: "include",
        headers: { "X-CSRF-Token": token },
      },
    );
    const result = await r.json();
    if (!r.ok) {
      setError(result.detail || "No fue posible validar GesNot.");
      return;
    }
    setError(
      result.notaria_habilitada
        ? "Conexión GesNot validada correctamente."
        : "GesNot respondió, pero la notaría configurada no está habilitada para esta keyCliente.",
    );
  }

  if (!user)
    return <main className="session-gate" aria-label="Validando sesión" />;
  const metrics = (data?.metrics || data?.counts || {}) as Record<
    string,
    number
  >;
  const rows = (data?.items || data?.recent || []) as Record<string, unknown>[];
  const userEntities = user.entidades || user.notarias;
  return (
    <main className="panel-shell">
      <aside className="panel-sidebar">
        <a href="https://documenta.cl/" aria-label="Volver a la página principal de Documenta">
          <img src="/media/brand/logo-horizontal-white.svg" alt="Documenta" />
        </a>
        <div className="panel-identity">
          <strong>
            {user.nombres} {user.apellidos}
          </strong>
          <small>{user.roles.join(" · ")}</small>
          {userEntities.map((n) => (
            <small key={n.id}>{n.nombre_fantasia}</small>
          ))}
        </div>
        <nav>
          {menus.map((item) => (
            <button
              key={item.key}
              className={view === item.key ? "is-active" : ""}
              onClick={() => selectView(item.key)}
            >
              {item.label}
            </button>
          ))}
        </nav>
        <a className="panel-home-link" href="https://documenta.cl/">← Página principal</a>
        <button className="panel-logout" onClick={logout}>
          Cerrar sesión
        </button>
      </aside>
      <section className="panel-main">
        <header className="panel-header">
          <div>
            <span className="section-kicker">Panel Documenta</span>
            <h1>{menus.find((x) => x.key === view)?.label}</h1>
          </div>
          <button className="panel-avatar" onClick={() => selectView("profile")}>
            {user.nombres[0]}
            {user.apellidos[0]}
          </button>
        </header>
        {user.mfa_requerido && !user.mfa_habilitado && (
          <div className="security-alert">
            <div>
              <strong>Protege tu cuenta con 2FA</strong>
              <p>
                Es obligatorio para usuarios internos antes de acceder a
                información operacional.
              </p>
            </div>
            <button
              className="button button-primary"
              onClick={() => {
                selectView("profile");
                void beginMfa();
              }}
            >
              Configurar ahora
            </button>
          </div>
        )}
        {error && (
          <div
            className={`app-toast ${error.includes("correctamente") ? "is-success" : "is-error"}`}
            role="status"
          >
            <strong>
              {error.includes("correctamente") ? "Listo" : "Atención"}
            </strong>
            <span>{error}</span>
            <button
              type="button"
              onClick={() => setError("")}
              aria-label="Cerrar"
            >
              ×
            </button>
          </div>
        )}
        {loading ? (
          <div className="panel-empty">Cargando información…</div>
        ) : view === "profile" ? (
          <section className="profile-grid">
            <form className="panel-card profile-form" onSubmit={saveProfile}>
              <h2>Datos personales</h2>
              <label>
                Nombres
                <input name="nombres" defaultValue={user.nombres} required />
              </label>
              <label>
                Apellidos
                <input
                  name="apellidos"
                  defaultValue={user.apellidos}
                  required
                />
              </label>
              <label>
                Teléfono
                <input name="telefono" defaultValue={user.telefono || ""} />
              </label>
              <label>
                Correo
                <input value={user.email} disabled />
              </label>
              <button className="button button-primary">Guardar perfil</button>
            </form>
            <div className="panel-card">
              <h2>Seguridad</h2>
              <p>
                Segundo factor:{" "}
                <strong>{user.mfa_habilitado ? "Activo" : "Pendiente"}</strong>
              </p>
              {!user.mfa_habilitado && !mfaSetup && (
                <button className="button button-secondary" onClick={beginMfa}>
                  Configurar 2FA
                </button>
              )}
              {mfaSetup && (
                <form className="mfa-setup" onSubmit={confirmMfa}>
                  <p>Agrega esta clave a tu aplicación autenticadora:</p>
                  <code>{mfaSetup.secret}</code>
                  <details>
                    <summary>Ver URI de configuración</summary>
                    <code>{mfaSetup.provisioning_uri}</code>
                  </details>
                  <label>
                    Código de seis dígitos
                    <input
                      name="code"
                      required
                      pattern="[0-9]{6}"
                      maxLength={6}
                    />
                  </label>
                  <button className="button button-primary">
                    Confirmar 2FA
                  </button>
                </form>
              )}
              {recovery.length > 0 && (
                <div className="recovery-codes">
                  <strong>Guarda estos códigos una sola vez:</strong>
                  {recovery.map((c) => (
                    <code key={c}>{c}</code>
                  ))}
                </div>
              )}
            </div>
          </section>
        ) : (
          <>
            <div className="metrics-grid">
              {view !== "billing" && view !== "territory" && view !== "workspace" && view !== "reservations" &&
                Object.entries(metrics).map(([key, value]) => (
                  <article className="metric-card" key={key}>
                    <small>{panelLabel(key)}</small>
                    <strong>
                      {Number(value || 0).toLocaleString("es-CL")}
                    </strong>
                  </article>
                ))}
            </div>
            {view === "workspace" && (
              <EntityWorkspace
                initial={data as WorkspaceHome | null}
                csrf={csrf}
                notify={setError}
                onContextChanged={loadMe}
              />
            )}{" "}
            {view === "admin" && (
              <AdminOverview
                data={data}
                onCreate={createInternalUser}
                onUpdate={updateInternalUser}
                onSaveNotary={saveNotary}
                onSaveCatalogEntity={saveCatalogEntity}
                onRotateCredential={rotateCredential}
                onDeleteCredential={deleteCredential}
                onTestGesnot={testGesnot}
                onResetMfa={resetUserMfa}
              />
            )}{" "}
            {view === "matters" && (
              <MattersOverview data={data} csrf={csrf} notify={setError} />
            )}{" "}
            {view === "offers" && (
              <OffersManagement
                csrf={csrf}
                notify={setError}
                canManageCommission={user.permissions.includes("admin.global")}
              />
            )}{" "}
            {view === "maintainers" && (
              <MaintainersManagement
                data={data}
                csrf={csrf}
                notify={setError}
              />
            )}{" "}
            {view === "content" && (
              <PortalContentManagement
                data={data}
                csrf={csrf}
                notify={setError}
                onSaved={setData}
              />
            )}{" "}
            {view === "editorial" && (
              <EditorialManagement csrf={csrf} notify={setError} />
            )}{" "}
            {view === "verification" && (
              <VerificationManagement csrf={csrf} notify={setError} />
            )}{" "}
            {view === "operations" && (
              <OperationsManagement csrf={csrf} notify={setError} />
            )}{" "}
            {view === "reservations" && (
              <ReservationsManagement notarias={user.notarias} globalAdmin={user.roles.includes("ADMIN_PLATAFORMA")} csrf={csrf} notify={setError} />
            )}{" "}
            {view === "territory" && (
              <TerritoryManagement data={data} csrf={csrf} notify={setError} />
            )}{" "}
            {view === "security" && (
              <SecurityOverview data={data} onRevoke={revokeSession} csrf={csrf} notify={setError} />
            )}{" "}
            {view === "documents" && (
              <DocumentsManagement
                rows={rows}
                csrf={csrf}
                notify={setError}
                canComplete={!user.roles.includes("CLIENTE")}
                canReopen={user.roles.includes("ADMIN_PLATAFORMA")}
              />
            )}{" "}
            {view === "billing" && <BillingManagement data={data} />}{" "}
            {view === "dashboard" && <DataTable rows={rows} />}
          </>
        )}
      </section>
    </main>
  );
}

function DataTable({ rows }: { rows: Record<string, unknown>[] }) {
  if (!rows.length)
    return (
      <div className="panel-empty">Todavía no hay registros para mostrar.</div>
    );
  const columns = Object.keys(rows[0]).slice(0, 8);
  return (
    <div className="panel-table-wrap">
      <table>
        <thead>
          <tr>
            {columns.map((c) => (
              <th key={c}>{panelLabel(c)}</th>
            ))}
          </tr>
        </thead>
        <tbody>
          {rows.map((row, i) => (
            <tr key={i}>
              {columns.map((c) => (
                <td key={c}>{panelValue(c, row[c])}</td>
              ))}
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}
function LegacyAdminOverview({
  data,
  onCreate,
  onUpdate,
  onSaveNotary,
  onRotateCredential,
  onTestGesnot,
}: {
  data: Record<string, unknown> | null;
  onCreate: (event: FormEvent<HTMLFormElement>) => void;
  onUpdate: (id: number, event: FormEvent<HTMLFormElement>) => void;
  onSaveNotary: (id: number | null, event: FormEvent<HTMLFormElement>) => void;
  onRotateCredential: (id: number, event: FormEvent<HTMLFormElement>) => void;
  onTestGesnot: (id: number) => void;
}) {
  const [editing, setEditing] = useState<Record<string, unknown> | null>(null);
  const [editingNotary, setEditingNotary] = useState<Record<
    string,
    unknown
  > | null>(null);
  const [credentialNotary, setCredentialNotary] = useState<Record<
    string,
    unknown
  > | null>(null);
  const notaries = (data?.notarias || []) as Record<string, unknown>[];
  const users = (data?.users || []) as Record<string, unknown>[];
  const communes = (data?.comunas || []) as Record<string, unknown>[];
  const credentials = (data?.credenciales || []) as Record<string, unknown>[];
  return (
    <div className="admin-sections">
      <div className="admin-columns">
        <form
          key={editing ? String(editing.id) : "new-user"}
          className="panel-card profile-form"
          onSubmit={(event) =>
            editing ? onUpdate(Number(editing.id), event) : onCreate(event)
          }
        >
          <h2>{editing ? "Editar usuario" : "Crear usuario"}</h2>
          <label>
            Nombres
            <input
              name="nombres"
              defaultValue={editing ? String(editing.nombres) : ""}
              required
            />
          </label>
          <label>
            Apellidos
            <input
              name="apellidos"
              defaultValue={editing ? String(editing.apellidos) : ""}
              required
            />
          </label>
          <label>
            Correo
            <input
              name="email"
              type="email"
              defaultValue={editing ? String(editing.email) : ""}
              required
            />
          </label>
          <label>
            {editing ? "Nueva contraseña (opcional)" : "Contraseña inicial"}
            <input
              name="password"
              type="password"
              minLength={12}
              required={!editing}
            />
          </label>
          <label>
            Rol
            <select
              name="rol"
              defaultValue={
                editing ? String(editing.roles) : "NOTARIA_FUNCIONARIO"
              }
              required
            >
              <option value="NOTARIA_FUNCIONARIO">
                Funcionario de notaría
              </option>
              <option value="NOTARIA_ADMIN">Administrador notarial</option>
              <option value="ADMIN_PLATAFORMA">Administrador Documenta</option>
              <option value="CLIENTE">Cliente</option>
            </select>
          </label>
          <label>
            Notaría
            <select
              name="notaria_id"
              defaultValue={
                editing?.notaria_id ? String(editing.notaria_id) : ""
              }
            >
              <option value="">Sin asignación</option>
              {notaries.map((n) => (
                <option key={String(n.id)} value={String(n.id)}>
                  {String(n.nombre_fantasia)}
                </option>
              ))}
            </select>
          </label>
          <div className="option-checks">
            <label>
              <input
                name="activo"
                type="checkbox"
                defaultChecked={!editing || Boolean(editing.activo)}
              />{" "}
              Usuario activo
            </label>
            <label>
              <input
                name="mfa_requerido"
                type="checkbox"
                defaultChecked={Boolean(editing?.mfa_requerido)}
              />{" "}
              Exigir 2FA
            </label>
          </div>
          <div className="wizard-actions">
            {editing && (
              <button
                className="button button-secondary"
                type="button"
                onClick={() => setEditing(null)}
              >
                Cancelar
              </button>
            )}
            <button className="button button-primary">
              {editing ? "Guardar cambios" : "Crear usuario"}
            </button>
          </div>
        </form>
        <section className="panel-card admin-user-list">
          <h2>Usuarios</h2>
          <div className="panel-table-wrap">
            <table>
              <thead>
                <tr>
                  <th>Usuario</th>
                  <th>Rol</th>
                  <th>Activo</th>
                  <th>2FA</th>
                  <th></th>
                </tr>
              </thead>
              <tbody>
                {users.map((item) => (
                  <tr key={String(item.id)}>
                    <td>
                      <strong>
                        {String(item.nombres)} {String(item.apellidos)}
                      </strong>
                      <small>{String(item.email)}</small>
                    </td>
                    <td>{String(item.roles || "—")}</td>
                    <td>{item.activo ? "Sí" : "No"}</td>
                    <td>
                      {item.mfa_requerido
                        ? "Exigido"
                        : item.mfa_habilitado
                          ? "Configurado"
                          : "Opcional"}
                    </td>
                    <td>
                      <button
                        className="table-action"
                        type="button"
                        onClick={() => setEditing(item)}
                      >
                        Editar
                      </button>
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        </section>
      </div>
      <div className="admin-columns">
        <form
          key={editingNotary ? String(editingNotary.id) : "new-notary"}
          className="panel-card profile-form"
          onSubmit={(event) =>
            onSaveNotary(editingNotary ? Number(editingNotary.id) : null, event)
          }
        >
          <h2>{editingNotary ? "Editar notaría" : "Agregar notaría"}</h2>
          <div className="form-pair">
            <label>
              RUT
              <input
                name="rut"
                defaultValue={editingNotary ? String(editingNotary.rut) : ""}
                onChange={(event) =>
                  (event.currentTarget.value = formatRutInput(
                    event.currentTarget.value,
                  ))
                }
                placeholder="12.345.678-9"
                required
              />
            </label>
            <label>
              Nombre de fantasía
              <input
                name="nombre_fantasia"
                defaultValue={
                  editingNotary ? String(editingNotary.nombre_fantasia) : ""
                }
                required
              />
            </label>
          </div>
          <label>
            Razón social
            <input
              name="razon_social"
              defaultValue={
                editingNotary ? String(editingNotary.razon_social) : ""
              }
              required
            />
          </label>
          <label>
            Nombre del notario
            <input
              name="nombre_notario"
              defaultValue={
                editingNotary ? String(editingNotary.nombre_notario || "") : ""
              }
            />
          </label>
          <label>
            Comuna
            <select
              name="comuna_id"
              defaultValue={
                editingNotary ? String(editingNotary.comuna_id) : ""
              }
              required
            >
              <option value="">Seleccionar</option>
              {communes.map((c) => (
                <option key={String(c.id)} value={String(c.id)}>
                  {String(c.comuna)} · {String(c.region)}
                </option>
              ))}
            </select>
          </label>
          <label>
            Dirección
            <input
              name="direccion"
              defaultValue={
                editingNotary ? String(editingNotary.direccion) : ""
              }
              required
            />
          </label>
          <div className="form-pair">
            <label>
              Teléfono
              <input
                name="telefono"
                defaultValue={
                  editingNotary ? String(editingNotary.telefono || "") : ""
                }
              />
            </label>
            <label>
              Días de vencimiento
              <input
                name="dias_vencimiento"
                type="number"
                min="1"
                max="365"
                defaultValue={
                  editingNotary ? Number(editingNotary.dias_vencimiento) : 30
                }
                required
              />
            </label>
          </div>
          <label>
            Correo de operaciones
            <input
              name="email_operaciones"
              type="email"
              defaultValue={
                editingNotary ? String(editingNotary.email_operaciones) : ""
              }
              required
            />
          </label>
          <label>
            Correo de notificaciones
            <input
              name="email_notificaciones"
              type="email"
              defaultValue={
                editingNotary ? String(editingNotary.email_notificaciones) : ""
              }
              required
            />
          </label>
          <div className="option-checks">
            <label>
              <input
                name="activa"
                type="checkbox"
                defaultChecked={!editingNotary || Boolean(editingNotary.activa)}
              />{" "}
              Notaría activa
            </label>
          </div>
          <div className="wizard-actions">
            {editingNotary && (
              <button
                className="button button-secondary"
                type="button"
                onClick={() => setEditingNotary(null)}
              >
                Cancelar
              </button>
            )}
            <button className="button button-primary">
              {editingNotary ? "Guardar cambios" : "Agregar notaría"}
            </button>
          </div>
        </form>
        <section className="panel-card admin-user-list">
          <h2>Notarías</h2>
          <div className="notary-admin-list">
            {notaries.map((item) => (
              <article key={String(item.id)}>
                <div>
                  <strong>{String(item.nombre_fantasia)}</strong>
                  <small>
                    {String(item.rut)} · {item.activa ? "Activa" : "Inactiva"}
                  </small>
                  <small>{String(item.email_operaciones)}</small>
                </div>
                <div>
                  <button
                    className="table-action"
                    type="button"
                    onClick={() => setEditingNotary(item)}
                  >
                    Editar
                  </button>
                  <button
                    className="table-action"
                    type="button"
                    onClick={() => setCredentialNotary(item)}
                  >
                    Credenciales
                  </button>
                </div>
              </article>
            ))}
          </div>
        </section>
      </div>
      {credentialNotary && (
        <section className="panel-card credential-manager">
          <div className="credential-heading">
            <div>
              <span className="section-kicker">Integraciones protegidas</span>
              <h2>{String(credentialNotary.nombre_fantasia)}</h2>
              <p>
                El secreto se cifra con AES-256-GCM y nunca se vuelve a mostrar.
              </p>
            </div>
            <div className="download-actions">
              <button
                className="table-action"
                type="button"
                onClick={() => void onTestGesnot(Number(credentialNotary.id))}
              >
                Probar conexión GN
              </button>
              <button
                className="table-action"
                type="button"
                onClick={() => setCredentialNotary(null)}
              >
                Cerrar
              </button>
            </div>
          </div>
          <div className="integration-note">
            <strong>Configuración GN</strong>
            <span>
              Secreto: <code>keyCliente</code>. Identificador público:{" "}
              <code>idNotaria</code>. Endpoint:{" "}
              <code>https://api.gesnot.cl/ot</code>.
            </span>
          </div>
          <div className="admin-columns">
            <form
              className="profile-form"
              onSubmit={(event) =>
                onRotateCredential(Number(credentialNotary.id), event)
              }
            >
              <label>
                Proveedor
                <select name="proveedor">
                  <option value="GESNOT">GesNot / GN</option>
                  <option value="WEBPAY">Webpay</option>
                </select>
              </label>
              <label>
                Ambiente
                <select name="ambiente">
                  <option value="INTEGRACION">Integración</option>
                  <option value="PRODUCCION">Producción</option>
                </select>
              </label>
              <label>
                Secreto / keyCliente
                <input
                  name="secreto"
                  type="password"
                  minLength={8}
                  autoComplete="new-password"
                  required
                />
              </label>
              <label>
                ID notaría GN / identificador público
                <input name="identificador_publico" required />
              </label>
              <label>
                Endpoint base
                <input
                  name="endpoint_base"
                  type="url"
                  defaultValue="https://api.gesnot.cl/ot"
                />
              </label>
              <label>
                Fingerprint SHA-256 (opcional)
                <input name="fingerprint" pattern="[a-fA-F0-9]{64}" />
              </label>
              <label>
                Motivo de configuración
                <input name="motivo" minLength={5} required />
              </label>
              <button className="button button-primary">
                Cifrar y guardar
              </button>
            </form>
            <div>
              <h3>Credenciales activas</h3>
              <div className="credential-status-list">
                {credentials
                  .filter(
                    (item) =>
                      Number(item.notaria_id) === Number(credentialNotary.id),
                  )
                  .map((item) => (
                    <div key={`${item.proveedor}-${item.ambiente}`}>
                      <strong>{String(item.proveedor)}</strong>
                      <span>
                        {String(item.ambiente)} · versión{" "}
                        {String(item.version || "nueva")}
                      </span>
                      <small>
                        {String(
                          item.identificador_publico ||
                            "Sin identificador público",
                        )}
                      </small>
                    </div>
                  ))}
                {!credentials.some(
                  (item) =>
                    Number(item.notaria_id) === Number(credentialNotary.id),
                ) && (
                  <p className="muted-copy">
                    Aún no hay credenciales configuradas.
                  </p>
                )}
              </div>
            </div>
          </div>
        </section>
      )}
    </div>
  );
}
function DocumentsTable({ rows }: { rows: Record<string, unknown>[] }) {
  if (!rows.length)
    return (
      <div className="panel-empty">Todavía no hay documentos para mostrar.</div>
    );
  return (
    <div className="panel-table-wrap">
      <table>
        <thead>
          <tr>
            <th>Folio</th>
            <th>Documento</th>
            <th>Notaría</th>
            <th>Estado</th>
            <th>Fecha</th>
            <th>Descargas</th>
          </tr>
        </thead>
        <tbody>
          {rows.map((row) => (
            <tr key={String(row.id)}>
              <td>{String(row.folio)}</td>
              <td>{String(row.documento)}</td>
              <td>{String(row.notaria)}</td>
              <td>{String(row.estado)}</td>
              <td>{dateTimeCL(row.creada_en)}</td>
              <td>
                <div className="download-actions">
                  <a
                    className="table-action"
                    href={`${apiBase}/panel/documents/${encodeURIComponent(String(row.folio))}/download?format=pdf`}
                    target="_blank"
                  >
                    PDF
                  </a>
                  <a
                    className="table-action"
                    href={`${apiBase}/panel/documents/${encodeURIComponent(String(row.folio))}/download?format=docx`}
                    target="_blank"
                  >
                    Word
                  </a>
                </div>
              </td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}

function SecurityOverview({
  data,
  onRevoke,
  csrf,
  notify,
}: {
  data: Record<string, unknown> | null;
  onRevoke: (id: number) => void;
  csrf: () => Promise<string>;
  notify: (message: string) => void;
}) {
  const [tab, setTab] = useState<"sessions" | "audit" | "integrations" | "attempts" | "emails" | "mail_settings">("sessions");
  const [savingMail,setSavingMail]=useState(false);
  const [query, setQuery] = useState("");
  const [page, setPage] = useState(1);
  const pageSize = 12;
  const source = (tab === "mail_settings" ? [] : data?.[tab] || []) as Record<string, unknown>[];
  const filtered = source.filter(
    (row) =>
      !query ||
      Object.values(row).some((value) =>
        String(value ?? "")
          .toLocaleLowerCase("es")
          .includes(query.toLocaleLowerCase("es")),
      ),
  );
  const pages = Math.max(1, Math.ceil(filtered.length / pageSize));
  const rows = filtered.slice((page - 1) * pageSize, page * pageSize);
  function changeTab(next: "sessions" | "audit" | "integrations" | "attempts" | "emails" | "mail_settings") {
    setTab(next);
    setPage(1);
    setQuery("");
  }
  async function saveMail(event:FormEvent<HTMLFormElement>){event.preventDefault();setSavingMail(true);try{const f=new FormData(event.currentTarget),token=await csrf();const r=await fetch(`${apiBase}/panel/admin/mail-settings`,{method:"PUT",credentials:"include",headers:{"Content-Type":"application/json","X-CSRF-Token":token},body:JSON.stringify({smtp_usuario:f.get("smtp_usuario"),smtp_desde:f.get("smtp_desde"),nombre_remitente:f.get("nombre_remitente"),auth_mode:f.get("auth_mode"),app_password:f.get("app_password")||null,google_client_id:f.get("google_client_id")||null,google_client_secret:f.get("google_client_secret")||null,google_refresh_token:f.get("google_refresh_token")||null,smtp_host:f.get("smtp_host"),smtp_port:Number(f.get("smtp_port")),seguridad:f.get("seguridad"),activo:f.get("activo")==="on",debug_copia_admin:f.get("debug_copia_admin")==="on"})});const b=await r.json();if(!r.ok)throw new Error(apiMessage(b.detail,"No fue posible guardar el correo."));notify("Configuración OAuth de correo guardada y cifrada correctamente.");}catch(e){notify(userMessage(e,"No fue posible guardar la configuración de correo."));}finally{setSavingMail(false)}}
  async function testMail(){setSavingMail(true);try{const token=await csrf(),r=await fetch(`${apiBase}/panel/admin/mail-settings/test`,{method:"POST",credentials:"include",headers:{"X-CSRF-Token":token}}),b=await r.json();if(!r.ok)throw new Error(apiMessage(b.detail,"No fue posible enviar la prueba."));notify("Correo de prueba enviado correctamente. Revisa tu bandeja.");}catch(e){notify(userMessage(e,"No fue posible enviar el correo de prueba."));}finally{setSavingMail(false)}}
  async function retryMail(){setSavingMail(true);try{const token=await csrf(),r=await fetch(`${apiBase}/panel/admin/mail-settings/retry-pending`,{method:"POST",credentials:"include",headers:{"X-CSRF-Token":token}}),b=await r.json();if(!r.ok)throw new Error(apiMessage(b.detail,"No fue posible reactivar los correos."));notify(`${Number(b.reactivados||0)} evento(s) de correo reactivado(s).`);}catch(e){notify(userMessage(e,"No fue posible reactivar los correos."));}finally{setSavingMail(false)}}
  const mail=(data?.mail_settings||{}) as Record<string,unknown>;
  return (
    <section className="panel-card security-browser">
      <div className="security-tabs">
        <button
          className={tab === "sessions" ? "is-active" : ""}
          onClick={() => changeTab("sessions")}
        >
          Sesiones
        </button>
        <button
          className={tab === "audit" ? "is-active" : ""}
          onClick={() => changeTab("audit")}
        >
          Auditoría
        </button>
        <button
          className={tab === "attempts" ? "is-active" : ""}
          onClick={() => changeTab("attempts")}
        >
          Intentos de acceso
        </button>
        <button className={tab === "integrations" ? "is-active" : ""} onClick={() => changeTab("integrations")}>Integraciones</button>
        <button className={tab === "emails" ? "is-active" : ""} onClick={() => changeTab("emails")}>Correos</button>
        <button className={tab === "mail_settings" ? "is-active" : ""} onClick={() => changeTab("mail_settings")}>Google Workspace</button>
      </div>
      {tab === "mail_settings" ? <form className="profile-form mail-settings-form" onSubmit={saveMail}>
        <div className="settings-intro"><div><span className="section-kicker">SMTP PROTEGIDO</span><h2>Correo de Google Workspace</h2><p>Usa una clave de aplicación, nunca la contraseña principal. El secreto se cifra antes de almacenarse.</p></div></div>
        <div className="form-pair"><label>Cuenta de Workspace<input name="smtp_usuario" type="email" required defaultValue={String(mail.smtp_usuario||"")} placeholder="notificaciones@documenta.cl"/></label><label>Correo remitente<input name="smtp_desde" type="email" required defaultValue={String(mail.smtp_desde||"")} placeholder="notificaciones@documenta.cl"/></label></div>
        <div className="form-pair"><label>Nombre visible<input name="nombre_remitente" required defaultValue={String(mail.nombre_remitente||"Documenta")}/></label><label>Autenticación<select name="auth_mode" defaultValue={String(mail.auth_mode||"OAUTH2")}><option value="OAUTH2">Google OAuth 2.0</option><option value="APP_PASSWORD">Clave de aplicación</option></select></label></div>
        <div className="form-pair"><label>Servidor SMTP<input name="smtp_host" required defaultValue={String(mail.smtp_host||"smtp.gmail.com")}/></label><label>Puerto<input name="smtp_port" type="number" required defaultValue={Number(mail.smtp_port||587)}/></label></div>
        <div className="form-pair"><label>Seguridad<select name="seguridad" defaultValue={String(mail.seguridad||"STARTTLS")}><option value="STARTTLS">STARTTLS (587)</option><option value="SSL">SSL (465)</option></select></label><label>Clave de aplicación<input name="app_password" type="password" minLength={16} placeholder={mail.smtp_usuario?"Dejar vacía para conservar":"16 caracteres de Google"}/><small>No se vuelve a mostrar después de guardarla.</small></label></div>
        <label>Google Client ID<input name="google_client_id" defaultValue={String(mail.google_client_id||"")} placeholder="000000000000-xxxxx.apps.googleusercontent.com"/></label>
        <div className="form-pair"><label>Google Client Secret<input name="google_client_secret" type="password" placeholder={mail.google_client_id?"Dejar vacío para conservar":"Client Secret nuevo"}/><small>Se almacena cifrado.</small></label><label>Google Refresh Token<input name="google_refresh_token" type="password" placeholder={mail.google_client_id?"Dejar vacío para conservar":"Refresh Token nuevo"}/><small>Se almacena cifrado y sólo se usa para solicitar access tokens.</small></label></div>
        <label className="wizard-check"><input name="activo" type="checkbox" defaultChecked={mail.activo!==false}/><span>Activar envíos reales con esta configuración</span></label>
        <label className="wizard-check"><input name="debug_copia_admin" type="checkbox" defaultChecked={mail.debug_copia_admin!==false}/><span>Modo depuración: enviar copia oculta al administrador de plataforma</span></label>
        <div className="wizard-actions"><button type="button" className="button button-secondary" disabled={savingMail||!mail.smtp_usuario} onClick={testMail}>Enviar prueba</button><button type="button" className="button button-secondary" disabled={savingMail} onClick={retryMail}>Reintentar pendientes</button><button className="button button-primary" disabled={savingMail}>{savingMail?"Guardando…":"Guardar configuración"}</button></div>
      </form> : <>
      <div className="table-toolbar">
        <input
          type="search"
          value={query}
          onChange={(event) => {
            setQuery(event.target.value);
            setPage(1);
          }}
          placeholder="Buscar en esta tabla…"
        />
        <span>{filtered.length} registros</span>
      </div>
      {tab === "sessions" ? (
        <div className="panel-table-wrap">
          <table>
            <thead>
              <tr>
                <th>Usuario</th>
                <th>Creada</th>
                <th>Actividad</th>
                <th>Expira</th>
                <th>Revocada</th>
                <th></th>
              </tr>
            </thead>
            <tbody>
              {rows.map((item) => (
                <tr key={String(item.id)}>
                  <td>{String(item.email)}</td>
                  <td>{dateTimeCL(item.creada_en)}</td>
                  <td>{dateTimeCL(item.ultima_actividad_en)}</td>
                  <td>{dateTimeCL(item.expira_en)}</td>
                  <td>{dateTimeCL(item.revocada_en)}</td>
                  <td>
                    {!item.revocada_en && (
                      <button
                        className="table-action danger"
                        type="button"
                        onClick={() => onRevoke(Number(item.id))}
                      >
                        Revocar
                      </button>
                    )}
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      ) : (
        <DataTable rows={rows} />
      )}
      <div className="table-pagination">
        <button
          disabled={page <= 1}
          onClick={() => setPage((value) => value - 1)}
        >
          Anterior
        </button>
        <span>
          Página {page} de {pages}
        </span>
        <button
          disabled={page >= pages}
          onClick={() => setPage((value) => value + 1)}
        >
          Siguiente
        </button>
      </div>
      </>}
    </section>
  );
}

function LegacyMattersOverview({
  data,
  csrf,
  notify,
}: {
  data: Record<string, unknown> | null;
  csrf: () => Promise<string>;
  notify: (message: string) => void;
}) {
  const [items, setItems] = useState<Record<string, unknown>[]>(
    (data?.items || []) as Record<string, unknown>[],
  );
  const [selected, setSelected] = useState<number | null>(null);
  const [detail, setDetail] = useState<Record<string, unknown> | null>(null);
  const [editingField, setEditingField] = useState<Record<
    string,
    unknown
  > | null>(null);
  const [modalOpen, setModalOpen] = useState(false);
  const [query, setQuery] = useState("");
  const [page, setPage] = useState(1);
  const categories = (data?.categorias || []) as Record<string, unknown>[];
  const types = (data?.tipos || []) as Record<string, unknown>[];
  const notaries = (data?.notarias || []) as Record<string, unknown>[];
  async function request(path: string, options: RequestInit = {}) {
    const token = await csrf();
    const response = await fetch(`${apiBase}/panel${path}`, {
      ...options,
      credentials: "include",
      headers: {
        "Content-Type": "application/json",
        "X-CSRF-Token": token,
        ...(options.headers || {}),
      },
    });
    const result = await response.json();
    if (!response.ok) throw new Error(apiMessage(result.detail));
    return result;
  }
  async function loadDetail(id: number) {
    setSelected(id);
    setModalOpen(true);
    const response = await fetch(`${apiBase}/panel/admin/matters/${id}`, {
      credentials: "include",
      cache: "no-store",
    });
    const result = await response.json();
    if (!response.ok) {
      notify(result.detail || "No fue posible cargar la materia.");
      return;
    }
    setDetail(result);
    setEditingField(null);
  }
  async function saveMatter(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();
    const form = new FormData(event.currentTarget);
    const body = {
      categoria_id: Number(form.get("categoria_id")),
      codigo: form.get("codigo"),
      nombre: form.get("nombre"),
      slug: form.get("slug"),
      descripcion_corta: form.get("descripcion_corta") || null,
      descripcion: form.get("descripcion") || null,
      requiere_comparecientes: Number(form.get("requiere_comparecientes")),
      permite_adjuntos: form.get("permite_adjuntos") === "on",
      estado: form.get("estado"),
    };
    try {
      const result = await request(
        `/admin/matters${selected ? `/${selected}` : ""}`,
        { method: selected ? "PUT" : "POST", body: JSON.stringify(body) },
      );
      notify(`Materia ${selected ? "actualizada" : "creada"} correctamente.`);
      if (!selected) {
        setItems((previous) => [
          {
            id: result.id,
            ...body,
            categoria: categories.find(
              (c) => Number(c.id) === body.categoria_id,
            )?.nombre,
            campos: 0,
            ofertas: 0,
          },
          ...previous,
        ]);
        await loadDetail(result.id);
      } else {
        setItems((previous) =>
          previous.map((item) =>
            Number(item.id) === selected ? { ...item, ...body } : item,
          ),
        );
      }
    } catch (reason) {
      notify(userMessage(reason));
    }
  }
  async function saveField(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();
    if (!selected) return;
    const form = new FormData(event.currentTarget);
    const body = {
      codigo: form.get("codigo"),
      etiqueta: form.get("etiqueta"),
      tipo_dato: form.get("tipo_dato"),
      ayuda: form.get("ayuda") || null,
      placeholder: form.get("placeholder") || null,
      requerido: form.get("requerido") === "on",
      orden: Number(form.get("orden")),
      largo_minimo: form.get("largo_minimo")
        ? Number(form.get("largo_minimo"))
        : null,
      largo_maximo: form.get("largo_maximo")
        ? Number(form.get("largo_maximo"))
        : null,
      valor_minimo: form.get("valor_minimo")
        ? Number(form.get("valor_minimo"))
        : null,
      valor_maximo: form.get("valor_maximo")
        ? Number(form.get("valor_maximo"))
        : null,
      patron_regex: form.get("patron_regex") || null,
      opciones: String(form.get("opciones") || "")
        .split("\n")
        .map((x) => x.trim())
        .filter(Boolean),
      activo: true,
    };
    try {
      await request(
        `/admin/matters/${selected}/fields${editingField ? `/${editingField.id}` : ""}`,
        { method: editingField ? "PUT" : "POST", body: JSON.stringify(body) },
      );
      await loadDetail(selected);
      notify(`Campo ${editingField ? "actualizado" : "creado"} correctamente.`);
    } catch (reason) {
      notify(userMessage(reason));
    }
  }
  async function disableField(id: number) {
    if (!selected) return;
    try {
      await request(`/admin/matters/${selected}/fields/${id}`, {
        method: "DELETE",
      });
      await loadDetail(selected);
      notify("Campo desactivado correctamente.");
    } catch (reason) {
      notify(userMessage(reason));
    }
  }
  async function saveTemplate(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();
    if (!selected) return;
    const form = new FormData(event.currentTarget);
    try {
      const result = await request(`/admin/matters/${selected}/template`, {
        method: "PUT",
        body: JSON.stringify({
          nombre: form.get("nombre"),
          contenido: form.get("contenido"),
        }),
      });
      setDetail((previous) =>
        previous ? { ...previous, plantilla: result.plantilla } : previous,
      );
      notify("Plantilla publicada correctamente.");
    } catch (reason) {
      notify(userMessage(reason));
    }
  }
  async function saveOffer(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();
    if (!selected) return;
    const form = new FormData(event.currentTarget);
    try {
      await request(`/admin/matters/${selected}/offers`, {
        method: "PUT",
        body: JSON.stringify({
          notaria_id: Number(form.get("notaria_id")),
          codigo_gesnot: form.get("codigo_gesnot"),
          gesnot_tipo_ot: Number(form.get("gesnot_tipo_ot")),
          gesnot_materia: form.get("gesnot_materia"),
          precio: Number(form.get("precio")),
          plazo_estimado_horas: form.get("plazo_estimado_horas")
            ? Number(form.get("plazo_estimado_horas"))
            : null,
          activo: form.get("activo") === "on",
        }),
      });
      await loadDetail(selected);
      notify("Oferta notarial actualizada correctamente.");
    } catch (reason) {
      notify(userMessage(reason));
    }
  }
  const matter = (detail?.materia || null) as Record<string, unknown> | null;
  const fields = (detail?.campos || []) as Record<string, unknown>[];
  const template = (detail?.plantilla || null) as Record<
    string,
    unknown
  > | null;
  const offers = (detail?.ofertas || []) as Record<string, unknown>[];
  const filtered = items.filter(
    (item) =>
      !query ||
      Object.values(item).some((value) =>
        String(value ?? "")
          .toLowerCase()
          .includes(query.toLowerCase()),
      ),
  );
  const pageSize = 12;
  const pages = Math.max(1, Math.ceil(filtered.length / pageSize));
  const visible = filtered.slice((page - 1) * pageSize, page * pageSize);
  const goTo = (id: string) => {
    const indexes: Record<string, number> = {
      "matter-data": 0,
      "matter-fields": 1,
      "matter-template": 2,
    };
    const index = indexes[id];
    document
      .querySelectorAll<HTMLElement>(".matter-workspace > .panel-card")
      .forEach((section, position) => (section.hidden = position !== index));
    document
      .querySelectorAll(".admin-modal-nav button")
      .forEach((button, position) =>
        button.classList.toggle("is-active", position === index),
      );
  };
  return (
    <div className="matter-browser">
      <section className="panel-card">
        <div className="card-heading">
          <div>
            <h2>Materias del front</h2>
            <p className="muted-copy">
              Administra datos, campos, plantilla y oferta desde una sola ficha.
            </p>
          </div>
          <button
            className="button button-primary"
            type="button"
            onClick={() => {
              setSelected(null);
              setDetail(null);
              setEditingField(null);
              setModalOpen(true);
            }}
          >
            Nueva materia
          </button>
        </div>
        <div className="table-toolbar">
          <input
            type="search"
            value={query}
            onChange={(event) => {
              setQuery(event.target.value);
              setPage(1);
            }}
            placeholder="Buscar materia, categoría o estado…"
          />
          <span>{filtered.length} materias</span>
        </div>
        <div className="panel-table-wrap">
          <table>
            <thead>
              <tr>
                <th>Materia</th>
                <th>Categoría</th>
                <th>Estado</th>
                <th>Campos</th>
                <th>Ofertas</th>
                <th></th>
              </tr>
            </thead>
            <tbody>
              {visible.map((item) => (
                <tr key={String(item.id)}>
                  <td>
                    <strong>{String(item.nombre)}</strong>
                    <small>
                      {String(item.codigo)} · /{String(item.slug)}
                    </small>
                  </td>
                  <td>{String(item.categoria || "—")}</td>
                  <td>{String(item.estado)}</td>
                  <td>{String(item.campos || 0)}</td>
                  <td>{String(item.ofertas || 0)}</td>
                  <td>
                    <button
                      className="table-action"
                      type="button"
                      onClick={() => void loadDetail(Number(item.id))}
                    >
                      Editar
                    </button>
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
        <div className="table-pagination">
          <button
            disabled={page <= 1}
            onClick={() => setPage((value) => value - 1)}
          >
            Anterior
          </button>
          <span>
            Página {page} de {pages}
          </span>
          <button
            disabled={page >= pages}
            onClick={() => setPage((value) => value + 1)}
          >
            Siguiente
          </button>
        </div>
      </section>
      {modalOpen && (
        <div
          className="admin-modal-backdrop"
          onMouseDown={(event) => {
            if (event.target === event.currentTarget) setModalOpen(false);
          }}
        >
          <section
            className="admin-modal admin-modal-large"
            role="dialog"
            aria-modal="true"
          >
            <header>
              <div>
                <span className="section-kicker">
                  Administración de materias
                </span>
                <h2>
                  {selected
                    ? String(matter?.nombre || "Cargando materia…")
                    : "Nueva materia"}
                </h2>
              </div>
              <button
                className="modal-close"
                type="button"
                onClick={() => setModalOpen(false)}
                aria-label="Cerrar"
              >
                ×
              </button>
            </header>
            <div className="admin-modal-layout">
              <nav className="admin-modal-nav">
                <button type="button" onClick={() => goTo("matter-data")}>
                  Datos
                </button>
                <button
                  type="button"
                  disabled={!selected}
                  onClick={() => goTo("matter-fields")}
                >
                  Campos
                </button>
                <button
                  type="button"
                  disabled={!selected}
                  onClick={() => goTo("matter-template")}
                >
                  Plantilla
                </button>
                <button
                  type="button"
                  disabled={!selected}
                  onClick={() => goTo("matter-offers")}
                >
                  Oferta
                </button>
              </nav>
              <div className="matter-workspace">
                <form
                  key={selected || "new"}
                  className="panel-card profile-form"
                  onSubmit={saveMatter}
                >
                  <h2>
                    {selected ? "Configuración de materia" : "Nueva materia"}
                  </h2>
                  <div className="form-pair">
                    <label>
                      Nombre
                      <input
                        name="nombre"
                        defaultValue={matter ? String(matter.nombre) : ""}
                        required
                      />
                    </label>
                    <label>
                      Código
                      <input
                        name="codigo"
                        defaultValue={matter ? String(matter.codigo) : ""}
                        required
                      />
                    </label>
                  </div>
                  <div className="form-pair">
                    <label>
                      Slug público
                      <input
                        name="slug"
                        defaultValue={matter ? String(matter.slug) : ""}
                        pattern="[a-z0-9]+(?:-[a-z0-9]+)*"
                        required
                      />
                    </label>
                    <label>
                      Categoría
                      <select
                        name="categoria_id"
                        defaultValue={
                          matter ? String(matter.categoria_materia_id) : ""
                        }
                        required
                      >
                        <option value="">Seleccionar</option>
                        {categories.map((c) => (
                          <option key={String(c.id)} value={String(c.id)}>
                            {String(c.nombre)}
                          </option>
                        ))}
                      </select>
                    </label>
                  </div>
                  <label>
                    Descripción corta
                    <input
                      name="descripcion_corta"
                      defaultValue={
                        matter ? String(matter.descripcion_corta || "") : ""
                      }
                    />
                  </label>
                  <label>
                    Descripción
                    <textarea
                      name="descripcion"
                      defaultValue={
                        matter ? String(matter.descripcion || "") : ""
                      }
                    />
                  </label>
                  <div className="form-pair">
                    <label>
                      Comparecientes
                      <input
                        name="requiere_comparecientes"
                        type="number"
                        min="0"
                        max="20"
                        defaultValue={
                          matter ? Number(matter.requiere_comparecientes) : 1
                        }
                      />
                    </label>
                    <label>
                      Estado
                      <select
                        name="estado"
                        defaultValue={
                          matter ? String(matter.estado) : "BORRADOR"
                        }
                      >
                        <option value="BORRADOR">Borrador</option>
                        <option value="ACTIVA">Activa en el front</option>
                        <option value="INACTIVA">Inactiva</option>
                      </select>
                    </label>
                  </div>
                  <div className="option-checks">
                    <label>
                      <input
                        name="permite_adjuntos"
                        type="checkbox"
                        defaultChecked={
                          !matter || Boolean(matter.permite_adjuntos)
                        }
                      />{" "}
                      Permitir adjuntos
                    </label>
                  </div>
                  <button className="button button-primary">
                    {selected ? "Guardar materia" : "Crear materia"}
                  </button>
                </form>
                {selected && (
                  <>
                    <section className="panel-card">
                      <div className="card-heading">
                        <div>
                          <h2>Campos y orden</h2>
                          <p className="muted-copy">
                            El número menor aparece primero. Recomendamos 10,
                            20, 30 para poder insertar campos después.
                          </p>
                        </div>
                        <button
                          className="table-action"
                          type="button"
                          onClick={() => setEditingField({})}
                        >
                          Agregar campo
                        </button>
                      </div>
                      <div className="field-order-list">
                        {fields.map((field) => (
                          <article
                            key={String(field.id)}
                            className={!field.activo ? "is-disabled" : ""}
                          >
                            <span className="order-badge">
                              {String(field.orden)}
                            </span>
                            <div>
                              <strong>{String(field.etiqueta)}</strong>
                              <small>
                                {`{{campo.${field.codigo}}}`} ·{" "}
                                {String(field.tipo_dato)} ·{" "}
                                {field.requerido ? "Obligatorio" : "Opcional"}
                              </small>
                            </div>
                            <button
                              className="table-action"
                              type="button"
                              onClick={() => setEditingField(field)}
                            >
                              Editar
                            </button>
                            {Boolean(field.activo) && (
                              <button
                                className="table-action danger"
                                type="button"
                                onClick={() =>
                                  void disableField(Number(field.id))
                                }
                              >
                                Desactivar
                              </button>
                            )}
                          </article>
                        ))}
                      </div>
                      {editingField && (
                        <form
                          key={String(editingField.id || "new")}
                          className="profile-form nested-form"
                          onSubmit={saveField}
                        >
                          <div className="form-pair">
                            <label>
                              <span>
                                Etiqueta{" "}
                                <i
                                  className="help-tip"
                                  title="Texto que verá el cliente. Ejemplo: RUT del apoderado"
                                >
                                  ?
                                </i>
                              </span>
                              <input
                                name="etiqueta"
                                placeholder="Ej. RUT del apoderado"
                                defaultValue={String(
                                  editingField.etiqueta || "",
                                )}
                                required
                              />
                            </label>
                            <label>
                              <span>
                                Variable/código{" "}
                                <i
                                  className="help-tip"
                                  title="Solo minúsculas, números y guion bajo. Se utilizará como {{campo.rut_apoderado}}"
                                >
                                  ?
                                </i>
                              </span>
                              <input
                                name="codigo"
                                pattern="[a-z][a-z0-9_]*"
                                placeholder="Ej. rut_apoderado"
                                onChange={(event) =>
                                  (event.currentTarget.value =
                                    event.currentTarget.value
                                      .toLowerCase()
                                      .replace(/[^a-z0-9_]/g, "_")
                                      .replace(/^([^a-z])/, ""))
                                }
                                defaultValue={String(editingField.codigo || "")}
                                required
                              />
                              <small className="field-hint">
                                Ejemplo de plantilla:{" "}
                                {`{{campo.${String(editingField.codigo || "rut_apoderado")}}}`}
                              </small>
                            </label>
                          </div>
                          <div className="form-pair">
                            <label>
                              <span>
                                Tipo{" "}
                                <i
                                  className="help-tip"
                                  title="Define el control y su validación automática en el formulario público"
                                >
                                  ?
                                </i>
                              </span>
                              <select
                                name="tipo_dato"
                                defaultValue={String(
                                  editingField.tipo_dato || "TEXTO",
                                )}
                              >
                                {types.map((t) => (
                                  <option
                                    key={String(t.id)}
                                    value={String(t.codigo)}
                                  >
                                    {String(t.nombre)}
                                  </option>
                                ))}
                              </select>
                            </label>
                            <label>
                              <span>
                                Orden{" "}
                                <i
                                  className="help-tip"
                                  title="Los campos se muestran de menor a mayor. Usa 10, 20, 30…"
                                >
                                  ?
                                </i>
                              </span>
                              <input
                                name="orden"
                                type="number"
                                min="0"
                                step="1"
                                defaultValue={Number(
                                  editingField.orden ||
                                    (fields.length + 1) * 10,
                                )}
                              />
                            </label>
                          </div>
                          <label>
                            <span>
                              Texto de ayuda{" "}
                              <i
                                className="help-tip"
                                title="Explicación visible bajo el campo"
                              >
                                ?
                              </i>
                            </span>
                            <input
                              name="ayuda"
                              placeholder="Ej. Ingresa el RUT sin puntos; lo formatearemos automáticamente"
                              defaultValue={String(editingField.ayuda || "")}
                            />
                          </label>
                          <label>
                            <span>
                              Ejemplo dentro del campo{" "}
                              <i
                                className="help-tip"
                                title="Placeholder que desaparece al escribir"
                              >
                                ?
                              </i>
                            </span>
                            <input
                              name="placeholder"
                              placeholder="Ej. 12.345.678-9"
                              defaultValue={String(
                                editingField.placeholder || "",
                              )}
                            />
                          </label>
                          <div className="form-pair">
                            <label>
                              <span>
                                Largo mínimo{" "}
                                <i
                                  className="help-tip"
                                  title="Cantidad mínima de caracteres permitida"
                                >
                                  ?
                                </i>
                              </span>
                              <input
                                name="largo_minimo"
                                type="number"
                                min="0"
                                placeholder="Ej. 3"
                                defaultValue={
                                  editingField.largo_minimo
                                    ? Number(editingField.largo_minimo)
                                    : undefined
                                }
                              />
                            </label>
                            <label>
                              <span>
                                Largo máximo{" "}
                                <i
                                  className="help-tip"
                                  title="Cantidad máxima de caracteres permitida"
                                >
                                  ?
                                </i>
                              </span>
                              <input
                                name="largo_maximo"
                                type="number"
                                min="1"
                                placeholder="Ej. 120"
                                defaultValue={
                                  editingField.largo_maximo
                                    ? Number(editingField.largo_maximo)
                                    : undefined
                                }
                              />
                            </label>
                          </div>
                          <div className="form-pair">
                            <label>
                              <span>
                                Valor mínimo{" "}
                                <i
                                  className="help-tip"
                                  title="Solo para campos numéricos"
                                >
                                  ?
                                </i>
                              </span>
                              <input
                                name="valor_minimo"
                                type="number"
                                placeholder="Ej. 1"
                                defaultValue={
                                  editingField.valor_minimo
                                    ? Number(editingField.valor_minimo)
                                    : undefined
                                }
                              />
                            </label>
                            <label>
                              <span>
                                Valor máximo{" "}
                                <i
                                  className="help-tip"
                                  title="Solo para campos numéricos"
                                >
                                  ?
                                </i>
                              </span>
                              <input
                                name="valor_maximo"
                                type="number"
                                placeholder="Ej. 99"
                                defaultValue={
                                  editingField.valor_maximo
                                    ? Number(editingField.valor_maximo)
                                    : undefined
                                }
                              />
                            </label>
                          </div>
                          <label>
                            <span>
                              Expresión regular avanzada{" "}
                              <i
                                className="help-tip"
                                title="Opcional. Úsala solo para formatos que no cubra el tipo seleccionado"
                              >
                                ?
                              </i>
                            </span>
                            <input
                              name="patron_regex"
                              placeholder="Ej. [A-Z]{2}-[0-9]{6}"
                              defaultValue={String(
                                editingField.patron_regex || "",
                              )}
                            />
                          </label>
                          <label>
                            <span>
                              Opciones de lista{" "}
                              <i
                                className="help-tip"
                                title="Solo para tipo Lista. Escribe una opción por línea"
                              >
                                ?
                              </i>
                            </span>
                            <textarea
                              name="opciones"
                              placeholder={
                                "Opción uno\nOpción dos\nOpción tres"
                              }
                              defaultValue={
                                editingField.opciones_json
                                  ? JSON.parse(
                                      String(editingField.opciones_json),
                                    ).join("\n")
                                  : ""
                              }
                            />
                          </label>
                          <div className="option-checks">
                            <label>
                              <input
                                name="requerido"
                                type="checkbox"
                                defaultChecked={Boolean(editingField.requerido)}
                              />{" "}
                              Campo obligatorio
                            </label>
                          </div>
                          <div className="wizard-actions">
                            <button
                              className="button button-secondary"
                              type="button"
                              onClick={() => setEditingField(null)}
                            >
                              Cancelar
                            </button>
                            <button className="button button-primary">
                              Guardar campo
                            </button>
                          </div>
                        </form>
                      )}
                    </section>
                    <section className="panel-card">
                      <h2>Plantilla del documento</h2>
                      <div className="template-variables">
                        <code>{"{{folio}}"}</code>
                        <code>{"{{cliente.nombres}}"}</code>
                        <code>{"{{cliente.apellidos}}"}</code>
                        <code>{"{{cliente.rut}}"}</code>
                        <code>{"{{cliente.email}}"}</code>
                        {fields
                          .filter((f) => f.activo)
                          .map((f) => (
                            <code
                              key={String(f.id)}
                            >{`{{campo.${f.codigo}}}`}</code>
                          ))}
                      </div>
                      <form
                        key={String(template?.id || "new-template")}
                        className="profile-form"
                        onSubmit={saveTemplate}
                      >
                        <label>
                          Nombre de plantilla
                          <input
                            name="nombre"
                            defaultValue={
                              template
                                ? String(template.nombre)
                                : `${matter?.nombre || "Documento"} v1`
                            }
                            required
                          />
                        </label>
                        <label>
                          Contenido
                          <textarea
                            className="template-editor"
                            name="contenido"
                            defaultValue={
                              template
                                ? String(template.contenido)
                                : `DOCUMENTO: ${matter?.nombre || ""}\n\nComparece {{cliente.nombres}} {{cliente.apellidos}}, RUT {{cliente.rut}}.\n\n`
                            }
                            required
                          />
                        </label>
                        <button className="button button-primary">
                          Publicar nueva versión
                        </button>
                      </form>
                    </section>
                    <section className="panel-card">
                      <h2>Oferta por notaría</h2>
                      <form className="profile-form" onSubmit={saveOffer}>
                        <label>
                          Notaría
                          <select name="notaria_id" required>
                            <option value="">Seleccionar</option>
                            {notaries.map((n) => (
                              <option key={String(n.id)} value={String(n.id)}>
                                {String(n.nombre_fantasia)}
                              </option>
                            ))}
                          </select>
                        </label>
                        <div className="form-pair">
                          <label>
                            Código interno GesNot
                            <input name="codigo_gesnot" required />
                          </label>
                          <label>
                            tipoOT GN
                            <input
                              name="gesnot_tipo_ot"
                              type="number"
                              min="1"
                              defaultValue="2"
                              required
                            />
                          </label>
                        </div>
                        <label>
                          Materia exacta enviada a GN
                          <input
                            name="gesnot_materia"
                            defaultValue={String(
                              matter?.nombre || "",
                            ).toUpperCase()}
                            required
                          />
                        </label>
                        <div className="form-pair">
                          <label>
                            Precio
                            <input
                              name="precio"
                              type="number"
                              min="0"
                              required
                            />
                          </label>
                          <label>
                            Plazo estimado (horas)
                            <input
                              name="plazo_estimado_horas"
                              type="number"
                              min="1"
                            />
                          </label>
                        </div>
                        <div className="option-checks">
                          <label>
                            <input
                              name="activo"
                              type="checkbox"
                              defaultChecked
                            />{" "}
                            Oferta activa
                          </label>
                        </div>
                        <button className="button button-primary">
                          Guardar oferta
                        </button>
                      </form>
                      <DataTable rows={offers} />
                    </section>
                  </>
                )}
              </div>
            </div>
          </section>
        </div>
      )}
    </div>
  );
}
