import { create } from "zustand";
import { invoke } from "@tauri-apps/api/core";
import { Profile, GuideListItem, GuideData, SyncResult, CombatIndicator, Section } from "./types";

interface AppState {
  profiles: Profile[];
  activeProfileId: string | null;
  guides: GuideListItem[];
  activeGuideGid: string | null;
  activeGuideData: GuideData | null;
  completedQuests: Set<string>;
  syncing: boolean;
  syncProgress: { current: number; total: number; label: string } | null;
  view: "home" | "guide";
  sidebarCollapsed: boolean;
  resourcesPanelCollapsed: boolean;
  resourceInventory: Record<string, number>;
  questPreviews: Record<string, CombatIndicator[]>;
  previewsLoading: boolean;

  setResourcesPanelCollapsed: (v: boolean) => void;
  loadResourceInventory: () => Promise<void>;
  setResourceQuantity: (name: string, qty: number) => Promise<void>;
  loadProfiles: () => Promise<void>;
  setActiveProfile: (id: string) => Promise<void>;
  createProfile: (name: string) => Promise<void>;
  deleteProfile: (id: string) => Promise<void>;

  loadGuides: () => Promise<void>;
  openGuide: (gid: string) => Promise<void>;
  setSidebarCollapsed: (collapsed: boolean) => void;
  closeGuide: () => void;
  loadQuestPreviews: (gid: string) => Promise<void>;

  toggleQuest: (questName: string) => Promise<void>;

  syncGuides: () => Promise<SyncResult>;
  syncSingleGuide: (gid: string, name: string) => Promise<void>;
}

export const useStore = create<AppState>((set, get) => ({
  profiles: [],
  activeProfileId: null,
  guides: [],
  activeGuideGid: null,
  activeGuideData: null,
  completedQuests: new Set(),
  syncing: false,
  syncProgress: null,
  view: "home",
  sidebarCollapsed: false,
  resourcesPanelCollapsed: false,
  resourceInventory: {},
  questPreviews: {},
  previewsLoading: false,

  setResourcesPanelCollapsed: (v) => set({ resourcesPanelCollapsed: v }),

  loadResourceInventory: async () => {
    const { activeProfileId } = get();
    if (!activeProfileId) return;
    const rows = await invoke<[string, number][]>("get_resource_inventory", { profileId: activeProfileId });
    const inventory: Record<string, number> = {};
    for (const [name, qty] of rows) inventory[name] = qty;
    set({ resourceInventory: inventory });
  },

  setResourceQuantity: async (name, qty) => {
    const { activeProfileId } = get();
    if (!activeProfileId) return;
    set(state => ({ resourceInventory: { ...state.resourceInventory, [name]: qty } }));
    await invoke("set_resource_quantity", { profileId: activeProfileId, resourceName: name, quantity: qty });
  },

  loadProfiles: async () => {
    const profiles = await invoke<Profile[]>("get_profiles");
    const saved = await invoke<string | null>("get_setting", { key: "active_profile" });
    const activeId = saved && profiles.find(p => p.id === saved) ? saved : profiles[0]?.id ?? null;
    set({ profiles, activeProfileId: activeId });
    if (activeId) {
      const completed = await invoke<string[]>("get_completed_quests", { profileId: activeId });
      set({ completedQuests: new Set(completed) });
      await get().loadResourceInventory();
    }
  },

  setActiveProfile: async (id) => {
    await invoke("set_setting", { key: "active_profile", value: id });
    const completed = await invoke<string[]>("get_completed_quests", { profileId: id });
    set({ activeProfileId: id, completedQuests: new Set(completed) });
    await Promise.all([get().loadGuides(), get().loadResourceInventory()]);
  },

  createProfile: async (name) => {
    const profile = await invoke<Profile>("create_profile", { name });
    set(state => ({ profiles: [...state.profiles, profile] }));
    await get().setActiveProfile(profile.id);
  },

  deleteProfile: async (id) => {
    await invoke("delete_profile", { profileId: id });
    const { profiles, activeProfileId } = get();
    const remaining = profiles.filter(p => p.id !== id);
    const newActive = activeProfileId === id ? remaining[0]?.id ?? null : activeProfileId;
    set({ profiles: remaining, activeProfileId: newActive });
    if (newActive) await get().setActiveProfile(newActive);
  },

  loadGuides: async () => {
    const { activeProfileId } = get();
    if (!activeProfileId) return;
    const guides = await invoke<GuideListItem[]>("get_guides_list", { profileId: activeProfileId });
    set({ guides });
  },

  openGuide: async (gid) => {
    const data = await invoke<GuideData>("get_guide", { gid });
    await invoke("set_setting", { key: "active_guide", value: gid });
    set({ activeGuideGid: gid, activeGuideData: data, view: "guide" });
    await get().loadQuestPreviews(gid);
  },

  setSidebarCollapsed: (collapsed) => set({ sidebarCollapsed: collapsed }),

  closeGuide: () => {
    invoke("set_setting", { key: "active_guide", value: "" });
    set({ activeGuideGid: null, activeGuideData: null, view: "home", questPreviews: {}, previewsLoading: false });
  },

  loadQuestPreviews: async (gid) => {
    const { activeGuideData } = get();
    if (!activeGuideData) return;

    const urls = collectQuestUrls(activeGuideData.sections);
    if (urls.length === 0) return;

    // Hydratation immédiate depuis le cache DB
    const cached = await invoke<Record<string, CombatIndicator[]>>("get_cached_previews", { questUrls: urls });
    set({ questPreviews: cached });

    // Fetch réseau en tâche de fond (fire & forget)
    set({ previewsLoading: true });
    invoke<Record<string, CombatIndicator[]>>("fetch_guide_previews", { gid })
      .then(result => set({ questPreviews: result, previewsLoading: false }))
      .catch(() => set({ previewsLoading: false }));
  },

  toggleQuest: async (questName) => {
    const { activeProfileId, completedQuests } = get();
    if (!activeProfileId) return;
    const isNowCompleted = await invoke<boolean>("toggle_quest", {
      profileId: activeProfileId,
      questName,
    });
    const next = new Set(completedQuests);
    if (isNowCompleted) next.add(questName);
    else next.delete(questName);
    set({ completedQuests: next });

    // Refresh guide list progress counts
    await get().loadGuides();
  },

  syncGuides: async () => {
    const tabs = await invoke<{ gid: string; name: string }[]>("get_tabs_list");
    const total = tabs.length;
    const errors: string[] = [];
    let synced = 0;

    set({ syncing: true, syncProgress: { current: 0, total, label: "Démarrage…" } });

    for (const tab of tabs) {
      set({ syncProgress: { current: synced, total, label: tab.name } });
      try {
        await invoke("sync_single_guide", { gid: tab.gid, name: tab.name });
        synced++;
      } catch (e) {
        errors.push(`${tab.name}: ${e}`);
      }
    }

    set({ syncing: false, syncProgress: null });
    await get().loadGuides();
    return { synced, errors };
  },

  syncSingleGuide: async (gid, name) => {
    await invoke("sync_single_guide", { gid, name });
  },
}));

export function collectQuestUrls(sections: Section[]): string[] {
  const urls: string[] = [];
  for (const section of sections) {
    for (const item of section.items) {
      if (item.type === "Quest" && item.url) urls.push(item.url);
      else if (item.type === "Group") {
        for (const q of item.quests) {
          if (q.url) urls.push(q.url);
        }
      }
    }
  }
  return urls;
}
