// ─── Mana Store ───────────────────────────────────────────────────────────────
// Handles raw mana, elements, meditation, and mana regeneration

import { create } from 'zustand';
import { persist } from 'zustand/middleware';
import { ELEMENTS, MANA_PER_ELEMENT, BASE_UNLOCKED_ELEMENTS } from '../constants';
import type { ElementState } from '../types';

export interface ManaState {
  rawMana: number;
  meditateTicks: number;
  totalManaGathered: number;
  elements: Record<string, ElementState>;
  
  // Actions
  setRawMana: (amount: number) => void;
  addRawMana: (amount: number, maxMana: number) => void;
  spendRawMana: (amount: number) => boolean;
  gatherMana: (amount: number, maxMana: number) => void;
  
  // Meditation
  setMeditateTicks: (ticks: number) => void;
  incrementMeditateTicks: () => void;
  resetMeditateTicks: () => void;
  
  // Elements
  convertMana: (element: string, amount: number) => boolean;
  unlockElement: (element: string, cost: number) => boolean;
  addElementMana: (element: string, amount: number, max: number) => void;
  spendElementMana: (element: string, amount: number) => boolean;
  setElementMax: (max: number) => void;
  craftComposite: (target: string, recipe: string[]) => boolean;
  
  // Helper for gameStore coordination
  processConvertAction: (rawMana: number) => { rawMana: number; elements: Record<string, ElementState> } | null;
  
  // Reset
  resetMana: (
    prestigeUpgrades: Record<string, number>,
    skills?: Record<string, number>,
    skillUpgrades?: Record<string, string[]>,
    skillTiers?: Record<string, number>
  ) => void;
}

