import { useEffect, useMemo } from "react";
import { useNavigate } from "@tanstack/react-router";
import { useQuery, useQueryClient } from "@tanstack/react-query";
import { useAuth } from "@/hooks/useAuth";
import { useSettings } from "@/hooks/useSettings";
import { useHotels } from "@/hooks/useHotels";
import { supabase } from "@/integrations/supabase/client";
import { authHeaders } from "@/lib/authHeaders";
import { getDismissedTitles } from "@/lib/dismissedActions";
import {
  generateBriefingCore,
  generateBriefingCompetitors,
  generateBriefingIndustry,
  type Briefing,
  type BriefingCore,
  type BriefingCompetitors,
  type BriefingIndustry,
} from "@/lib/briefing.functions";
import type { Hotel } from "@/lib/hotel";

const KEY = (section: string, hotelId: string, lang: string, profile: string) =>
  ["briefing", section, hotelId, lang, profile] as const;

function buildArgs(hotel: Hotel, lang: "en" | "zh", profileName?: string | null) {
  return {
    hotelierName: profileName?.trim() || hotel.hotelier_name || "Hotelier",
    hotelName: hotel.hotel_name,
    location: hotel.location,
    address: hotel.address || null,
    rooms: hotel.rooms,
    segment: hotel.segment,
    brand: hotel.brand,
    adrWeekday: hotel.adr_weekday,
    adrWeekend: hotel.adr_weekend,
    occupancyPct: hotel.occupancy_pct,
    currency: hotel.currency || "MYR",
    starRating: hotel.star_rating,
    propertyType: hotel.property_type,
    targetGuest: hotel.target_guest,
    amenities: hotel.amenities ?? [],
    roomTypes: hotel.room_types ?? [],
    pms: hotel.pms,
    channelManager: hotel.channel_manager,
    bookingEngine: hotel.booking_engine,
    paymentGateway: hotel.payment_gateway,
    invoicing: hotel.invoicing,
    dynamicPricing: hotel.dynamic_pricing,
    reviewMgmt: hotel.review_mgmt,
    websiteBuilder: hotel.website_builder,
    restaurantPos: hotel.restaurant_pos,
    ezeeProducts: hotel.ezee_products ?? [],
    radiusKm: hotel.radius_km ?? 5,
    anchorLat: hotel.latitude ?? null,
    anchorLng: hotel.longitude ?? null,
    language: lang,
  };
}

/**
 * Loads the user's currently-selected hotel and its briefing.
 * The brief is fetched as 3 INDEPENDENT, PARALLEL queries (core / competitors /
 * industry) so the page shell renders immediately and each section streams in
 * as soon as its AI call returns.
 */
