"use client";

import { useEffect, useMemo, useState } from "react";
import { useForm } from "react-hook-form";
import type { FormConfig, FormDataPayload, SubmitPayload } from "@/types/form";
import { evaluate } from "@/lib/conditional";
import { StageSection } from "./StageSection";

interface EngagementFormProps {
  config: FormConfig;
  cid: string;
  cs: string;
}

type LoadState =
  | { kind: "loading" }
  | { kind: "error"; message: string }
  | { kind: "ready"; data: FormDataPayload };

/**
 * Top-level form orchestrator. Responsible for:
 *   - fetching prefill data + the org's current stage from /api/data
 *   - hydrating react-hook-form with prefill values
 *   - re-evaluating section visibility against live form values on every change
 *   - submitting to /api/submit and surfacing success / error feedback
 */
export function EngagementForm({ config, cid, cs }: EngagementFormProps) {
  const [load, setLoad] = useState<LoadState>({ kind: "loading" });
  const [submitState, setSubmitState] = useState<
    | { kind: "idle" }
    | { kind: "submitting" }
    | { kind: "success" }
    | { kind: "error"; message: string }
  >({ kind: "idle" });

  const {
    register,
    handleSubmit,
    reset,
    watch,
    formState: { errors },
  } = useForm({ mode: "onBlur" });

  // Subscribe to all form values so section visibility re-evaluates live.
  const formValues = watch();

  useEffect(() => {
    let cancelled = false;
    async function go() {
      try {
        const url = new URL("/api/data", window.location.origin);
        url.searchParams.set("cid", cid);
        url.searchParams.set("cs", cs);
        const res = await fetch(url.toString(), { cache: "no-store" });
        if (!res.ok) {
          const text = await res.text();
          if (!cancelled) {
            setLoad({ kind: "error", message: `Could not load form (${res.status}). ${text}` });
          }
          return;
        }
        const data: FormDataPayload = await res.json();
        if (cancelled) return;
        // Merge stage value + per-field prefill into a single defaults map.
        const defaults = {
          [config.stageField]: data.currentStage,
          ...data.prefill,
        };
        reset(defaults);
        setLoad({ kind: "ready", data });
      } catch (e) {
        if (!cancelled) {
          setLoad({
            kind: "error",
            message: e instanceof Error ? e.message : "Unexpected error loading form.",
          });
        }
      }
    }
    void go();
    return () => {
      cancelled = true;
    };
  }, [cid, cs, reset, config.stageField]);

  const sectionsToRender = useMemo(() => {
    return config.sections.map((s) => ({
      section: s,
      sectionVisible: evaluate(s.visibleWhen, formValues),
    }));
  }, [config.sections, formValues]);

  // The "current" rank: highest section rank whose visibility rule matches
  // the current stage value. If nothing matches, fall back to 0 (Inquiry).
  const currentRank = useMemo(() => {
    const visibleRanks = sectionsToRender
      .filter((s) => s.sectionVisible)
      .map((s) => s.section.rank);
    return visibleRanks.length > 0 ? Math.max(...visibleRanks) : 0;
  }, [sectionsToRender]);

  if (load.kind === "loading") {
    return <LoadingState />;
  }
  if (load.kind === "error") {
    return <ErrorState message={load.message} />;
  }

  const onSubmit = async (values: Record<string, unknown>) => {
    setSubmitState({ kind: "submitting" });
    try {
      // Strip values for fields whose section or field rule isn't currently visible —
      // those aren't part of the user's intent in this submission.
      const visibleFieldNames = new Set<string>();
      for (const s of config.sections) {
        if (!evaluate(s.visibleWhen, values)) continue;
        for (const f of s.fields) {
          if (evaluate(f.visibleWhen, values)) {
            visibleFieldNames.add(f.name);
          }
        }
      }
      const filtered: Record<string, unknown> = {};
      for (const [k, v] of Object.entries(values)) {
        if (visibleFieldNames.has(k)) filtered[k] = v;
      }
      const payload: SubmitPayload = { cid, cs, values: filtered };
      const res = await fetch("/api/submit", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(payload),
      });
      if (!res.ok) {
        const text = await res.text();
        setSubmitState({ kind: "error", message: `Submit failed (${res.status}). ${text}` });
        return;
      }
      setSubmitState({ kind: "success" });
    } catch (e) {
      setSubmitState({
        kind: "error",
        message: e instanceof Error ? e.message : "Unexpected submit error.",
      });
    }
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)} className="space-y-5" noValidate>
      <SubmissionContextHeader
        orgName={load.data.orgName}
        currentStage={load.data.currentStage}
      />

      {sectionsToRender.map(({ section, sectionVisible }) => {
        if (!sectionVisible) return null;
        return (
          <StageSection
            key={section.id}
            section={section}
            register={register}
            errors={errors}
            formValues={formValues}
            isCurrent={section.rank === currentRank}
            defaultOpen={section.rank === currentRank || section.rank === 0}
          />
        );
      })}

      <div className="sticky bottom-4 z-10 flex flex-col-reverse gap-3 rounded-xl border border-stone-200 bg-white/95 px-5 py-4 shadow-lg backdrop-blur-sm sm:flex-row sm:items-center sm:justify-between">
        <SubmitFeedback state={submitState} />
        <button
          type="submit"
          disabled={submitState.kind === "submitting"}
          className={
            "inline-flex items-center justify-center rounded-md px-5 py-2.5 font-medium text-white transition " +
            "bg-leaf-700 hover:bg-leaf-800 focus:outline-none focus-visible:ring-2 focus-visible:ring-leaf-500/40 " +
            "disabled:cursor-not-allowed disabled:bg-stone-400"
          }
        >
          {submitState.kind === "submitting" ? "Saving…" : "Submit check-in"}
        </button>
      </div>
    </form>
  );
}

