"use client";

import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { useRouter } from "next/navigation";
import { toast } from "sonner";
import {
  Play,
  Pause,
  RotateCcw,
  SkipForward,
  CheckCircle2,
} from "lucide-react";
import type { TemplateExercise } from "@/db/schema";
import { useWorkerTimer } from "@/lib/use-worker-timer";
import {
  playBeep,
  notify,
  requestNotificationPermission,
} from "@/lib/timer-effects";
import { formatSeconds } from "@/lib/utils";
import { TimerCircle } from "@/components/timer-circle";
import { TemplateProgressBar } from "@/components/template-progress-bar";
import { ConfirmModal } from "@/components/confirm-modal";
import { Button } from "@/components/ui/button";

type TimerViewProps =
  | {
      mode: "template";
      templateName: string;
      exercises: TemplateExercise[];
    }
  | {
      mode: "single";
      templateName?: undefined;
      exercises?: undefined;
    };

type SingleMode = "countdown" | "stopwatch";

export function TimerView(props: TimerViewProps) {
  const isTemplate = props.mode === "template";
  const router = useRouter();
  const { elapsedMs, running, start, pause, reset } = useWorkerTimer();

  // ----- single mode state -----
  const [singleMode, setSingleMode] = useState<SingleMode>("countdown");
  const [singleName, setSingleName] = useState("");
  const [singleMinutes, setSingleMinutes] = useState(5);
  const [singleCategory, setSingleCategory] = useState("Cardio");

  // ----- template mode state -----
  const [currentIndex, setCurrentIndex] = useState(0);
  const [templateDone, setTemplateDone] = useState(false);
  const [showSaveModal, setShowSaveModal] = useState(false);
  const [saving, setSaving] = useState(false);
  // guards the advance effect from firing twice for one expiry
  const advancingRef = useRef(false);

  const templateExercises = isTemplate ? props.exercises : undefined;
  const exercises = useMemo(
    () => templateExercises ?? [],
    [templateExercises]
  );
  const current = exercises[currentIndex];

  const targetSeconds = isTemplate
    ? (current?.duration ?? 0) * 60
    : singleMode === "countdown"
      ? singleMinutes * 60
      : 0;

  const elapsedSeconds = elapsedMs / 1000;
  const remaining = Math.max(0, targetSeconds - elapsedSeconds);
  const countdownActive = isTemplate || singleMode === "countdown";

  const progress = countdownActive
    ? targetSeconds > 0
      ? elapsedSeconds / targetSeconds
      : 0
    : (elapsedSeconds % 60) / 60; // stopwatch: one lap per minute

  // ---- advance template / finish countdown when time is up ----
  const advance = useCallback(() => {
    if (!isTemplate) return;
    const nextIndex = currentIndex + 1;
    playBeep(nextIndex >= exercises.length ? 3 : 1);

    if (nextIndex >= exercises.length) {
      notify("Workout completed! 🎉", `${props.templateName} selesai. Mantap!`);
      pause();
      reset();
      setTemplateDone(true);
      setShowSaveModal(true);
    } else {
      const next = exercises[nextIndex];
      notify(
        `${exercises[currentIndex].name} selesai!`,
        `Lanjut: ${next.name} (${next.duration} menit)`
      );
      toast.info(`Lanjut ke gerakan ${nextIndex + 1}: ${next.name}`);
      setCurrentIndex(nextIndex);
      reset();
      start(0); // auto-continue into the next exercise
    }
  }, [isTemplate, currentIndex, exercises, props, pause, reset, start]);

  useEffect(() => {
    if (!countdownActive || !running || targetSeconds <= 0) return;
    if (elapsedSeconds >= targetSeconds && !advancingRef.current) {
      advancingRef.current = true;
      if (isTemplate) {
        advance();
      } else {
        playBeep(3);
        notify("Time's up! ⏰", singleName || "Countdown selesai");
        pause();
      }
      // release the guard on the next tick (after state has settled)
      setTimeout(() => {
        advancingRef.current = false;
      }, 300);
    }
  }, [
    elapsedSeconds,
    targetSeconds,
    running,
    countdownActive,
    isTemplate,
    advance,
    pause,
    singleName,
  ]);

  // ---- controls ----
  const handleStartPause = () => {
    if (running) {
      pause();
    } else {
      requestNotificationPermission();
      playBeep(1); // also unlocks the AudioContext within a user gesture
      start(elapsedMs);
    }
  };

  const handleRestart = () => {
    reset();
    setCurrentIndex(0);
    setTemplateDone(false);
    setShowSaveModal(false);
    advancingRef.current = false;
  };

  const handleNext = () => {
    if (!isTemplate || templateDone) return;
    advance();
  };

  // ---- batch save after template completes ----
  const handleBatchSave = async () => {
    if (!isTemplate) return;
    setSaving(true);
    try {
      const res = await fetch("/api/workouts/batch", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ workouts: exercises }),
      });
      if (!res.ok) {
        const data = await res.json().catch(() => ({}));
        throw new Error(data.error || `HTTP ${res.status}`);
      }
      const data = await res.json();
      toast.success(`${data.count} workout tersimpan ke history!`);
      router.push("/");
    } catch (err) {
      toast.error(
        `Gagal menyimpan: ${err instanceof Error ? err.message : "unknown error"}`
      );
      setSaving(false);
    }
  };

  // ---- save single workout once finished (countdown done or stopwatch stopped) ----
  const [savingSingle, setSavingSingle] = useState(false);
  const handleSaveSingle = async () => {
    const minutes =
      singleMode === "countdown"
        ? singleMinutes
        : Math.max(1, Math.round(elapsedSeconds / 60));
    if (!singleName.trim()) {
      toast.error("Isi nama latihan dulu ya");
      return;
    }
    setSavingSingle(true);
    try {
      const res = await fetch("/api/workouts", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          name: singleName.trim(),
          duration: minutes,
          category: singleCategory,
          completed: true,
        }),
      });
      if (!res.ok) throw new Error(`HTTP ${res.status}`);
      toast.success("Workout tersimpan!");
      router.push("/");
    } catch {
      toast.error("Gagal menyimpan workout");
      setSavingSingle(false);
    }
  };

  const mainLabel = countdownActive
    ? formatSeconds(remaining)
    : formatSeconds(elapsedSeconds);

  return (
    <div className="flex flex-col items-center gap-6">
      {/* header */}
      {isTemplate ? (
        <div className="text-center">
          <h1 className="text-2xl font-bold">{props.templateName}</h1>
          {!templateDone && current && (
            <p className="mt-1 text-lg text-muted-foreground">
              Gerakan {currentIndex + 1}/{exercises.length}:{" "}
              <span className="font-semibold text-foreground">
                {current.name}
              </span>
            </p>
          )}
          {templateDone && (
            <p className="mt-1 flex items-center justify-center gap-2 text-lg text-primary">
              <CheckCircle2 className="h-5 w-5" /> Semua gerakan selesai!
            </p>
          )}
        </div>
      ) : (
        <div className="flex w-full max-w-md flex-col gap-3">
          <h1 className="text-center text-2xl font-bold">Workout Timer</h1>
          <div className="flex justify-center gap-2">
            <Button
              size="sm"
              variant={singleMode === "countdown" ? "default" : "outline"}
              onClick={() => {
                setSingleMode("countdown");
                reset();
              }}
            >
              Countdown
            </Button>
            <Button
              size="sm"
              variant={singleMode === "stopwatch" ? "default" : "outline"}
              onClick={() => {
                setSingleMode("stopwatch");
                reset();
              }}
            >
              Stopwatch
            </Button>
          </div>
          <div className="grid grid-cols-2 gap-2">
            <input
              className="col-span-2 h-10 rounded-md border border-input bg-background px-3 text-sm"
              placeholder="Nama latihan (mis. Push up)"
              value={singleName}
              onChange={(e) => setSingleName(e.target.value)}
            />
            {singleMode === "countdown" && (
              <input
                type="number"
                min={1}
                className="h-10 rounded-md border border-input bg-background px-3 text-sm"
                value={singleMinutes}
                onChange={(e) =>
                  setSingleMinutes(Math.max(1, Number(e.target.value)))
                }
                disabled={running}
                aria-label="Durasi (menit)"
              />
            )}
            <select
              className="h-10 rounded-md border border-input bg-background px-3 text-sm"
              value={singleCategory}
              onChange={(e) => setSingleCategory(e.target.value)}
            >
              <option>Cardio</option>
              <option>Strength</option>
              <option>Yoga</option>
              <option>Rest</option>
            </select>
          </div>
        </div>
      )}

      {/* progress bar (template only) */}
      {isTemplate && (
        <TemplateProgressBar
          exercises={exercises}
          currentIndex={currentIndex}
          done={templateDone}
        />
      )}

      {/* circle */}
      <TimerCircle
        progress={templateDone ? 1 : progress}
        label={templateDone ? "🎉" : mainLabel}
        sublabel={
          isTemplate
            ? templateDone
              ? "Workout completed!"
              : current?.category
            : singleMode === "countdown"
              ? "remaining"
              : "elapsed"
        }
      />

      {/* controls */}
      <div className="flex items-center gap-3">
        <Button
          variant="outline"
          size="icon"
          onClick={handleRestart}
          aria-label="Restart"
        >
          <RotateCcw className="h-5 w-5" />
        </Button>
        {!templateDone && (
          <Button
            size="lg"
            className="h-14 w-14 rounded-full p-0"
            onClick={handleStartPause}
            aria-label={running ? "Pause" : "Start"}
          >
            {running ? (
              <Pause className="h-6 w-6" />
            ) : (
              <Play className="h-6 w-6" />
            )}
          </Button>
        )}
        {isTemplate && !templateDone && (
          <Button
            variant="outline"
            size="icon"
            onClick={handleNext}
            aria-label="Next exercise"
          >
            <SkipForward className="h-5 w-5" />
          </Button>
        )}
      </div>

      {/* single mode: save button */}
      {!isTemplate && (
        <Button
          variant="secondary"
          onClick={handleSaveSingle}
          disabled={savingSingle || (elapsedSeconds < 1 && singleMode === "stopwatch")}
        >
          {savingSingle ? "Saving..." : "Save Workout"}
        </Button>
      )}

      {/* template done: reopen save modal if dismissed */}
      {isTemplate && templateDone && !showSaveModal && (
        <Button onClick={() => setShowSaveModal(true)}>Save to History</Button>
      )}

      <ConfirmModal
        open={showSaveModal}
        title="Workout completed! 🎉"
        description="Save to history? Semua gerakan akan tersimpan sekaligus."
        confirmLabel="Save"
        cancelLabel="Later"
        loading={saving}
        onConfirm={handleBatchSave}
        onCancel={() => setShowSaveModal(false)}
      >
        <ul className="space-y-1 text-sm">
          {exercises.map((ex, i) => (
            <li key={i} className="flex justify-between">
              <span>{ex.name}</span>
              <span className="text-muted-foreground">{ex.duration} menit</span>
            </li>
          ))}
        </ul>
      </ConfirmModal>
    </div>
  );
}
