"use client";

import { useRouter } from "next/navigation";
import { useEffect, useEffectEvent, useMemo, useRef, useState } from "react";
import { MandatoryOnboardingGuard } from "@/components/mandatory-onboarding-guard";
import {
  getDemoOnboardingState,
  updateDemoOnboardingState,
} from "@/lib/demo-session-store";
import {
  createEmptyActionPlanObjective,
  createDefaultActionPlanObjectives,
  isActionPlanComplete,
  parseActionPlanPrompt,
  serializeActionPlanObjectives,
  type ActionPlanObjective,
  type OnboardingState,
} from "@/lib/onboarding-shared";

type SuggestedObjective = Omit<ActionPlanObjective, "id">;

const SUGGESTIONS_READY_MESSAGE =
  "Les 3 premiers objectifs ont ete pre-remplis par l'IA. Vous pouvez les ajuster librement.";
const PLAN_SAVED_MESSAGE =
  "Le plan d'action individuel a ete enregistre dans cette session navigateur.";

const columns: Array<{
  key: keyof Pick<
    ActionPlanObjective,
    "whatToDo" | "howAndWithWhom" | "when" | "successCriteria"
  >;
  label: string;
  placeholder: string;
}> = [
  {
    key: "whatToDo",
    label: "Ce que je dois faire pour y parvenir",
    placeholder: "Action manager concrete a enclencher.",
  },
  {
    key: "howAndWithWhom",
    label: "Comment et avec qui",
    placeholder: "Modalites, rituels, parties prenantes, sponsor...",
  },
  {
    key: "when",
    label: "Quand",
    placeholder: "Echeance, jalons, frequence, cadence.",
  },
  {
    key: "successCriteria",
    label: "Criteres de mesure",
    placeholder: "Indicateurs observables et criteres de reussite.",
  },
];

const vigilanceField = {
  key: "pointOfAttention" as const,
  label: "Point de vigilance",
  placeholder: "Risque principal, angle sensible, point a surveiller.",
};

const objectiveField = {
  key: "objectiveLabel" as const,
  label: "Objectif",
  placeholder: "Formulez l'objectif de cette ligne de plan d'action individuel.",
};

function fetchOnboardingState() {
  return getDemoOnboardingState();
}

function saveActionPlan(actionPlanPrompt: string) {
  return updateDemoOnboardingState({
    actionPlanPrompt,
    completeActionPlan: true,
  });
}

function saveActionPlanDraft(actionPlanPrompt: string) {
  return updateDemoOnboardingState({
    actionPlanPrompt,
  });
}

function isSuggestedObjective(value: unknown): value is SuggestedObjective {
  if (!value || typeof value !== "object") {
    return false;
  }

  return (
    typeof Reflect.get(value, "objectiveLabel") === "string" &&
    typeof Reflect.get(value, "whatToDo") === "string" &&
    typeof Reflect.get(value, "howAndWithWhom") === "string" &&
    typeof Reflect.get(value, "when") === "string" &&
    typeof Reflect.get(value, "successCriteria") === "string" &&
    typeof Reflect.get(value, "pointOfAttention") === "string"
  );
}

function isSuggestionsPayload(
  value: unknown,
): value is { objectives: SuggestedObjective[] } {
  if (!value || typeof value !== "object") {
    return false;
  }

  const objectives = Reflect.get(value, "objectives");

  return (
    Array.isArray(objectives) &&
    objectives.length === 3 &&
    objectives.every((objective) => isSuggestedObjective(objective))
  );
}

function applySuggestionsToObjectives(
  currentObjectives: ActionPlanObjective[],
  suggestions: SuggestedObjective[],
) {
  const nextObjectives =
    currentObjectives.length >= 3
      ? [...currentObjectives]
      : createDefaultActionPlanObjectives();

  suggestions.forEach((suggestion, index) => {
    const existing = nextObjectives[index] ?? createEmptyActionPlanObjective();

    nextObjectives[index] = {
      ...existing,
      ...suggestion,
    };
  });

  return nextObjectives;
}

