"use client";

import { useState, useCallback, useRef, useEffect } from "react";
import { getCachedProfile } from "@/lib/userId";
import { useToast } from "@/hooks/useToast";
import type { RoomInfo } from "@/hooks/useBlindboxRoom";
import type { WeekendPlanData, UserProfile } from "@/types";
import type { PendingContract } from "@/components/ContractCompletionModal";

type Phase = "pool" | "shaking" | "reveal" | "time_select" | "planning" | "plan_reveal";

const PLAN_STATUS_STEPS = [
  "正在分析你们的想法...",
  "正在搜索地点...",
  "正在规划路线...",
  "快好了...",
];

export function useBlindboxPlan(
  room: RoomInfo | null,
  profile: UserProfile | null,
  phase: Phase,
  setPhase: (p: Phase) => void,
  fireConfetti: () => void,
) {
  const toast = useToast();
  const [planId, setPlanId] = useState<string | null>(null);
  const [planDays, setPlanDays] = useState<WeekendPlanData[]>([]);
  const [planAccepted, setPlanAccepted] = useState(false);
  const [generating, setGenerating] = useState(false);
  const [planStatusMessages, setPlanStatusMessages] = useState<string[]>([]);
  const [showPlanShareCard, setShowPlanShareCard] = useState(false);
  const [activeContract, setActiveContract] = useState<{
    id: string;
    days: WeekendPlanData[];
    endTime: string | null;
  } | null>(null);
  const [pendingContracts, setPendingContracts] = useState<PendingContract[]>([]);
  const planLogRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    if (planLogRef.current) {
      planLogRef.current.scrollTop = planLogRef.current.scrollHeight;
    }
  }, [planStatusMessages]);

  const fetchAcceptedPlan = useCallback(async () => {
    if (!room || !profile) return;
    try {
      const res = await fetch(`/api/blindbox/plan?mode=latest&roomId=${room.id}&userId=${profile.id}`);
      if (!res.ok) return;
      const data = await res.json();
      if (data.plan) {
        setActiveContract({
          id: data.plan.id,
          days: data.plan.days,
          endTime: data.plan.endTime ?? null,
        });
      }
    } catch (e) { console.error("fetchAcceptedPlan failed:", e); }
  }, [room, profile]);

  // Check for expired contracts on load
  useEffect(() => {
    if (!profile) return;
    (async () => {
      try {
        const res = await fetch(`/api/blindbox/plan?mode=pending&userId=${profile.id}`);
        if (!res.ok) return;
        const data = await res.json();
        if (data.pending?.length) setPendingContracts(data.pending);
      } catch (e) { console.error("fetchPendingContracts failed:", e); }
    })();
  }, [profile]);

  // Browser notification timer for active contract
  useEffect(() => {
    if (!activeContract?.endTime) return;
    const end = new Date(activeContract.endTime).getTime();
    const now = Date.now();
    const ms = end - now;
    if (ms <= 0) return;

    if (typeof Notification !== "undefined" && Notification.permission === "default") {
      Notification.requestPermission();
    }

    const timer = setTimeout(() => {
      if (typeof Notification !== "undefined" && Notification.permission === "granted") {
        const n = new Notification("周末契约到期", {
          body: "你的周末契约已结束，完成了吗？",
          icon: "/icon-192x192.png",
        });
        n.onclick = () => { window.focus(); n.close(); };
      }
      const p = getCachedProfile();
      if (p) {
        fetch(`/api/blindbox/plan?mode=pending&userId=${p.id}`)
          .then((r) => r.json())
          .then((d) => { if (d.pending?.length) setPendingContracts(d.pending); })
          .catch((e) => { console.error("refreshPendingContracts failed:", e); });
      }
    }, ms);

    return () => clearTimeout(timer);
  }, [activeContract?.endTime]);

  const handleGeneratePlan = useCallback(async (timeConfig: { date: string; startHour: number; endHour: number }) => {
    if (generating || !profile || !room) return;
    setGenerating(true);
    setPhase("planning");
    setPlanStatusMessages([PLAN_STATUS_STEPS[0]]);
    const payload = { roomId: room.id, userId: profile.id, availableTime: timeConfig };
    const stepRef = { current: 0 };
    const fallbackTimer = setInterval(() => {
      stepRef.current = (stepRef.current + 1) % PLAN_STATUS_STEPS.length;
      setPlanStatusMessages((prev) => [...prev, PLAN_STATUS_STEPS[stepRef.current]]);
    }, 2800);
    try {
      const res = await fetch("/api/blindbox/plan/stream", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(payload),
      });
      if (!res.ok) {
        const data = await res.json().catch(() => ({}));
        throw new Error(data.error || "生成失败");
      }
      const reader = res.body?.getReader();
      const decoder = new TextDecoder();
      if (!reader) throw new Error("无法读取响应");
      let buffer = "";
      while (true) {
        const { done, value } = await reader.read();
        if (done) break;
        buffer += decoder.decode(value, { stream: true });
        const blocks = buffer.split("\n\n");
        buffer = blocks.pop() ?? "";
        for (const block of blocks) {
          let eventType = "";
          let data = "";
          for (const line of block.split("\n")) {
            if (line.startsWith("event:")) eventType = line.slice(6).trim();
            else if (line.startsWith("data:")) data = line.slice(5).trim();
          }
          if (eventType === "status") setPlanStatusMessages((prev) => [...prev, data]);
          else if (eventType === "plan") {
            const parsed = JSON.parse(data);
            setPlanId(parsed.id);
            setPlanDays(parsed.days);
            setPlanAccepted(false);
            setPhase("plan_reveal");
            fireConfetti();
          } else if (eventType === "error") {
            toast.show(data || "生成计划失败");
            setPhase("pool");
          }
        }
      }
    } catch {
      try {
        const res = await fetch("/api/blindbox/plan", {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify(payload),
        });
        if (!res.ok) {
          const data = await res.json().catch(() => ({}));
          throw new Error(data.error || "生成失败");
        }
        const data = await res.json();
        setPlanId(data.id);
        setPlanDays(data.days);
        setPlanAccepted(false);
        setPhase("plan_reveal");
        fireConfetti();
      } catch (fallbackErr) {
        toast.show(fallbackErr instanceof Error ? fallbackErr.message : "生成计划失败");
        setPhase("pool");
      }
    } finally {
      clearInterval(fallbackTimer);
      setGenerating(false);
    }
  }, [generating, profile, room, setPhase, fireConfetti, toast]);

  const handlePlanDaysChange = useCallback(async (newDays: WeekendPlanData[]) => {
    if (!planId || !profile) return;
    const prevDays = planDays;
    setPlanDays(newDays);
    if (planAccepted) {
      setActiveContract((prev) => prev ? { ...prev, days: newDays } : prev);
    }
    try {
      const res = await fetch("/api/blindbox/plan", {
        method: "PATCH",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ planId, userId: profile.id, action: "update_plan", days: newDays }),
      });
      if (!res.ok) throw new Error((await res.json().catch(() => ({}))).error || "保存失败");
    } catch (e) {
      setPlanDays(prevDays);
      if (planAccepted) setActiveContract((prev) => prev ? { ...prev, days: prevDays } : prev);
      toast.show(e instanceof Error ? e.message : "保存失败");
    }
  }, [planId, profile, planDays, planAccepted, toast]);

  const handleRefine = useCallback(async (instruction: string) => {
    if (!profile || !planDays.length) return;
    const prevDays = planDays;
    try {
      const res = await fetch("/api/blindbox/plan/refine", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ userId: profile.id, instruction, days: planDays }),
      });
      if (!res.ok) throw new Error((await res.json().catch(() => ({}))).error || "AI 调整失败");
      const data = await res.json();
      await handlePlanDaysChange(data.days);
    } catch (e) {
      setPlanDays(prevDays);
      toast.show(e instanceof Error ? e.message : "AI 调整失败");
    }
  }, [profile, planDays, handlePlanDaysChange, toast]);

  const handleAcceptPlan = useCallback(async () => {
    setPlanAccepted(true);
    fireConfetti();
    if (planId && profile) {
      try {
        const res = await fetch("/api/blindbox/plan", {
          method: "PATCH",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({ planId, userId: profile.id, action: "accept" }),
        });
        const data = await res.json();
        setActiveContract({ id: planId, days: planDays, endTime: data.endTime ?? null });
      } catch (e) { console.error("acceptPlan failed:", e); }
    }
    toast.show("契约已接受！");
  }, [planId, profile, planDays, fireConfetti, toast]);

  const handleRegenerate = useCallback(() => {
    setPlanId(null);
    setPlanDays([]);
    setPlanAccepted(false);
    setPhase("time_select");
  }, [setPhase]);

  const showActiveContract = useCallback(() => {
    if (!activeContract) return;
    setPlanId(activeContract.id);
    setPlanDays(activeContract.days);
    setPlanAccepted(true);
    setPhase("plan_reveal");
  }, [activeContract, setPhase]);

  const clearPendingContracts = useCallback(() => {
    setPendingContracts([]);
    setActiveContract(null);
  }, []);

  return {
    planId,
    planDays,
    setPlanDays,
    planAccepted,
    generating,
    planStatusMessages,
    showPlanShareCard,
    setShowPlanShareCard,
    activeContract,
    pendingContracts,
    planLogRef,
    fetchAcceptedPlan,
    handleGeneratePlan,
    handlePlanDaysChange,
    handleRefine,
    handleAcceptPlan,
    handleRegenerate,
    showActiveContract,
    clearPendingContracts,
  };
}
