"use client";

import { useEffect, useMemo, useState } from "react";
import ExperienciometroTabs from "@/components/experienciometro/ExperienciometroTabs";
import type { ExperiencePolicyDTO, ExperienceTemplateCategoryDTO, ExperienceTemplateDTO } from "@/lib/experienciometro/types";

function cloneTemplate(template: ExperienceTemplateDTO): ExperienceTemplateDTO {
  return {
    ...template,
    categories: template.categories.map((category) => ({
      ...category,
      items: category.items.map((item) => ({ ...item })),
    })),
  };
}

export default function ExperienciometroConfigPage() {
  const [templates, setTemplates] = useState<ExperienceTemplateDTO[]>([]);
  const [selectedTemplateId, setSelectedTemplateId] = useState("");
  const [editingTemplate, setEditingTemplate] = useState<ExperienceTemplateDTO | null>(null);
  const [policy, setPolicy] = useState<ExperiencePolicyDTO | null>(null);
  const [isLoading, setIsLoading] = useState(true);
  const [isSavingTemplate, setIsSavingTemplate] = useState(false);
  const [isSavingPolicy, setIsSavingPolicy] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [message, setMessage] = useState<string | null>(null);

  const currentTemplate = useMemo(
    () => templates.find((template) => template.id === selectedTemplateId) ?? templates[0] ?? null,
    [selectedTemplateId, templates]
  );

  useEffect(() => {
    const controller = new AbortController();

    const load = async () => {
      setIsLoading(true);
      setError(null);
      try {
        const [templatesResponse, policyResponse] = await Promise.all([
          fetch("/api/experienciometro/templates", {
            method: "GET",
            cache: "no-store",
            signal: controller.signal,
          }),
          fetch("/api/experienciometro/scoring-policy", {
            method: "GET",
            cache: "no-store",
            signal: controller.signal,
          }),
        ]);

        const templatesPayload = (await templatesResponse.json()) as { error?: string; templates?: ExperienceTemplateDTO[] };
        const policyPayload = (await policyResponse.json()) as { error?: string; policy?: ExperiencePolicyDTO };

        if (!templatesResponse.ok) {
          throw new Error(templatesPayload.error ?? "No se pudieron cargar plantillas.");
        }

        if (!policyResponse.ok) {
          throw new Error(policyPayload.error ?? "No se pudo cargar política de score.");
        }

        const list = templatesPayload.templates ?? [];
        setTemplates(list);
        setSelectedTemplateId((current) => current || list[0]?.id || "");
        setPolicy(policyPayload.policy ?? null);
      } catch (loadError) {
        if (controller.signal.aborted) {
          return;
        }

        setError(loadError instanceof Error ? loadError.message : "No se pudo cargar configuración.");
      } finally {
        if (!controller.signal.aborted) {
          setIsLoading(false);
        }
      }
    };

    void load();

    return () => controller.abort();
  }, []);

  useEffect(() => {
    if (currentTemplate) {
      setEditingTemplate(cloneTemplate(currentTemplate));
    }
  }, [currentTemplate]);

  const upsertCategory = () => {
    if (!editingTemplate) {
      return;
    }

    const nextCategory: ExperienceTemplateCategoryDTO = {
      id: `tmp-cat-${Date.now()}`,
      key: `nueva_categoria_${editingTemplate.categories.length + 1}`,
      name: "Nueva categoría",
      weight: 1,
      sortOrder: editingTemplate.categories.length,
      items: [
        {
          id: `tmp-item-${Date.now()}`,
          key: "nuevo_item",
          label: "Nuevo reactivo",
          weight: 1,
          sortOrder: 0,
          allowsComment: true,
          requiresObservation: false,
          allowsEvidence: true,
          isActive: true,
        },
      ],
    };

    setEditingTemplate({
      ...editingTemplate,
      categories: [...editingTemplate.categories, nextCategory],
    });
  };

  const saveTemplate = async (publish: boolean) => {
    if (!editingTemplate) {
      return;
    }

    setIsSavingTemplate(true);
    setError(null);
    setMessage(null);

    try {
      const response = await fetch(`/api/experienciometro/templates/${editingTemplate.id}`, {
        method: "PATCH",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          name: editingTemplate.name,
          isDefault: editingTemplate.isDefault,
          categories: editingTemplate.categories.map((category, categoryIndex) => ({
            key: category.key,
            name: category.name,
            weight: category.weight,
            sortOrder: categoryIndex,
            items: category.items.map((item, itemIndex) => ({
              key: item.key,
              label: item.label,
              weight: item.weight,
              sortOrder: itemIndex,
              allowsComment: item.allowsComment,
              requiresObservation: item.requiresObservation,
              allowsEvidence: item.allowsEvidence,
              isActive: item.isActive,
            })),
          })),
          publish,
        }),
      });

      const payload = (await response.json()) as { error?: string; template?: ExperienceTemplateDTO };
      if (!response.ok || !payload.template) {
        throw new Error(payload.error ?? "No se pudo guardar plantilla.");
      }

      setTemplates((prev) => {
        const updated = prev.map((template) => (template.id === payload.template!.id ? payload.template! : template));
        return updated.sort((a, b) => (b.updatedAt > a.updatedAt ? 1 : -1));
      });
      setEditingTemplate(cloneTemplate(payload.template));
      setMessage(publish ? "Plantilla publicada correctamente." : "Plantilla guardada correctamente.");
    } catch (saveError) {
      setError(saveError instanceof Error ? saveError.message : "No se pudo guardar plantilla.");
    } finally {
      setIsSavingTemplate(false);
    }
  };

  const createDraft = async () => {
    if (!currentTemplate) {
      return;
    }

    setError(null);
    setMessage(null);

    try {
      const response = await fetch("/api/experienciometro/templates", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          name: `${currentTemplate.name} (borrador)`,
          fromTemplateId: currentTemplate.id,
        }),
      });

      const payload = (await response.json()) as { error?: string; template?: ExperienceTemplateDTO };
      if (!response.ok || !payload.template) {
        throw new Error(payload.error ?? "No se pudo crear borrador.");
      }

      setTemplates((prev) => [payload.template!, ...prev]);
      setSelectedTemplateId(payload.template.id);
      setMessage("Borrador creado.");
    } catch (createError) {
      setError(createError instanceof Error ? createError.message : "No se pudo crear borrador.");
    }
  };

  const savePolicy = async () => {
    if (!policy) {
      return;
    }

    setIsSavingPolicy(true);
    setError(null);
    setMessage(null);

    try {
      const response = await fetch("/api/experienciometro/scoring-policy", {
        method: "PATCH",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          name: policy.name,
          aggregationMode: policy.aggregationMode,
          recentWindow: policy.recentWindow,
          recentWeights: policy.recentWeights,
          greenThreshold: policy.greenThreshold,
          yellowThreshold: policy.yellowThreshold,
          isActive: true,
        }),
      });

      const payload = (await response.json()) as { error?: string; policy?: ExperiencePolicyDTO };
      if (!response.ok || !payload.policy) {
        throw new Error(payload.error ?? "No se pudo guardar política.");
      }

      setPolicy(payload.policy);
      setMessage("Política de score actualizada.");
    } catch (saveError) {
      setError(saveError instanceof Error ? saveError.message : "No se pudo guardar política.");
    } finally {
      setIsSavingPolicy(false);
    }
  };

  return (
    <div className="space-y-5">
      <header className="rounded-benell border border-benell-stroke bg-benell-surface p-5 shadow-benell">
        <p className="text-sm font-semibold uppercase tracking-wide text-benell-brown">Configuración</p>
        <h1 className="mt-1 text-2xl font-semibold text-benell-text">Constructor de checklist y scoring</h1>
        <p className="mt-1 text-sm text-benell-text-soft">Administra versiones de plantilla y parámetros de cálculo del Experienciómetro.</p>
      </header>

      <ExperienciometroTabs />

      {error ? <p className="text-sm font-semibold text-benell-red">{error}</p> : null}
      {message ? <p className="text-sm font-semibold text-benell-green">{message}</p> : null}
      {isLoading ? <p className="text-sm text-benell-text-soft">Cargando configuración...</p> : null}

      {editingTemplate && policy ? (
        <>
          <section className="rounded-benell border border-benell-stroke bg-benell-surface p-4 shadow-benell">
            <div className="grid gap-3 md:grid-cols-[220px_minmax(0,1fr)_auto] md:items-end">
              <label className="space-y-1">
                <span className="text-xs font-semibold text-benell-text-soft">Plantilla</span>
                <select
                  value={selectedTemplateId}
                  onChange={(event) => setSelectedTemplateId(event.target.value)}
                  className="w-full rounded-xl border border-benell-stroke bg-white px-3 py-2 text-sm"
                >
                  {templates.map((template) => (
                    <option key={template.id} value={template.id}>
                      v{template.version} · {template.name} · {template.state}
                    </option>
                  ))}
                </select>
              </label>

              <label className="space-y-1">
                <span className="text-xs font-semibold text-benell-text-soft">Nombre plantilla</span>
                <input
                  value={editingTemplate.name}
                  onChange={(event) => setEditingTemplate({ ...editingTemplate, name: event.target.value })}
                  className="w-full rounded-xl border border-benell-stroke bg-white px-3 py-2 text-sm"
                />
              </label>

              <button type="button" onClick={() => void createDraft()} className="rounded-pill border border-benell-stroke px-3 py-2 text-sm font-semibold">
                Nuevo borrador
              </button>
            </div>

            <div className="mt-4 space-y-3">
              {editingTemplate.categories.map((category, categoryIndex) => (
                <article key={category.id} className="rounded-xl border border-benell-stroke bg-white p-3">
                  <div className="grid gap-2 md:grid-cols-[minmax(0,1fr)_120px]">
                    <label className="space-y-1">
                      <span className="text-xs font-semibold text-benell-text-soft">Categoría</span>
                      <input
                        value={category.name}
                        onChange={(event) =>
                          setEditingTemplate((prev) => {
                            if (!prev) {
                              return prev;
                            }

                            const next = cloneTemplate(prev);
                            next.categories[categoryIndex].name = event.target.value;
                            next.categories[categoryIndex].key = event.target.value.toLowerCase().replace(/\s+/g, "_");
                            return next;
                          })
                        }
                        className="w-full rounded-lg border border-benell-stroke bg-white px-2 py-1.5 text-sm"
                      />
                    </label>
                    <label className="space-y-1">
                      <span className="text-xs font-semibold text-benell-text-soft">Peso</span>
                      <input
                        type="number"
                        min={0.1}
                        step={0.1}
                        value={category.weight}
                        onChange={(event) =>
                          setEditingTemplate((prev) => {
                            if (!prev) {
                              return prev;
                            }

                            const next = cloneTemplate(prev);
                            next.categories[categoryIndex].weight = Number(event.target.value) || 1;
                            return next;
                          })
                        }
                        className="w-full rounded-lg border border-benell-stroke bg-white px-2 py-1.5 text-sm"
                      />
                    </label>
                  </div>

                  <div className="mt-2 space-y-2">
                    {category.items.map((item, itemIndex) => (
                      <div key={item.id} className="grid gap-2 md:grid-cols-[minmax(0,1fr)_80px_120px]">
                        <input
                          value={item.label}
                          onChange={(event) =>
                            setEditingTemplate((prev) => {
                              if (!prev) {
                                return prev;
                              }

                              const next = cloneTemplate(prev);
                              next.categories[categoryIndex].items[itemIndex].label = event.target.value;
                              next.categories[categoryIndex].items[itemIndex].key = event.target.value.toLowerCase().replace(/\s+/g, "_");
                              return next;
                            })
                          }
                          className="rounded-lg border border-benell-stroke bg-white px-2 py-1.5 text-sm"
                        />
                        <input
                          type="number"
                          min={0.1}
                          step={0.1}
                          value={item.weight}
                          onChange={(event) =>
                            setEditingTemplate((prev) => {
                              if (!prev) {
                                return prev;
                              }

                              const next = cloneTemplate(prev);
                              next.categories[categoryIndex].items[itemIndex].weight = Number(event.target.value) || 1;
                              return next;
                            })
                          }
                          className="rounded-lg border border-benell-stroke bg-white px-2 py-1.5 text-sm"
                        />
                        <label className="inline-flex items-center gap-2 text-xs font-semibold text-benell-text-soft">
                          <input
                            type="checkbox"
                            checked={item.requiresObservation}
                            onChange={(event) =>
                              setEditingTemplate((prev) => {
                                if (!prev) {
                                  return prev;
                                }

                                const next = cloneTemplate(prev);
                                next.categories[categoryIndex].items[itemIndex].requiresObservation = event.target.checked;
                                return next;
                              })
                            }
                          />
                          Requiere obs.
                        </label>
                      </div>
                    ))}
                  </div>

                  <button
                    type="button"
                    onClick={() =>
                      setEditingTemplate((prev) => {
                        if (!prev) {
                          return prev;
                        }

                        const next = cloneTemplate(prev);
                        const bucket = next.categories[categoryIndex].items;
                        bucket.push({
                          id: `tmp-item-${Date.now()}`,
                          key: `nuevo_item_${bucket.length + 1}`,
                          label: "Nuevo reactivo",
                          weight: 1,
                          sortOrder: bucket.length,
                          allowsComment: true,
                          requiresObservation: false,
                          allowsEvidence: true,
                          isActive: true,
                        });
                        return next;
                      })
                    }
                    className="mt-3 rounded-pill border border-benell-stroke px-3 py-1.5 text-xs font-semibold"
                  >
                    + Agregar reactivo
                  </button>
                </article>
              ))}
            </div>

            <div className="mt-3 flex flex-wrap justify-between gap-2">
              <button type="button" onClick={() => upsertCategory()} className="rounded-pill border border-benell-stroke px-3 py-2 text-sm font-semibold">
                + Agregar categoría
              </button>
              <div className="flex gap-2">
                <button
                  type="button"
                  disabled={isSavingTemplate}
                  onClick={() => void saveTemplate(false)}
                  className="rounded-pill border border-benell-stroke px-3 py-2 text-sm font-semibold disabled:opacity-60"
                >
                  Guardar borrador
                </button>
                <button
                  type="button"
                  disabled={isSavingTemplate}
                  onClick={() => void saveTemplate(true)}
                  className="rounded-pill bg-benell-brown px-3 py-2 text-sm font-semibold text-white disabled:opacity-60"
                >
                  Publicar versión
                </button>
              </div>
            </div>
          </section>

          <section className="rounded-benell border border-benell-stroke bg-benell-surface p-4 shadow-benell">
            <h2 className="text-h2 font-semibold text-benell-text">Política de scoring</h2>
            <div className="mt-3 grid gap-2 md:grid-cols-2 xl:grid-cols-4">
              <label className="space-y-1">
                <span className="text-xs font-semibold text-benell-text-soft">Modo</span>
                <select
                  value={policy.aggregationMode}
                  onChange={(event) => setPolicy({ ...policy, aggregationMode: event.target.value as ExperiencePolicyDTO["aggregationMode"] })}
                  className="w-full rounded-lg border border-benell-stroke bg-white px-2 py-1.5 text-sm"
                >
                  <option value="weighted_recent">Weighted recent</option>
                  <option value="moving_average">Moving average</option>
                  <option value="full_average">Full average</option>
                </select>
              </label>
              <label className="space-y-1">
                <span className="text-xs font-semibold text-benell-text-soft">Ventana reciente</span>
                <input
                  type="number"
                  min={1}
                  value={policy.recentWindow}
                  onChange={(event) => setPolicy({ ...policy, recentWindow: Number(event.target.value) || 1 })}
                  className="w-full rounded-lg border border-benell-stroke bg-white px-2 py-1.5 text-sm"
                />
              </label>
              <label className="space-y-1">
                <span className="text-xs font-semibold text-benell-text-soft">Umbral verde</span>
                <input
                  type="number"
                  min={0}
                  max={100}
                  value={policy.greenThreshold}
                  onChange={(event) => setPolicy({ ...policy, greenThreshold: Number(event.target.value) || 85 })}
                  className="w-full rounded-lg border border-benell-stroke bg-white px-2 py-1.5 text-sm"
                />
              </label>
              <label className="space-y-1">
                <span className="text-xs font-semibold text-benell-text-soft">Umbral amarillo</span>
                <input
                  type="number"
                  min={0}
                  max={100}
                  value={policy.yellowThreshold}
                  onChange={(event) => setPolicy({ ...policy, yellowThreshold: Number(event.target.value) || 70 })}
                  className="w-full rounded-lg border border-benell-stroke bg-white px-2 py-1.5 text-sm"
                />
              </label>
            </div>

            <label className="mt-3 block space-y-1">
              <span className="text-xs font-semibold text-benell-text-soft">Pesos recientes (coma separada)</span>
              <input
                value={policy.recentWeights.join(",")}
                onChange={(event) => {
                  const values = event.target.value
                    .split(",")
                    .map((value) => Number(value.trim()))
                    .filter((value) => Number.isFinite(value) && value > 0);
                  setPolicy({ ...policy, recentWeights: values.length > 0 ? values : [0.5, 0.3, 0.2] });
                }}
                className="w-full rounded-lg border border-benell-stroke bg-white px-2 py-1.5 text-sm"
              />
            </label>

            <div className="mt-3 flex justify-end">
              <button
                type="button"
                disabled={isSavingPolicy}
                onClick={() => void savePolicy()}
                className="rounded-pill bg-benell-brown px-4 py-2 text-sm font-semibold text-white disabled:opacity-60"
              >
                {isSavingPolicy ? "Guardando..." : "Guardar política"}
              </button>
            </div>
          </section>
        </>
      ) : null}
    </div>
  );
}