export function useBriefing(options: { skipBriefing?: boolean; competitorRadiusOverride?: number; competitorSearchMode?: "distance" | "time"; competitorTravelTimeMin?: number } = {}) {
  const { user, loading: authLoading } = useAuth();
  const { lang } = useSettings();
  const { hotels, selectedHotel, isAllHotels, isLoading: hotelsLoading } = useHotels();
  const navigate = useNavigate();
  const qc = useQueryClient();

  useEffect(() => {
    if (!authLoading && !user) navigate({ to: "/login" });
  }, [authLoading, user, navigate]);

  useEffect(() => {
    if (!user || hotelsLoading) return;
    if (hotels.length === 0) navigate({ to: "/onboarding" });
  }, [user, hotelsLoading, hotels.length, navigate]);

  const hotel = selectedHotel;

  const profileQuery = useQuery({
    queryKey: ["user_profile_name", user?.id],
    enabled: !!user?.id,
    staleTime: 1000 * 60 * 5,
    queryFn: async () => {
      const { data } = await supabase
        .from("user_preferences")
        .select("display_name")
        .eq("user_id", user!.id)
        .maybeSingle();
      return (data?.display_name as string | null) ?? null;
    },
  });
  const profileName = profileQuery.data ?? null;

  const enabled =
    !!hotel?.onboarded && !options.skipBriefing && !isAllHotels && !profileQuery.isLoading;

  const args = hotel ? buildArgs(hotel, lang, profileName) : null;
  const profileKey = profileName ?? "";

  // Dismissed action titles are passed to the core briefing so the AI never
  // re-suggests something the hotelier already dismissed. Sorted so the
  // query key is stable regardless of insertion order.
  const dismissedTitles = useMemo(() => getDismissedTitles().slice().sort(), []);
  const dismissedKey = dismissedTitles.join("|");
  const coreArgs = args ? { ...args, dismissedActionTitles: dismissedTitles } : null;

  const coreQ = useQuery<BriefingCore>({
    queryKey: hotel ? KEY("core", hotel.id, lang, `${profileKey}|d=${dismissedKey}`) : ["briefing", "core", "none"],
    enabled: enabled && !!coreArgs,
    staleTime: Infinity,
    gcTime: Infinity,
    queryFn: async () => generateBriefingCore({ data: coreArgs!, headers: await authHeaders() }),
  });
  const compRadius = options.competitorRadiusOverride ?? hotel?.radius_km ?? 5;
  const compSearchMode = options.competitorSearchMode ?? "distance";
  const compTravelTime = options.competitorTravelTimeMin ?? 10;
  const compArgs = args
    ? { ...args, radiusKm: compRadius, searchMode: compSearchMode, travelTimeMin: compTravelTime }
    : null;
  const compKeyExtra = `${profileKey}|m=${compSearchMode}|r=${compRadius}|t=${compTravelTime}`;
  const compQ = useQuery<BriefingCompetitors>({
    queryKey: hotel ? KEY("competitors", hotel.id, lang, compKeyExtra) : ["briefing", "competitors", "none"],
    enabled: enabled && !!compArgs,
    staleTime: Infinity,
    gcTime: Infinity,
    queryFn: async () => generateBriefingCompetitors({ data: compArgs!, headers: await authHeaders() }),
  });
  const indQ = useQuery<BriefingIndustry>({
    queryKey: hotel ? KEY("industry", hotel.id, lang, profileKey) : ["briefing", "industry", "none"],
    enabled: enabled && !!args,
    staleTime: Infinity,
    gcTime: Infinity,
    queryFn: async () => generateBriefingIndustry({ data: args!, headers: await authHeaders() }),
  });

  const briefing = useMemo<Briefing | null>(() => {
    if (!coreQ.data || !compQ.data || !indQ.data) return null;
    return {
      ...coreQ.data,
      competitors: compQ.data.competitors,
      industry_analysis: indQ.data.industry_analysis,
    };
  }, [coreQ.data, compQ.data, indQ.data]);

  const refresh = () => {
    if (!hotel) return;
    qc.invalidateQueries({ queryKey: ["briefing", "core", hotel.id] });
    qc.invalidateQueries({ queryKey: ["briefing", "competitors", hotel.id] });
    qc.invalidateQueries({ queryKey: ["briefing", "industry", hotel.id] });
  };

  return {
    user,
    hotel,
    hotels,
    isAllHotels,
    briefing,
    // Section-level data and loading flags so each page can render its shell
    // first and show only the relevant section's skeleton.
    core: coreQ.data ?? null,
    competitorsData: compQ.data ?? null,
    industryData: indQ.data ?? null,
    isCoreLoading: coreQ.isLoading,
    isCompetitorsLoading: compQ.isLoading,
    isIndustryLoading: indQ.isLoading,
    isHotelLoading: authLoading || hotelsLoading,
    // Combined flag — kept for backward-compat. True only while ALL sections are still loading.
    isBriefingLoading: coreQ.isLoading && compQ.isLoading && indQ.isLoading,
    // Combined error kept for backward compat. Prefer the section-specific
    // errors so a single failing section doesn't blank out unrelated pages.
    error: coreQ.error || compQ.error || indQ.error,
    coreError: coreQ.error,
    competitorsError: compQ.error,
    industryError: indQ.error,
    refresh,
  };
}