function SubmissionContextHeader({
  orgName,
  currentStage,
}: {
  orgName: string;
  currentStage: string;
}) {
  return (
    <div className="rounded-xl border border-stone-200 bg-white px-5 py-4 shadow-sm">
      <p className="text-sm text-stone-600">Check-in for</p>
      <h1 className="mt-0.5 text-xl font-semibold text-stone-900">{orgName}</h1>
      <p className="mt-2 text-sm text-stone-700">
        Framework Stage:{" "}
        <span className="rounded-full bg-leaf-100 px-2 py-0.5 text-leaf-800 text-sm font-medium">
          {currentStage || "—"}
        </span>
      </p>
    </div>
  );
}

function SubmitFeedback({
  state,
}: {
  state:
    | { kind: "idle" }
    | { kind: "submitting" }
    | { kind: "success" }
    | { kind: "error"; message: string };
}) {
  if (state.kind === "idle") {
    return <p className="text-sm text-stone-600">Your changes will be saved as a new check-in record.</p>;
  }
  if (state.kind === "submitting") {
    return (
      <p className="text-sm text-stone-700" role="status">
        Saving your check-in…
      </p>
    );
  }
  if (state.kind === "success") {
    return (
      <p className="text-sm font-medium text-leaf-800" role="status">
        ✓ Check-in saved. Thank you.
      </p>
    );
  }
  return (
    <p className="text-sm font-medium text-red-700" role="alert">
      ✕ {state.message}
    </p>
  );
}

function LoadingState() {
  return (
    <div className="rounded-xl border border-stone-200 bg-white px-6 py-12 text-center text-stone-600 shadow-sm">
      <div className="mx-auto mb-3 h-6 w-6 animate-spin rounded-full border-2 border-leaf-200 border-t-leaf-700" />
      <p>Loading your check-in form…</p>
    </div>
  );
}

function ErrorState({ message }: { message: string }) {
  return (
    <div
      role="alert"
      className="rounded-xl border border-red-200 bg-red-50 px-6 py-6 text-red-900"
    >
      <h2 className="text-lg font-semibold">We couldn't load your check-in form.</h2>
      <p className="mt-2 text-sm leading-relaxed">{message}</p>
      <p className="mt-3 text-sm">
        If this problem persists, please contact your engagement coordinator and ask for a fresh
        link.
      </p>
    </div>
  );
}
