import { DateTime, formatDateOnly, getWeekStart, parseDateOnly } from "@batch-cooking/date-tools";
import type {
  CookingBackgroundTaskView,
  CookingPhaseView,
  CookingTaskView,
  OptimizedCookingPlanView,
} from "@batch-cooking/shared";
import { useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import { useSearchParams } from "react-router-dom";
import { apiClient } from "../../api/client";
import { WeekNavigator } from "../../features/planning/WeekNavigator";
import { taskHeadline, taskRecipeNames } from "./cooking-session";
import "./cooking-session-page.scss";

/** Load state for the `GET /cooking-session` call — same discriminated-union shape as `ShoppingListPage`'s own state. */
type CookingSessionState =
  | { status: "loading" }
  | { status: "loaded"; plan: OptimizedCookingPlanView }
  | { status: "error" };

/**
 * "Cuisiner cette semaine" — routed at `/cuisiner`, reached from the
 * planning page's "Commencer à cuisiner" button. Shows the household's week
 * of planned recipes reorganized by the backend optimizer
 * (`GET /cooking-session`, see the API's `cooking-optimizer.ts`) into
 * ordered phases: a mise-en-place that pools shared prep, then cooking
 * phases that interleave the recipes with passive cooks shown as running
 * in the background.
 *
 * The week comes from a `?date=` query param (set by the planning button so
 * the two pages stay on the same week); absent/invalid falls back to the
 * current week. Read-only and recomputed on every visit — no progress
 * state to keep in sync, same design stance as `ShoppingListPage`.
 */
export function CookingSessionPage() {
  const { t } = useTranslation();
  const [searchParams] = useSearchParams();
  const [weekStart, setWeekStart] = useState<DateTime>(() => {
    const fromQuery = parseDateOnly(searchParams.get("date") ?? "");
    return getWeekStart(fromQuery ?? DateTime.utc());
  });
  const [state, setState] = useState<CookingSessionState>({ status: "loading" });

  useEffect(() => {
    let cancelled = false;
    setState({ status: "loading" });

    apiClient
      .getCookingPlanForWeek(formatDateOnly(weekStart))
      .then((plan) => {
        if (!cancelled) setState({ status: "loaded", plan });
      })
      .catch(() => {
        if (!cancelled) setState({ status: "error" });
      });

    return () => {
      cancelled = true;
    };
  }, [weekStart]);

  return (
    <div className="cooking-session-page">
      <div className="cooking-session-page__header">
        <h1>{t("cookingSession.title")}</h1>
        <WeekNavigator weekStart={weekStart} onChangeWeek={setWeekStart} />
      </div>
      <p className="cooking-session-page__subtitle">{t("cookingSession.subtitle")}</p>

      {state.status === "loading" && (
        <p className="cooking-session-page__status">{t("cookingSession.loading")}</p>
      )}

      {state.status === "error" && (
        <p className="cooking-session-page__status cooking-session-page__status--error">
          {t("common.loadError")}
        </p>
      )}

      {state.status === "loaded" && <CookingPlan plan={state.plan} />}
    </div>
  );
}

/** The plan body — the recipe legend then every phase, or the empty-week message. */
function CookingPlan({ plan }: { plan: OptimizedCookingPlanView }) {
  const { t } = useTranslation();

  if (plan.phases.length === 0) {
    return <p className="cooking-session-page__status">{t("cookingSession.empty")}</p>;
  }

  return (
    <div className="cooking-session">
      <section className="cooking-session__legend" aria-label={t("cookingSession.recipesLegend")}>
        {plan.recipes.map((recipe) => (
          <span
            key={`${recipe.recipeId}-${recipe.portions}`}
            className="cooking-session__legend-item"
          >
            {recipe.name} · ×{recipe.portions}
          </span>
        ))}
      </section>

      {plan.phases.map((phase) => (
        <PhaseSection key={phase.index} phase={phase} />
      ))}
    </div>
  );
}

/** One phase: its background band (if any) then its task cards. */
function PhaseSection({ phase }: { phase: CookingPhaseView }) {
  const { t } = useTranslation();

  return (
    <section className={`cooking-phase cooking-phase--${phase.kind}`}>
      <h2 className="cooking-phase__title">
        <span className="cooking-phase__index">
          {t("cookingSession.phase.label", { index: phase.index + 1 })}
        </span>
        <span className="cooking-phase__kind">{t(`cookingSession.phase.${phase.kind}`)}</span>
      </h2>

      {phase.background.length > 0 && (
        <div className="cooking-phase__background">
          <span className="cooking-phase__background-title">
            {t("cookingSession.background.title")}
          </span>
          <ul>
            {phase.background.map((task) => (
              <li key={task.id}>
                <BackgroundLine task={task} />
              </li>
            ))}
          </ul>
        </div>
      )}

      <ul className="cooking-phase__tasks">
        {phase.tasks.map((task) => (
          <li key={task.id}>
            <TaskCard task={task} />
          </li>
        ))}
      </ul>
    </section>
  );
}

/** A single actionable task — a merged-prep pool or a plain recipe step. */
function TaskCard({ task }: { task: CookingTaskView }) {
  const { t } = useTranslation();

  return (
    <article className={`cooking-task cooking-task--${task.kind}`}>
      <p className="cooking-task__headline">
        {taskHeadline(task, t)}
        {task.kind === "merged-prep" && (
          <span className="cooking-task__badge">{t("cookingSession.task.sharedBadge")}</span>
        )}
      </p>
      <p className="cooking-task__recipes">
        {t("cookingSession.task.forRecipes", { recipes: taskRecipeNames(task) })}
      </p>
      {task.utensils.length > 0 && (
        <p className="cooking-task__utensils">
          {t("cookingSession.task.utensils")} :{" "}
          {task.utensils.map((utensil) => t(`catalog.utensils.${utensil.key}`)).join(", ")}
        </p>
      )}
    </article>
  );
}

/** One "meanwhile, X is cooking" line inside a phase's background band. */
function BackgroundLine({ task }: { task: CookingBackgroundTaskView }) {
  const { t } = useTranslation();
  const technique = task.technique ? `${t(`catalog.techSteps.${task.technique.key}`)} — ` : "";
  return (
    <span>
      {technique}
      {task.description} <em>({task.recipeName})</em>
    </span>
  );
}
