import { useLocation, useNavigate, useParams } from "@solidjs/router";
import type { Accessor, Setter } from "solid-js";
import { createEffect, createMemo, createSignal, onMount } from "solid-js";
import type { BentoSelection, StepKind } from "@ben-to/builder/domain";
import { createInitialSelection } from "@ben-to/builder/domain";
import type { RecipesIndex } from "@ben-to/recipes/catalog";
import { loadSelection, saveSelection } from "../../infra/persistence";
import { safeDecodePathSegment } from "./path-utils";
import { BUILDER_STEP_ORDER, PICK_DOUBLE_TAP_MS, PICK_DOUBLE_TAP_PX } from "./constants";
import type { FlavorFilter } from "./builder-flow-types";

export function useBuilderSteps(props: {
  readonly selection: Accessor<BentoSelection>;
  readonly setSelection: Setter<BentoSelection>;
  readonly recipesIndex: Accessor<RecipesIndex | undefined>;
}) {
  const params = useParams<{ baseId?: string; variantId?: string }>();
  const navigate = useNavigate();
  const location = useLocation();
  const [currentStep, setCurrentStep] = createSignal<StepKind>("base");
  const [flavorFilter, setFlavorFilter] = createSignal<FlavorFilter>("all");

  const canContinue = createMemo(() => {
    if (currentStep() === "base") return Boolean(props.selection().baseId);
    if (currentStep() === "variant") return Boolean(props.selection().variantId);
    return false;
  });

  const nextStep = () => {
    const index = BUILDER_STEP_ORDER.indexOf(currentStep());
    const next = BUILDER_STEP_ORDER[index + 1];
    if (next) setCurrentStep(next);
  };

  const advanceAfterBasePickDouble = () => {
    if (currentStep() !== "base") return;
    if (!props.selection().baseId) return;
    setCurrentStep("variant");
  };

  const advanceAfterVariantPickDouble = () => {
    if (currentStep() !== "variant") return;
    if (!props.selection().variantId) return;
    setCurrentStep("recipe");
  };

  let lastPickTouch: { key: string; t: number; x: number; y: number } | null = null;

  const onPickCardTouchEndForDouble =
    (cardKey: string, advance: () => void) => (e: TouchEvent) => {
      if (e.changedTouches.length !== 1) return;
      const touch = e.changedTouches[0];
      const now = Date.now();
      const x = touch.clientX;
      const y = touch.clientY;
      const prev = lastPickTouch;
      if (
        prev &&
        prev.key === cardKey &&
        now - prev.t <= PICK_DOUBLE_TAP_MS &&
        Math.hypot(x - prev.x, y - prev.y) <= PICK_DOUBLE_TAP_PX
      ) {
        lastPickTouch = null;
        advance();
        return;
      }
      lastPickTouch = { key: cardKey, t: now, x, y };
    };

  const progressStepIndex = createMemo(() => BUILDER_STEP_ORDER.indexOf(currentStep()));
  const progressPercent = createMemo(() => ((progressStepIndex() + 1) / BUILDER_STEP_ORDER.length) * 100);

  const canNavigateToStep = (step: StepKind) => {
    if (step === "base") return true;
    if (step === "variant") return Boolean(props.selection().baseId);
    return Boolean(props.selection().baseId && props.selection().variantId);
  };

  const goToBuilderStep = (step: StepKind) => {
    if (!canNavigateToStep(step)) return;
    setCurrentStep(step);
  };

  const goHomeWizard = () => {
    setCurrentStep("base");
    props.setSelection(createInitialSelection());
    setFlavorFilter("all");
  };

  onMount(() => {
    if (location.pathname.startsWith("/r/")) return;
    const stored = loadSelection();
    if (stored) props.setSelection(stored);
  });

  createEffect(() => {
    const rawBase = params.baseId;
    const rawVariant = params.variantId;
    if (!rawBase || !rawVariant) return;

    const index = props.recipesIndex();
    if (!index) return;

    const baseId = safeDecodePathSegment(rawBase);
    const variantId = safeDecodePathSegment(rawVariant);
    if (!baseId || !variantId) {
      navigate("/", { replace: true });
      return;
    }

    const base = index.bases.find((item) => item.id === baseId);
    const variant = index.variants.find((item) => item.id === variantId);
    if (!base || !variant || !variant.baseIds.includes(base.id)) {
      navigate("/", { replace: true });
      return;
    }

    const sel = props.selection();
    if (sel.baseId === baseId && sel.variantId === variantId && currentStep() === "recipe") return;

    setFlavorFilter("all");
    props.setSelection({ baseId, variantId });
    setCurrentStep("recipe");
  });

  createEffect(() => {
    const index = props.recipesIndex();
    if (!index) return;

    const step = currentStep();
    const path = location.pathname;
    const { baseId, variantId } = props.selection();

    if (step === "recipe" && baseId && variantId) {
      const target = `/r/${encodeURIComponent(baseId)}/${encodeURIComponent(variantId)}`;
      if (path !== target) {
        navigate(target, { replace: false });
      }
      return;
    }

    if (step !== "recipe" && path.startsWith("/r/")) {
      navigate("/", { replace: true });
    }
  });

  createEffect(() => {
    saveSelection(props.selection());
  });

  createEffect(() => {
    const index = props.recipesIndex();
    if (!index) return;
    const baseId = props.selection().baseId;
    if (!baseId) return;
    const base = index.bases.find((item) => item.id === baseId);
    if (!base) {
      props.setSelection((prev) => ({ ...prev, baseId: null, variantId: null }));
      return;
    }
    if (flavorFilter() !== "all" && base.flavor !== flavorFilter()) {
      props.setSelection((prev) => ({ ...prev, baseId: null, variantId: null }));
    }
  });

  return {
    params,
    navigate,
    location,
    currentStep,
    setCurrentStep,
    flavorFilter,
    setFlavorFilter,
    canContinue,
    nextStep,
    advanceAfterBasePickDouble,
    advanceAfterVariantPickDouble,
    onPickCardTouchEndForDouble,
    progressStepIndex,
    progressPercent,
    canNavigateToStep,
    goToBuilderStep,
    goHomeWizard
  };
}
