import { router } from "expo-router";
import { useEffect, useRef, useState } from "react";
import { Alert, Platform } from "react-native";

import { useAccounts } from "@/contexts/AccountsContext";
import { useAppLock } from "@/contexts/AppLockContext";
import {
  clearPendingShortcut,
  peekPendingShortcut,
  subscribeShortcutQueue,
} from "@/lib/shortcut-queue";
import {
  DEFAULT_CLOCK_DESCRIPTION,
  resolveClockDescription,
  resolveEffectiveHourlyRate,
} from "@/lib/time-clock";
import { getLastTimeClockClientId } from "@/lib/time-clock-prefs";
import type { ParsedShortcut } from "@/lib/shortcuts";
import { api } from "@/lib/trpc";

/**
 * Executes queued shortcut actions once the user is signed in, unlocked, and data is ready.
 */
export function ShortcutHandler() {
  const { activeAccountId } = useAccounts();
  const { isLocked } = useAppLock();
  const utils = api.useUtils();
  const clientsQuery = api.clients.getAll.useQuery();
  const runningQuery = api.timeEntries.getRunning.useQuery();
  const [pending, setPending] = useState<ParsedShortcut | null>(null);
  const processingRef = useRef(false);

  const clockIn = api.timeEntries.clockIn.useMutation();
  const clockOut = api.timeEntries.clockOut.useMutation();

  useEffect(() => {
    let cancelled = false;

    async function refresh() {
      const next = await peekPendingShortcut();
      if (!cancelled) setPending(next);
    }

    void refresh();
    return subscribeShortcutQueue(() => {
      void refresh();
    });
  }, []);

  useEffect(() => {
    if (!pending || !activeAccountId || isLocked) return;
    if (clientsQuery.isLoading || runningQuery.isLoading) return;
    if (processingRef.current) return;

    processingRef.current = true;

    void (async () => {
      try {
        if (pending.action === "open-timer") {
          await clearPendingShortcut();
          setPending(null);
          router.push("/(app)/timer");
          return;
        }

        if (pending.action === "clock-out") {
          if (!runningQuery.data) {
            await clearPendingShortcut();
            setPending(null);
            router.push("/(app)/timer");
            if (Platform.OS === "ios") {
              Alert.alert("No timer running", "There is nothing to clock out.");
            }
            return;
          }

          await clockOut.mutateAsync({});
          await Promise.all([
            utils.timeEntries.getRunning.invalidate(),
            utils.timeEntries.getAll.invalidate(),
            utils.invoices.getAll.invalidate(),
            utils.dashboard.getStats.invalidate(),
          ]);
          await clearPendingShortcut();
          setPending(null);
          router.push("/(app)/timer");
          return;
        }

        if (pending.action === "clock-in") {
          if (runningQuery.data) {
            await clearPendingShortcut();
            setPending(null);
            router.push("/(app)/timer");
            if (Platform.OS === "ios") {
              Alert.alert("Timer already running", "Stop the current timer before clocking in again.");
            }
            return;
          }

          const clientId =
            pending.clientId || (await getLastTimeClockClientId(activeAccountId)) || "";

          if (!clientId) {
            await clearPendingShortcut();
            setPending(null);
            router.push("/(app)/timer");
            Alert.alert(
              "Choose a client",
              "Open the time clock and pick a client once — shortcuts will use it next time.",
            );
            return;
          }

          const client = (clientsQuery.data ?? []).find((entry) => entry.id === clientId);
          const rate = resolveEffectiveHourlyRate("", client?.defaultHourlyRate);

          await clockIn.mutateAsync({
            clientId,
            description: resolveClockDescription(pending.title || DEFAULT_CLOCK_DESCRIPTION),
            rate: rate ?? undefined,
          });
          await utils.timeEntries.getRunning.invalidate();
          await clearPendingShortcut();
          setPending(null);
          router.push("/(app)/timer");
        }
      } catch (err) {
        await clearPendingShortcut();
        setPending(null);
        Alert.alert(
          pending.action === "clock-out" ? "Clock out failed" : "Clock in failed",
          err instanceof Error ? err.message : "Something went wrong.",
        );
        router.push("/(app)/timer");
      } finally {
        processingRef.current = false;
      }
    })();
  }, [
    activeAccountId,
    clockIn,
    clockOut,
    clientsQuery.data,
    clientsQuery.isLoading,
    isLocked,
    pending,
    runningQuery.data,
    runningQuery.isLoading,
    utils,
  ]);

  return null;
}
