import { useMemo, useState } from "react";
import { useQuery } from "@tanstack/react-query";
import { useTranslation } from "react-i18next";
import { fetchShoppingList } from "@/api/meal-plan.api";
import { extractApiError } from "@/api/axiosInstance";
import { ErrorState } from "@/components/ui/ErrorState";
import { Skeleton } from "@/components/ui/Skeleton";
import { endOfWeekIso, startOfWeekIso, todayIso } from "@/utils/date.util";

const STORAGE_KEY = "dm_shopping_checks";

function loadChecks(): Record<string, boolean> {
  try {
    return JSON.parse(localStorage.getItem(STORAGE_KEY) ?? "{}") as Record<string, boolean>;
  } catch {
    return {};
  }
}

function itemKey(name: string, unit?: string | null): string {
  return `${name.toLowerCase()}|${unit ?? ""}`;
}

export function ShoppingListPage() {
  const { t } = useTranslation();
  const [from, setFrom] = useState(() => startOfWeekIso(todayIso()));
  const [to, setTo] = useState(() => endOfWeekIso(todayIso()));
  const [checks, setChecks] = useState<Record<string, boolean>>(loadChecks);
  const [loaded, setLoaded] = useState(false);

  const listQuery = useQuery({
    queryKey: ["shopping-list", from, to],
    queryFn: () => fetchShoppingList(from, to),
    enabled: loaded,
  });

  const items = listQuery.data ?? [];

  const sortedItems = useMemo(
    () => [...items].sort((a, b) => a.name.localeCompare(b.name)),
    [items],
  );

  function toggleCheck(name: string, unit?: string | null) {
    const key = itemKey(name, unit);
    setChecks((prev) => {
      const next = { ...prev, [key]: !prev[key] };
      localStorage.setItem(STORAGE_KEY, JSON.stringify(next));
      return next;
    });
  }

  function clearChecks() {
    setChecks({});
    localStorage.removeItem(STORAGE_KEY);
  }

  return (
    <div className="space-y-6">
      <header>
        <h1 className="text-2xl font-extrabold tracking-tight sm:text-3xl">{t("shoppingList.title")}</h1>
        <p className="mt-1 text-slate-500 dark:text-slate-400">{t("shoppingList.subtitle")}</p>
      </header>

      <div className="card flex flex-wrap items-end gap-4 p-5">
        <label className="block text-sm">
          <span className="font-medium">{t("shoppingList.from")}</span>
          <input type="date" className="input mt-1" value={from} onChange={(e) => setFrom(e.target.value)} />
        </label>
        <label className="block text-sm">
          <span className="font-medium">{t("shoppingList.to")}</span>
          <input type="date" className="input mt-1" value={to} onChange={(e) => setTo(e.target.value)} />
        </label>
        <button type="button" className="btn-primary" onClick={() => setLoaded(true)}>
          {t("shoppingList.load")}
        </button>
        <button type="button" className="btn-secondary" onClick={clearChecks}>
          {t("shoppingList.clearChecks")}
        </button>
      </div>

      <p className="text-sm text-slate-500">{t("shoppingList.checklistHint")}</p>

      {loaded && listQuery.isLoading ? (
        <Skeleton className="h-48" />
      ) : listQuery.isError ? (
        <ErrorState
          message={extractApiError(listQuery.error, t("errors.loadFailed"))}
          onRetry={() => void listQuery.refetch()}
        />
      ) : sortedItems.length === 0 && loaded ? (
        <p className="text-sm text-slate-400">{t("shoppingList.empty")}</p>
      ) : (
        <ul className="space-y-2">
          {sortedItems.map((item) => {
            const key = itemKey(item.name, item.unit);
            const checked = !!checks[key];
            const amount =
              item.totalGrams != null
                ? `${item.totalGrams.toFixed(0)}g`
                : item.totalAmount != null
                  ? `${item.totalAmount.toFixed(1)}${item.unit ? ` ${item.unit}` : "g"}`
                  : "";
            return (
              <li
                key={key}
                className={`card flex items-start gap-3 p-4 ${checked ? "opacity-50" : ""}`}
              >
                <input
                  type="checkbox"
                  className="mt-1 h-4 w-4 rounded border-slate-300"
                  checked={checked}
                  onChange={() => toggleCheck(item.name, item.unit)}
                />
                <div>
                  <p className={`font-medium ${checked ? "line-through" : ""}`}>
                    {item.name} {amount ? `· ${amount}` : ""}
                  </p>
                  {item.breakdown.length > 0 ? (
                    <ul className="mt-1 text-xs text-slate-400">
                      {item.breakdown.map((line) => (
                        <li key={line}>{line}</li>
                      ))}
                    </ul>
                  ) : null}
                </div>
              </li>
            );
          })}
        </ul>
      )}
    </div>
  );
}