export function ActionPlanShell() {
  const router = useRouter();
  const autoGenerationStartedRef = useRef(false);
  const [objectives, setObjectives] = useState<ActionPlanObjective[]>(
    createDefaultActionPlanObjectives(),
  );
  const [onboardingState, setOnboardingState] = useState<OnboardingState | null>(
    null,
  );
  const [loading, setLoading] = useState(true);
  const [saving, setSaving] = useState(false);
  const [generatingSuggestions, setGeneratingSuggestions] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [success, setSuccess] = useState<string | null>(null);

  useEffect(() => {
    let active = true;

    function load() {
      try {
        const nextState = fetchOnboardingState();

        if (!active) {
          return;
        }

        setOnboardingState(nextState);
        setObjectives(parseActionPlanPrompt(nextState.actionPlanPrompt));
      } catch (caughtError) {
        if (!active) {
          return;
        }

        setError(
          caughtError instanceof Error
            ? caughtError.message
            : "Impossible de charger le plan d'action individuel.",
        );
      } finally {
        if (active) {
          setLoading(false);
        }
      }
    }

    load();

    return () => {
      active = false;
    };
  }, []);

  async function generateSuggestions(force = false) {
    if (
      generatingSuggestions ||
      !onboardingState?.autodiagnosticResult ||
      !onboardingState.answers.managerialLevel
    ) {
      return;
    }

    if (!force && onboardingState.actionPlanPrompt.trim().length > 0) {
      return;
    }

    setGeneratingSuggestions(true);
    setError(null);
    setSuccess(null);

    try {
      const response = await fetch("/api/onboarding/action-plan-suggestions", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify({
          answers: onboardingState.answers,
          autodiagnosticResult: onboardingState.autodiagnosticResult,
        }),
      });

      const payload = (await response.json()) as unknown;

      if (!response.ok || !isSuggestionsPayload(payload)) {
        const routeError =
          payload &&
          typeof payload === "object" &&
          typeof Reflect.get(payload, "error") === "string"
            ? String(Reflect.get(payload, "error"))
            : "Les suggestions IA n'ont pas pu etre generees.";

        throw new Error(routeError);
      }

      const nextObjectives = applySuggestionsToObjectives(
        objectives,
        payload.objectives,
      );
      const nextPrompt = serializeActionPlanObjectives(nextObjectives);
      const nextState = saveActionPlanDraft(nextPrompt);

      setObjectives(nextObjectives);
      setOnboardingState(nextState);
      setSuccess(SUGGESTIONS_READY_MESSAGE);
    } catch (caughtError) {
      setError(
        caughtError instanceof Error
          ? caughtError.message
          : "Les suggestions IA n'ont pas pu etre generees.",
      );
    } finally {
      setGeneratingSuggestions(false);
    }
  }

  const runAutoGeneration = useEffectEvent(() => {
    void generateSuggestions();
  });

  useEffect(() => {
    if (
      loading ||
      autoGenerationStartedRef.current ||
      !onboardingState?.autodiagnosticResult ||
      onboardingState.actionPlanPrompt.trim().length > 0
    ) {
      return;
    }

    autoGenerationStartedRef.current = true;
    runAutoGeneration();
  }, [loading, onboardingState]);

  const serializedPlan = useMemo(
    () => serializeActionPlanObjectives(objectives),
    [objectives],
  );
  const planIsComplete = useMemo(
    () => isActionPlanComplete(objectives),
    [objectives],
  );
  const canRemoveObjective = objectives.length > 3;
  const isInitialGenerationBlocking =
    generatingSuggestions &&
    (onboardingState?.actionPlanPrompt.trim().length ?? 0) === 0;

  function updateObjective(
    objectiveId: string,
    key:
      | typeof objectiveField.key
      | (typeof columns)[number]["key"]
      | typeof vigilanceField.key,
    value: string,
  ) {
    setObjectives((currentObjectives) =>
      currentObjectives.map((objective) =>
        objective.id === objectiveId
          ? {
              ...objective,
              [key]: value,
            }
          : objective,
      ),
    );
  }

  function handleAddObjective() {
    setObjectives((currentObjectives) => [
      ...currentObjectives,
      createEmptyActionPlanObjective(),
    ]);
  }

  function handleRemoveObjective(objectiveId: string) {
    setObjectives((currentObjectives) => {
      if (currentObjectives.length <= 3) {
        return currentObjectives;
      }

      return currentObjectives.filter(
        (objective) => objective.id !== objectiveId,
      );
    });
  }

  function persistActionPlan(redirectTo?: string) {
    if (saving || !planIsComplete) {
      return;
    }

    setSaving(true);
    setError(null);
    setSuccess(null);

    try {
      const nextState = saveActionPlan(serializedPlan);
      setOnboardingState(nextState);
      setObjectives(parseActionPlanPrompt(nextState.actionPlanPrompt));
      setSuccess(PLAN_SAVED_MESSAGE);

      if (redirectTo) {
        router.push(redirectTo);
      }
    } catch (caughtError) {
      setError(
        caughtError instanceof Error
          ? caughtError.message
          : "Impossible d'enregistrer le plan d'action individuel.",
      );
    } finally {
      setSaving(false);
    }
  }

  if (loading) {
    return (
      <main className="app-shell min-h-screen px-5 py-8 sm:px-8 lg:px-10">
        <div className="relative z-10 mx-auto flex min-h-[80vh] max-w-4xl items-center justify-center">
          <div className="glass-card w-full max-w-2xl rounded-[32px] px-8 py-10 text-center">
            <p className="text-sm font-semibold uppercase tracking-[0.22em] text-[var(--primary)]">
              Plan d&apos;action individuel
            </p>
            <h1 className="mt-4 text-3xl font-extrabold text-[var(--ink)]">
              Chargement...
            </h1>
          </div>
        </div>
      </main>
    );
  }

  return (
    <MandatoryOnboardingGuard scope="onboarding">
      <main className="app-shell min-h-screen px-5 py-8 sm:px-8 lg:px-10">
        <div className="relative z-10 mx-auto max-w-[1120px]">
          <section className="glass-card fade-in-up rounded-[32px] px-6 py-6 lg:px-8 lg:py-8">
            <p className="text-sm font-semibold uppercase tracking-[0.22em] text-[var(--accent-red)]">
              Plan d&apos;action individuel
            </p>
            <h1 className="mt-4 text-4xl font-extrabold tracking-[-0.04em] text-[var(--ink)]">
              Completer votre plan d&apos;action individuel
            </h1>

            {onboardingState?.autodiagnosticResult ? (
              <section className="mt-6 rounded-[28px] border border-[rgba(23,117,186,0.12)] bg-[linear-gradient(160deg,rgba(255,255,255,0.98)_0%,rgba(240,246,252,0.96)_100%)] p-5 sm:p-6">
                <p className="text-xs font-semibold uppercase tracking-[0.18em] text-[var(--primary)]">
                  Contexte autodiagnostique charge
                </p>
                <p className="mt-3 text-sm leading-7 text-[var(--foreground)]">
                  Niveau retenu :{" "}
                  <span className="font-semibold text-[var(--ink)]">
                    {onboardingState.autodiagnosticResult.managerialLevel}
                  </span>
                  {" "}avec un score global de{" "}
                  <span className="font-semibold text-[var(--ink)]">
                    {onboardingState.autodiagnosticResult.globalScore}/100
                  </span>
                  . Les 3 premiers objectifs peuvent etre proposes automatiquement
                  a partir de ce resultat et restent entierement modifiables.
                </p>
                <div className="mt-5 flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
                  <p className="text-sm text-[var(--foreground)]">
                    {generatingSuggestions
                      ? "Generation des suggestions IA en cours..."
                      : "Le brouillon du plan est stocke dans la session du navigateur."}
                  </p>
                  {onboardingState.actionPlanPrompt.trim().length === 0 ? (
                    <button
                      type="button"
                      onClick={() => void generateSuggestions(true)}
                      disabled={generatingSuggestions}
                      className="inline-flex items-center justify-center rounded-full border border-[var(--line)] bg-white px-5 py-3 text-sm font-semibold text-[var(--foreground)] transition-colors hover:border-[var(--primary)] hover:text-[var(--primary)] disabled:cursor-not-allowed disabled:opacity-60"
                    >
                      {generatingSuggestions
                        ? "Generation..."
                        : "Generer des suggestions IA"}
                    </button>
                  ) : null}
                </div>
              </section>
            ) : null}

            {success === SUGGESTIONS_READY_MESSAGE ? (
              <div className="mt-6 rounded-[24px] border border-[rgba(47,138,99,0.16)] bg-[rgba(47,138,99,0.07)] px-4 py-3 text-sm leading-7 text-[var(--success)]">
                {success}
              </div>
            ) : null}

            {isInitialGenerationBlocking ? (
              <div className="mt-6 rounded-[24px] border border-[rgba(23,117,186,0.16)] bg-[rgba(23,117,186,0.07)] px-4 py-3 text-sm leading-7 text-[var(--primary)]">
                Les champs seront debloques des que la generation initiale des suggestions IA sera terminee.
              </div>
            ) : null}

            <div className="mt-8 space-y-5">
              {objectives.map((objective, index) => (
                <section
                  key={objective.id}
                  aria-busy={generatingSuggestions && index < 3}
                  className={`relative rounded-[28px] border border-[var(--line)] bg-[var(--surface-soft)] p-5 transition-opacity sm:p-6 ${
                    generatingSuggestions && index < 3 ? "overflow-hidden" : ""
                  }`}
                >
                  {generatingSuggestions && index < 3 ? (
                    <div className="pointer-events-none absolute inset-0 bg-[linear-gradient(135deg,rgba(23,117,186,0.05)_0%,rgba(216,142,4,0.08)_100%)]" />
                  ) : null}

                  <div className="flex items-center justify-between gap-3">
                    <div>
                      <p className="text-sm font-semibold uppercase tracking-[0.18em] text-[var(--primary)] sm:text-base">
                        Objectif {index + 1}
                      </p>
                    </div>
                    {generatingSuggestions && index < 3 ? (
                      <div className="relative z-10 inline-flex items-center gap-3 rounded-full bg-[rgba(23,117,186,0.12)] px-4 py-2 text-xs font-semibold uppercase tracking-[0.14em] text-[var(--primary)]">
                        <span>Generation IA</span>
                        <span className="flex items-center gap-1.5">
                          <span className="pulse-dot h-2.5 w-2.5 rounded-full bg-current [animation-delay:0ms]" />
                          <span className="pulse-dot h-2.5 w-2.5 rounded-full bg-current [animation-delay:150ms]" />
                          <span className="pulse-dot h-2.5 w-2.5 rounded-full bg-current [animation-delay:300ms]" />
                        </span>
                      </div>
                    ) : canRemoveObjective ? (
                      <button
                        type="button"
                        onClick={() => handleRemoveObjective(objective.id)}
                        disabled={isInitialGenerationBlocking}
                        className="relative z-10 inline-flex items-center justify-center rounded-full border border-[var(--line)] px-4 py-2 text-xs font-semibold text-[var(--foreground)] transition-colors hover:border-[var(--accent-red)] hover:text-[var(--accent-red)]"
                      >
                        Supprimer
                      </button>
                    ) : null}
                  </div>

                  <div className="relative z-10 mt-5 overflow-hidden rounded-[24px] border border-[var(--line)] bg-white xl:grid xl:grid-cols-4">
                    <label className="border-b border-[var(--line)] p-4 xl:col-span-4">
                      <span className="block text-sm font-semibold text-[var(--ink)]">
                        {objectiveField.label}
                      </span>
                      <textarea
                        value={objective[objectiveField.key]}
                        onChange={(event) =>
                          updateObjective(
                            objective.id,
                            objectiveField.key,
                            event.target.value,
                          )
                        }
                        disabled={isInitialGenerationBlocking}
                        rows={3}
                        placeholder={
                          generatingSuggestions && index < 3
                            ? "Generation IA de l'objectif en cours..."
                            : objectiveField.placeholder
                        }
                        className="mt-3 min-h-24 w-full resize-y border-none bg-transparent p-0 text-sm leading-7 text-[var(--ink)] outline-none placeholder:text-[var(--foreground)]/65 disabled:cursor-wait disabled:text-[var(--foreground)]/70"
                      />
                    </label>
                    {columns.map((column) => (
                      <label
                        key={`${objective.id}-${column.key}`}
                        className="border-b border-[var(--line)] p-4 last:border-b-0 xl:border-r xl:border-b-0 xl:last:border-r-0"
                      >
                        <span className="block text-sm font-semibold text-[var(--ink)]">
                          {column.label}
                        </span>
                        <textarea
                          value={objective[column.key]}
                          onChange={(event) =>
                          updateObjective(
                              objective.id,
                              column.key,
                              event.target.value,
                            )
                          }
                          disabled={isInitialGenerationBlocking}
                          rows={7}
                          placeholder={
                            generatingSuggestions && index < 3
                              ? "Suggestion IA en cours de generation..."
                              : column.placeholder
                          }
                          className="mt-3 min-h-40 w-full resize-y border-none bg-transparent p-0 text-sm leading-7 text-[var(--ink)] outline-none placeholder:text-[var(--foreground)]/65 disabled:cursor-wait disabled:text-[var(--foreground)]/70"
                        />
                      </label>
                    ))}
                    <label className="border-t border-[var(--line)] p-4 xl:col-span-4">
                      <span className="block text-sm font-semibold text-[var(--ink)]">
                        {vigilanceField.label}
                      </span>
                      <textarea
                        value={objective[vigilanceField.key]}
                        onChange={(event) =>
                          updateObjective(
                            objective.id,
                            vigilanceField.key,
                            event.target.value,
                          )
                        }
                        disabled={isInitialGenerationBlocking}
                        rows={4}
                        placeholder={
                          generatingSuggestions && index < 3
                            ? "Generation IA des points de vigilance..."
                            : vigilanceField.placeholder
                        }
                        className="mt-3 min-h-28 w-full resize-y border-none bg-transparent p-0 text-sm leading-7 text-[var(--ink)] outline-none placeholder:text-[var(--foreground)]/65 disabled:cursor-wait disabled:text-[var(--foreground)]/70"
                      />
                    </label>
                  </div>
                </section>
              ))}

              <div className="flex justify-center">
                <button
                  type="button"
                  onClick={handleAddObjective}
                  disabled={isInitialGenerationBlocking}
                  className="inline-flex items-center justify-center gap-3 rounded-[24px] border border-dashed border-[var(--primary)] bg-[rgba(23,117,186,0.08)] px-5 py-4 text-sm font-semibold text-[var(--primary)] transition-colors hover:bg-[rgba(23,117,186,0.14)]"
                >
                  <span className="inline-flex h-8 w-8 items-center justify-center rounded-full bg-[var(--primary)] text-lg leading-none text-white">
                    +
                  </span>
                  Ajouter un objectif
                </button>
              </div>
            </div>

            {error ? (
              <div className="mt-6 rounded-[24px] border border-[rgba(159,25,24,0.16)] bg-[rgba(159,25,24,0.06)] px-4 py-3 text-sm leading-7 text-[var(--accent-red)]">
                {error}
              </div>
            ) : null}

            {success && success !== SUGGESTIONS_READY_MESSAGE ? (
              <div className="mt-6 rounded-[24px] border border-[rgba(47,138,99,0.16)] bg-[rgba(47,138,99,0.07)] px-4 py-3 text-sm leading-7 text-[var(--success)]">
                {success}
              </div>
            ) : null}

            <div className="mt-8 flex flex-col gap-3 lg:flex-row lg:items-center lg:justify-between">
              <p className="text-sm text-[var(--foreground)]">
                {planIsComplete
                  ? "Les champs requis du plan d'action individuel sont complets."
                  : "Renseignez tous les champs de chaque objectif pour terminer l'onboarding obligatoire."}
              </p>

              <div className="flex flex-col gap-2 sm:flex-row">
                <button
                  type="button"
                  onClick={() => persistActionPlan("/")}
                  disabled={saving || !planIsComplete}
                  className="inline-flex items-center justify-center rounded-full bg-[var(--primary)] px-5 py-3 text-sm font-semibold text-white transition-colors hover:bg-[var(--primary-strong)] disabled:cursor-not-allowed disabled:opacity-60"
                >
                  {saving ? "Enregistrement..." : "Terminer l'onboarding"}
                </button>
                <button
                  type="button"
                  onClick={() => router.push("/onboarding/autodiagnostique/resultat")}
                  disabled={saving}
                  className="inline-flex items-center justify-center rounded-full border border-[var(--line)] px-5 py-3 text-sm font-semibold text-[var(--foreground)] transition-colors hover:border-[var(--accent-gold)] hover:text-[var(--accent-gold)] disabled:cursor-not-allowed disabled:opacity-60"
                >
                  Retour au resultat
                </button>
              </div>
            </div>
          </section>
        </div>
      </main>
    </MandatoryOnboardingGuard>
  );
}
