"use client";

import { useEffect, useState } from "react";
import Link from "next/link";
import { useTranslations } from "next-intl";
import { Card, CardContent } from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { buttonVariants } from "@/components/ui/button";
import { cn } from "@/lib/utils";

type NutritionTotals = {
  calories: number;
  proteinG: number;
  carbsG: number;
  fatG: number;
  fiberG: number;
  sodiumMg: number;
};

type NutritionGoals = {
  caloriesKcal: number | null;
  proteinG: number | null;
  carbsG: number | null;
  fatG: number | null;
} | null;

type NutritionCoverage = {
  calories: number;
  protein: number;
  carbs: number;
  fat: number;
};

type DiaryEntry = {
  id: string;
  recipeId: string;
  title: string;
  servings: number;
  cookedAt: string;
  nutritionKnown: boolean;
};

type DiaryResponse = {
  date: string;
  totals: NutritionTotals;
  goals: NutritionGoals;
  coverage: NutritionCoverage;
  entries: DiaryEntry[];
  unknownCount: number;
};

function todayIso(): string {
  return new Date().toISOString().slice(0, 10);
}

export function NutritionDiary() {
  const t = useTranslations("nutritionDiary");
  const [date, setDate] = useState(todayIso());
  // Tagged with the date it was fetched for, and set only from inside the
  // fetch's own then/catch — never synchronously in the effect body — so we
  // don't need a separate "loading" setState call at the top of the effect.
  const [result, setResult] = useState<
    { date: string; ok: true; data: DiaryResponse } | { date: string; ok: false } | null
  >(null);

  useEffect(() => {
    let cancelled = false;
    fetch(`/api/v1/users/me/nutrition-diary?date=${date}`)
      .then((res) => (res.ok ? res.json() : Promise.reject(new Error("request failed"))))
      .then((json: DiaryResponse) => {
        if (!cancelled) setResult({ date, ok: true, data: json });
      })
      .catch(() => {
        if (!cancelled) setResult({ date, ok: false });
      });
    return () => {
      cancelled = true;
    };
  }, [date]);

  const loading = result === null || result.date !== date;
  const error = !loading && result !== null && !result.ok;
  const data = !loading && result !== null && result.ok ? result.data : null;

  const bars = data
    ? [
        {
          label: t("calories"),
          value: data.totals.calories,
          goal: data.goals?.caloriesKcal ?? null,
          unit: "kcal",
          percentage: data.coverage.calories,
          colorClass: "bg-orange-500",
        },
        {
          label: t("protein"),
          value: data.totals.proteinG,
          goal: data.goals?.proteinG ?? null,
          unit: "g",
          percentage: data.coverage.protein,
          colorClass: "bg-blue-500",
        },
        {
          label: t("carbs"),
          value: data.totals.carbsG,
          goal: data.goals?.carbsG ?? null,
          unit: "g",
          percentage: data.coverage.carbs,
          colorClass: "bg-green-500",
        },
        {
          label: t("fat"),
          value: data.totals.fatG,
          goal: data.goals?.fatG ?? null,
          unit: "g",
          percentage: data.coverage.fat,
          colorClass: "bg-yellow-500",
        },
      ]
    : [];

  return (
    <div className="space-y-6">
      <div className="flex items-end gap-3">
        <div className="space-y-1.5">
          <Label htmlFor="diary-date">{t("dateLabel")}</Label>
          <Input
            id="diary-date"
            type="date"
            value={date}
            max={todayIso()}
            onChange={(e) => setDate(e.target.value || todayIso())}
            className="w-auto"
          />
        </div>
        {date !== todayIso() && (
          <button
            type="button"
            onClick={() => setDate(todayIso())}
            className={cn(buttonVariants({ variant: "ghost", size: "sm" }))}
          >
            {t("today")}
          </button>
        )}
      </div>

      {loading && <p className="text-sm text-muted-foreground">{t("loading")}</p>}
      {error && <p className="text-sm text-destructive">{t("loadError")}</p>}

      {!loading && !error && data && (
        <>
          {!data.goals && (
            <Card>
              <CardContent className="flex flex-col gap-2 py-4 sm:flex-row sm:items-center sm:justify-between">
                <p className="text-sm text-muted-foreground">{t("goalNotSet")}</p>
                <Link
                  href="/settings/nutrition"
                  className={cn(buttonVariants({ variant: "outline", size: "sm" }))}
                >
                  {t("setGoalsCta")}
                </Link>
              </CardContent>
            </Card>
          )}

          {data.goals && (
            <Card>
              <CardContent className="space-y-3 py-4">
                {bars.map((bar) =>
                  bar.goal == null ? null : (
                    <div key={bar.label} className="space-y-1">
                      <div className="flex justify-between text-sm">
                        <span className="font-medium">{bar.label}</span>
                        <span className="text-muted-foreground">
                          {bar.value} / {bar.goal} {bar.unit}
                        </span>
                      </div>
                      <div className="h-2 w-full rounded bg-muted overflow-hidden">
                        <div
                          className={`h-full rounded ${bar.colorClass}`}
                          style={{ width: `${Math.min(bar.percentage, 100)}%` }}
                        />
                      </div>
                    </div>
                  )
                )}
                <div className="grid grid-cols-2 gap-3 pt-2 text-sm sm:grid-cols-2">
                  <div className="flex justify-between rounded-md bg-muted px-3 py-2">
                    <span className="text-muted-foreground">{t("fiber")}</span>
                    <span className="font-medium tabular-nums">{data.totals.fiberG}g</span>
                  </div>
                  <div className="flex justify-between rounded-md bg-muted px-3 py-2">
                    <span className="text-muted-foreground">{t("sodium")}</span>
                    <span className="font-medium tabular-nums">{data.totals.sodiumMg}mg</span>
                  </div>
                </div>
              </CardContent>
            </Card>
          )}

          <div className="space-y-2">
            <h3 className="text-sm font-semibold">{t("entriesTitle")}</h3>
            {data.entries.length === 0 ? (
              <p className="text-sm text-muted-foreground">{t("noEntries")}</p>
            ) : (
              <ul className="space-y-1.5">
                {data.entries.map((entry) => (
                  <li
                    key={entry.id}
                    className="flex items-center justify-between rounded-md border px-3 py-2 text-sm"
                  >
                    <Link href={`/recipes/${entry.recipeId}`} className="hover:underline">
                      {entry.title}
                    </Link>
                    <span className="flex items-center gap-2 text-muted-foreground">
                      <span>{t("servingsLabel", { count: entry.servings })}</span>
                      {!entry.nutritionKnown && (
                        <span className="rounded bg-muted px-1.5 py-0.5 text-xs">
                          {t("nutritionUnknownBadge")}
                        </span>
                      )}
                    </span>
                  </li>
                ))}
              </ul>
            )}
            {data.unknownCount > 0 && (
              <p className="text-xs text-muted-foreground">{t("unknownNote", { count: data.unknownCount })}</p>
            )}
          </div>
        </>
      )}
    </div>
  );
}
