import { useRouter } from "next/navigation";
import { FormEvent, useEffect, useRef, useState } from "react";

import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import { useI18n } from "@/features/i18n/model/useI18n";
import { DEBRIEF_STATUS_OPTIONS } from "@/shared/config/i18n";
import { findRouteById } from "@/shared/config/routes";
import { saveCurrentVoyage, saveToHistory } from "@/shared/lib/store";
import { Voyage, VoyageStatus } from "@/shared/types";

const FINISH_HOLD_MS = 1000;
const HOLD_STAGE_ONE_MS = 100;
const HOLD_STAGE_ONE_PROGRESS = 0.2;

type FlightHudWidgetProps = {
  voyage: Voyage | null;
  isPaused: boolean;
  formattedTime: string;
  isCountdownCompleted: boolean;
  handlePauseToggle: () => void;
  handleFinish: () => Voyage | null;
};

export function FlightHudWidget({
  voyage,
  isPaused,
  formattedTime,
  isCountdownCompleted,
  handlePauseToggle,
  handleFinish,
}: FlightHudWidgetProps) {
  const { t } = useI18n();
  const router = useRouter();
  const [isDebriefOpen, setIsDebriefOpen] = useState(false);
  const [finishedVoyage, setFinishedVoyage] = useState<Voyage | null>(null);
  const [status, setStatus] = useState<VoyageStatus | null>(null);
  const [progress, setProgress] = useState("");
  const [holdProgress, setHoldProgress] = useState(0);
  const holdStartAtRef = useRef<number | null>(null);
  const holdRafRef = useRef<number | null>(null);
  const isHoldCompletedRef = useRef(false);

  const openDebriefModal = () => {
    const endedVoyage = handleFinish();
    if (!endedVoyage) return;

    setFinishedVoyage(endedVoyage);
    setStatus(null);
    setProgress("");
    setIsDebriefOpen(true);
  };

  const handleDebriefSubmit = (event: FormEvent<HTMLFormElement>) => {
    event.preventDefault();
    if (!status || !finishedVoyage) return;

    const finalVoyage: Voyage = {
      ...finishedVoyage,
      status,
      debriefProgress: progress,
    };

    saveToHistory(finalVoyage);
    saveCurrentVoyage(null);
    setIsDebriefOpen(false);
    router.push("/log");
  };

  const stopHoldLoop = () => {
    if (holdRafRef.current !== null) {
      cancelAnimationFrame(holdRafRef.current);
      holdRafRef.current = null;
    }
    holdStartAtRef.current = null;
  };

  const resetHold = () => {
    stopHoldLoop();
    isHoldCompletedRef.current = false;
    setHoldProgress(0);
  };

  const openDebriefByHold = () => {
    isHoldCompletedRef.current = true;
    stopHoldLoop();
    setHoldProgress(1);
    requestAnimationFrame(() => {
      resetHold();
      openDebriefModal();
    });
  };

  const tickHoldProgress = (timestamp: number) => {
    if (holdStartAtRef.current === null) return;

    const elapsed = timestamp - holdStartAtRef.current;
    const nextProgress = (() => {
      if (elapsed <= HOLD_STAGE_ONE_MS) {
        return Math.min(
          HOLD_STAGE_ONE_PROGRESS,
          (elapsed / HOLD_STAGE_ONE_MS) * HOLD_STAGE_ONE_PROGRESS,
        );
      }

      const stageTwoElapsed = elapsed - HOLD_STAGE_ONE_MS;
      const stageTwoDuration = FINISH_HOLD_MS - HOLD_STAGE_ONE_MS;
      const stageTwoProgressRatio = Math.min(1, stageTwoElapsed / stageTwoDuration);

      return Math.min(
        1,
        HOLD_STAGE_ONE_PROGRESS +
          stageTwoProgressRatio * (1 - HOLD_STAGE_ONE_PROGRESS),
      );
    })();
    setHoldProgress(nextProgress);

    if (nextProgress >= 1) {
      openDebriefByHold();
      return;
    }

    holdRafRef.current = requestAnimationFrame(tickHoldProgress);
  };

  const startHoldToFinish = () => {
    if (isDebriefOpen) return;

    resetHold();
    holdStartAtRef.current = performance.now();
    setHoldProgress(0);
    holdRafRef.current = requestAnimationFrame(tickHoldProgress);
  };

  const cancelHoldToFinish = () => {
    if (isHoldCompletedRef.current) return;
    resetHold();
  };

  useEffect(() => {
    return () => {
      if (holdRafRef.current !== null) {
        cancelAnimationFrame(holdRafRef.current);
      }
    };
  }, []);

  if (!voyage) return null;

  const route = findRouteById(voyage.routeId);
  const routeName = route
    ? t(route.nameKey, undefined, voyage.routeName)
    : voyage.routeName;
  const statusOptions = DEBRIEF_STATUS_OPTIONS.map((option) => ({
    value: option.value as VoyageStatus,
    label: t(option.labelKey),
    desc: t(option.descKey),
  }));

  return (
    <>
      <div className="absolute top-8 z-10 text-center">
        <span className="rounded-full border border-indigo-500/30 bg-indigo-950/50 px-4 py-1.5 text-xs font-medium uppercase tracking-widest text-indigo-300 shadow-[0_0_15px_rgba(99,102,241,0.3)] backdrop-blur">
          {routeName} · {isPaused ? t("flight.badge.paused") : t("flight.badge.cruising")}
        </span>
      </div>

      <div
        className={`relative z-10 my-12 font-mono text-7xl font-light tracking-tighter tabular-nums drop-shadow-2xl transition-opacity duration-300 md:text-9xl ${isPaused ? "opacity-50" : "opacity-100"}`}
      >
        {formattedTime}
      </div>

      <div className="relative z-10 mb-24 w-full max-w-2xl px-4">
        <section className="rounded-2xl border border-slate-600/60 bg-slate-950/55 p-4 text-left shadow-[0_16px_40px_rgba(2,6,23,0.35)] backdrop-blur md:p-6">
          <p className="text-[11px] font-semibold uppercase tracking-[0.24em] text-slate-400 md:text-xs">
            {t("flight.missionLabel")}
          </p>
          <p className="mt-2 max-h-32 overflow-y-auto break-words whitespace-pre-wrap pr-1 text-base leading-relaxed text-slate-100 md:text-lg">
            {voyage.missionText}
          </p>
        </section>
      </div>

      <div className="absolute bottom-12 z-10 flex gap-6">
        <button
          onClick={handlePauseToggle}
          className="rounded-full border border-slate-600 bg-slate-900/50 px-8 py-3 text-sm font-bold uppercase tracking-wide text-slate-300 backdrop-blur transition-all hover:border-slate-400 hover:bg-slate-800/80 hover:text-white"
        >
          {isPaused ? t("flight.resume") : t("flight.pause")}
        </button>
        <div className="relative">
          <button
            type="button"
            onPointerDown={startHoldToFinish}
            onPointerUp={cancelHoldToFinish}
            onPointerLeave={cancelHoldToFinish}
            onPointerCancel={cancelHoldToFinish}
            onKeyDown={(event) => {
              if (event.key === "Enter" || event.key === " ") {
                event.preventDefault();
                startHoldToFinish();
              }
            }}
            onKeyUp={(event) => {
              if (event.key === "Enter" || event.key === " ") {
                event.preventDefault();
                cancelHoldToFinish();
              }
            }}
            onBlur={cancelHoldToFinish}
            className="relative overflow-hidden rounded-full border border-slate-200 bg-slate-100 px-8 py-3 text-sm font-bold uppercase tracking-wide text-slate-900 shadow-lg shadow-white/10 transition-all hover:border-indigo-300 hover:text-slate-950"
          >
            <span
              aria-hidden
              className="absolute inset-0 origin-left bg-indigo-400/45"
              style={{ transform: `scaleX(${holdProgress})` }}
            />
            <span className="relative z-10">
              {isCountdownCompleted
                ? t("flight.finish.debrief")
                : t("flight.finish.end")}
            </span>
          </button>
        </div>
      </div>

      <Dialog open={isDebriefOpen} onOpenChange={setIsDebriefOpen}>
        <DialogContent className="max-h-[90vh] overflow-y-auto border-slate-700/80 bg-slate-950 text-slate-100">
          <DialogHeader>
            <DialogTitle className="text-white">
              {t("flight.debrief.title")}
            </DialogTitle>
            <DialogDescription className="text-slate-400">
              {t("flight.debrief.description")}
            </DialogDescription>
          </DialogHeader>

          <form onSubmit={handleDebriefSubmit} className="space-y-6">
            <section>
              <label className="mb-3 block text-sm font-medium text-slate-300">
                {t("debrief.status.label")}
              </label>
              <div className="grid grid-cols-1 gap-3 md:grid-cols-3">
                {statusOptions.map((opt) => (
                  <button
                    key={opt.value}
                    type="button"
                    onClick={() => setStatus(opt.value)}
                    className={`flex min-h-[116px] flex-col justify-between rounded-xl border px-4 py-3.5 text-left transition-all ${
                      status === opt.value
                        ? "border-indigo-500 bg-indigo-900/40 ring-1 ring-indigo-500"
                        : "border-slate-800 bg-slate-900/50 hover:bg-slate-800"
                    }`}
                  >
                    <div className="text-sm leading-snug font-bold text-slate-200 break-keep">
                      {opt.label}
                    </div>
                    <div className="mt-2 text-[11px] leading-relaxed text-slate-500">
                      {opt.desc}
                    </div>
                  </button>
                ))}
              </div>
            </section>

            <section>
              <label className="mb-2 block text-sm font-medium text-slate-300">
                {t("debrief.reflection.label")}
              </label>
              <input
                type="text"
                value={progress}
                onChange={(event) => setProgress(event.target.value)}
                placeholder={t("debrief.reflection.placeholder")}
                className="w-full rounded-lg border border-slate-800 bg-slate-900/30 px-4 py-3 text-slate-200 outline-none transition-all focus:border-indigo-500 focus:ring-1 focus:ring-indigo-500"
              />
            </section>

            <div className="grid grid-cols-2 gap-3 pt-1">
              <button
                type="button"
                onClick={() => setIsDebriefOpen(false)}
                className="rounded-xl border border-slate-700 bg-slate-900/60 px-4 py-3 font-semibold text-slate-300 transition-colors hover:border-slate-500 hover:text-white"
              >
                {t("boarding.cancel")}
              </button>
              <button
                type="submit"
                disabled={!status}
                className="rounded-xl bg-indigo-600 px-4 py-3 font-semibold text-white transition-colors hover:bg-indigo-500 disabled:bg-slate-800 disabled:text-slate-500"
              >
                {t("debrief.save")}
              </button>
            </div>
          </form>
        </DialogContent>
      </Dialog>
    </>
  );
}