export const useManaStore = create<ManaState>()(
  persist(
    (set, get) => ({
      rawMana: 10,
      meditateTicks: 0,
      totalManaGathered: 0,
      elements: Object.fromEntries(
        Object.keys(ELEMENTS).map(k => [
          k,
          {
            current: 0,
            max: 10,
            unlocked: BASE_UNLOCKED_ELEMENTS.includes(k),
          }
        ])
      ) as Record<string, ElementState>,
      
      setRawMana: (amount: number) => {
        set({ rawMana: Math.max(0, amount) });
      },
      
      addRawMana: (amount: number, maxMana: number) => {
        set((state) => ({
          rawMana: Math.min(state.rawMana + amount, maxMana),
          totalManaGathered: state.totalManaGathered + amount,
        }));
      },
      
      spendRawMana: (amount: number) => {
        const state = get();
        if (state.rawMana < amount) return false;
        
        set({ rawMana: state.rawMana - amount });
        return true;
      },
      
      gatherMana: (amount: number, maxMana: number) => {
        set((state) => ({
          rawMana: Math.min(state.rawMana + amount, maxMana),
          totalManaGathered: state.totalManaGathered + amount,
        }));
      },
      
      setMeditateTicks: (ticks: number) => {
        set({ meditateTicks: ticks });
      },
      
      incrementMeditateTicks: () => {
        set((state) => ({ meditateTicks: state.meditateTicks + 1 }));
      },
      
      resetMeditateTicks: () => {
        set({ meditateTicks: 0 });
      },
      
      convertMana: (element: string, amount: number) => {
        const state = get();
        const elem = state.elements[element];
        if (!elem?.unlocked) return false;
        
        const cost = MANA_PER_ELEMENT * amount;
        if (state.rawMana < cost) return false;
        if (elem.current >= elem.max) return false;
        
        const canConvert = Math.min(
          amount,
          Math.floor(state.rawMana / MANA_PER_ELEMENT),
          elem.max - elem.current
        );
        
        if (canConvert <= 0) return false;
        
        set({
          rawMana: state.rawMana - canConvert * MANA_PER_ELEMENT,
          elements: {
            ...state.elements,
            [element]: { ...elem, current: elem.current + canConvert },
          },
        });
        
        return true;
      },
      
      unlockElement: (element: string, cost: number) => {
        const state = get();
        if (state.elements[element]?.unlocked) return false;
        if (state.rawMana < cost) return false;
        
        set({
          rawMana: state.rawMana - cost,
          elements: {
            ...state.elements,
            [element]: { ...state.elements[element], unlocked: true },
          },
        });
        
        return true;
      },
      
      addElementMana: (element: string, amount: number, max: number) => {
        set((state) => {
          const elem = state.elements[element];
          if (!elem) return state;
          
          return {
            elements: {
              ...state.elements,
              [element]: {
                ...elem,
                current: Math.min(elem.current + amount, max),
              },
            },
          };
        });
      },
      
      spendElementMana: (element: string, amount: number) => {
        const state = get();
        const elem = state.elements[element];
        if (!elem || elem.current < amount) return false;
        
        set({
          elements: {
            ...state.elements,
            [element]: { ...elem, current: elem.current - amount },
          },
        });
        
        return true;
      },
      
      setElementMax: (max: number) => {
        set((state) => ({
          elements: Object.fromEntries(
            Object.entries(state.elements).map(([k, v]) => [k, { ...v, max }])
          ) as Record<string, ElementState>,
        }));
      },
      
      craftComposite: (target: string, recipe: string[]) => {
        const state = get();
        
        // Count required ingredients
        const costs: Record<string, number> = {};
        recipe.forEach(r => {
          costs[r] = (costs[r] || 0) + 1;
        });
        
        // Check if we have all ingredients
        for (const [r, amt] of Object.entries(costs)) {
          if ((state.elements[r]?.current || 0) < amt) return false;
        }
        
        // Deduct ingredients
        const newElems = { ...state.elements };
        for (const [r, amt] of Object.entries(costs)) {
          newElems[r] = {
            ...newElems[r],
            current: newElems[r].current - amt,
          };
        }
        
        // Add crafted element
        const targetElem = newElems[target];
        newElems[target] = {
          ...(targetElem || { current: 0, max: 10, unlocked: false }),
          current: (targetElem?.current || 0) + 1,
          unlocked: true,
        };
        
        set({ elements: newElems });
        return true;
      },
      
      processConvertAction: (rawMana: number) => {
        const state = get();
        const elements = { ...state.elements };
        
        const unlockedElements = Object.entries(elements)
          .filter(([, e]) => e.unlocked && e.current < e.max);

        if (unlockedElements.length === 0 || rawMana < 100) return null;
        
        unlockedElements.sort((a, b) => (b[1].max - b[1].current) - (a[1].max - a[1].current));
        const [targetId, targetState] = unlockedElements[0];
        const canConvert = Math.min(
          Math.floor(rawMana / 100),
          targetState.max - targetState.current
        );
        
        if (canConvert <= 0) return null;
        
        rawMana -= canConvert * 100;
        const updatedElements = {
          ...elements,
          [targetId]: { ...targetState, current: targetState.current + canConvert }
        };
        
        return { rawMana, elements: updatedElements };
      },
      
      resetMana: (
        prestigeUpgrades: Record<string, number>,
        skills: Record<string, number> = {},
        skillUpgrades: Record<string, string[]> = {},
        skillTiers: Record<string, number> = {}
      ) => {
        const elementMax = 10 + (prestigeUpgrades.elemMax || 0) * 5;
        const startingMana = 10 + (prestigeUpgrades.manaStart || 0) * 10;
        const elements = makeInitialElements(elementMax, prestigeUpgrades);
        
        set({
          rawMana: startingMana,
          meditateTicks: 0,
          totalManaGathered: 0,
          elements,
        });
      },
    }),
    {
      name: 'mana-loop-mana',
      partialize: (state) => ({
        rawMana: state.rawMana,
        totalManaGathered: state.totalManaGathered,
        elements: state.elements,
      }),
    }
  )
);

// Helper function to create initial elements
export function makeInitialElements(
  elementMax: number,
  prestigeUpgrades: Record<string, number> = {}
): Record<string, ElementState> {
  const elemStart = (prestigeUpgrades.elemStart || 0) * 5;
  
  const elements: Record<string, ElementState> = {};
  Object.keys(ELEMENTS).forEach(k => {
    const isUnlocked = BASE_UNLOCKED_ELEMENTS.includes(k);
    elements[k] = {
      current: isUnlocked ? elemStart : 0,
      max: elementMax,
      unlocked: isUnlocked,
    };
  });
  
  return elements;
}
