// ─── Crafting Store Slice ─────────────────────────────────────────────────────
// Core slice logic for equipment and enchantment system. Extracted logic lives
// in focused modules: crafting-utils, crafting-design, crafting-prep, 
// crafting-apply, crafting-equipment, crafting-loot, crafting-attunements.

import type { GameState, EquipmentInstance, AppliedEnchantment, EnchantmentDesign, DesignEffect, EquipmentCraftingProgress, LootInventory, AttunementState } from './types';
import { EQUIPMENT_TYPES } from './data/equipment';
import type { EquipmentSlot } from './data/equipment';
import { ENCHANTMENT_EFFECTS, calculateEffectCapacityCost } from './data/enchantment-effects';
import { CRAFTING_RECIPES, canCraftRecipe, type CraftingRecipe } from './data/crafting-recipes';
import { SPELLS_DEF } from './constants';
import { calculateEnchantingXP, getAttunementXPForLevel, MAX_ATTUNEMENT_LEVEL } from './data/attunements';
import { computeEffects } from './effects/upgrade-effects';
import { hasSpecial, SPECIAL_EFFECTS } from './effects/special-effects';
import type { ComputedEffects } from './effects/upgrade-effects.types';

// ─── Crafting Modules ───────────────────────────────────────────────────────

import * as CraftingUtils from './crafting-utils';
import * as CraftingDesign from './crafting-design';
import * as CraftingPrep from './crafting-prep';
import * as CraftingApply from './crafting-apply';
import * as CraftingEquipment from './crafting-equipment';
import * as CraftingLoot from './crafting-loot';
import * as CraftingAttunements from './crafting-attunements';
import * as CraftingActions from './crafting-actions';

// ─── Initial Equipment Setup ─────────────────────────────────────────────────

export function createStartingEquipment() {
  const staffId = CraftingUtils.generateInstanceId();
  const staffInstance: EquipmentInstance = {
    instanceId: staffId,
    typeId: 'basicStaff',
    name: 'Basic Staff',
    enchantments: [{ effectId: 'spell_manaBolt', stacks: 1, actualCost: 50 }],
    usedCapacity: 50,
    totalCapacity: 50,
    rarity: 'common',
    quality: 100,
    tags: [],
  };

  const shirtId = CraftingUtils.generateInstanceId();
  const shirtInstance: EquipmentInstance = {
    instanceId: shirtId,
    typeId: 'civilianShirt',
    name: 'Civilian Shirt',
    enchantments: [],
    usedCapacity: 0,
    totalCapacity: 30,
    rarity: 'common',
    quality: 100,
    tags: [],
  };

  const shoesId = CraftingUtils.generateInstanceId();
  const shoesInstance: EquipmentInstance = {
    instanceId: shoesId,
    typeId: 'civilianShoes',
    name: 'Civilian Shoes',
    enchantments: [],
    usedCapacity: 0,
    totalCapacity: 15,
    rarity: 'common',
    quality: 100,
    tags: [],
  };

  return {
    equippedInstances: {
      mainHand: staffId,
      offHand: null,
      head: null,
      body: shirtId,
      hands: null,
      feet: shoesId,
      accessory1: null,
      accessory2: null,
    },
    equipmentInstances: {
      [staffId]: staffInstance,
      [shirtId]: shirtInstance,
      [shoesId]: shoesInstance,
    },
  };
}

// ─── Crafting Actions Interface ─────────────────────────────────────────────

export type CraftingActions = {
  createEquipmentInstance: (typeId: string) => string | null;
  equipItem: (instanceId: string, slot: EquipmentSlot) => boolean;
  unequipItem: (slot: EquipmentSlot) => void;
  deleteEquipmentInstance: (instanceId: string) => void;
  startDesigningEnchantment: (name: string, equipmentTypeId: string, effects: DesignEffect[]) => boolean;
  cancelDesign: () => void;
  saveDesign: (design: EnchantmentDesign) => void;
  deleteDesign: (designId: string) => void;
  startPreparing: (equipmentInstanceId: string) => boolean;
  cancelPreparation: () => void;
  startApplying: (equipmentInstanceId: string, designId: string) => boolean;
  pauseApplication: () => void;
  resumeApplication: () => void;
  cancelApplication: () => void;
  disenchantEquipment: (instanceId: string) => void;
  startCraftingEquipment: (blueprintId: string) => boolean;
  cancelEquipmentCrafting: () => void;
  deleteMaterial: (materialId: string, amount: number) => void;
  getEquipmentSpells: () => string[];
  getEquipmentEffects: () => Record<string, number>;
  getAvailableCapacity: (instanceId: string) => number;
};

// ─── Crafting Store Slice ───────────────────────────────────────────────────

export function createCraftingSlice(
  set: (fn: (state: GameState) => Partial<GameState>) => void,
  get: () => GameState & CraftingActions
): CraftingActions {
  return {
    createEquipmentInstance: (typeId) => CraftingActions.createEquipmentInstance(typeId, set),
    equipItem: (instanceId, slot) => CraftingActions.equipItem(instanceId, slot, get, set),
    unequipItem: (slot) => CraftingActions.unequipItem(slot, set),
    deleteEquipmentInstance: (instanceId) => CraftingActions.deleteEquipmentInstance(instanceId, get, set),
    startDesigningEnchantment: (name, equipmentTypeId, effects) =>
      CraftingActions.startDesigningEnchantment(name, equipmentTypeId, effects, get, set),
    cancelDesign: () => CraftingActions.cancelDesign(get, set),
    saveDesign: (design) => CraftingActions.saveDesign(design, get, set),
    deleteDesign: (designId) => CraftingActions.deleteDesign(designId, set),
    startPreparing: (equipmentInstanceId) => CraftingActions.startPreparing(equipmentInstanceId, get, set),
    cancelPreparation: () => CraftingActions.cancelPreparation(set),
    startApplying: (equipmentInstanceId, designId) =>
      CraftingActions.startApplying(equipmentInstanceId, designId, get, set),
    pauseApplication: () => CraftingActions.pauseApplication(get, set),
    resumeApplication: () => CraftingActions.resumeApplication(get, set),
    cancelApplication: () => CraftingActions.cancelApplication(set),
    disenchantEquipment: (instanceId) => CraftingActions.disenchantEquipment(instanceId, get, set),
    startCraftingEquipment: (blueprintId) => CraftingActions.startCraftingEquipment(blueprintId, get, set),
    cancelEquipmentCrafting: () => CraftingActions.cancelEquipmentCrafting(get, set),
    deleteMaterial: (materialId, amount) => CraftingActions.deleteMaterial(materialId, amount, get, set),
    getEquipmentSpells: () => CraftingActions.getEquipmentSpells(get),
    getEquipmentEffects: () => CraftingActions.getEquipmentEffects(get),
    getAvailableCapacity: (instanceId) => CraftingActions.getAvailableCapacity(instanceId, get),
  };
}

// ─── Tick Processing for Crafting ────────────────────────────────────────────

export function processCraftingTick(
  state: GameState,
  effects: { rawMana: number; log: string[] }
): Partial<GameState> {
  const { rawMana, log } = effects;
  let updates: Partial<GameState> = {};

  const computedEffects = computeEffects(state.skillUpgrades || {}, state.skillTiers || {});

  // Process design progress (slot 1)
  if (state.currentAction === 'design' && state.designProgress) {
    const designResult = CraftingDesign.calculateDesignProgress(
      state.designProgress.progress,
      state.designProgress.required,
      computedEffects,
      false
    );

    if (designResult.isComplete) {
      const completedDesign = CraftingDesign.createCompletedDesignFromProgress(
        {
          designId: state.designProgress.designId,
          name: state.designProgress.name,
          equipmentType: state.designProgress.equipmentType,
          effects: state.designProgress.effects,
          required: state.designProgress.required,
        },
        ((state.skillUpgrades || {})['efficientEnchant'] || []).length * 0.05
      );
      updates = {
        ...updates,
        designProgress: null,
        currentAction: 'meditate' as const,
        enchantmentDesigns: [...state.enchantmentDesigns, completedDesign],
        log: [`✅ Enchantment design "${completedDesign.name}" complete!`, ...log],
      };
    } else {
      updates = {
        ...updates,
        designProgress: { ...state.designProgress, progress: designResult.progress },
      };
    }
  }

  // Process second design progress (slot 2)
  if (state.designProgress2) {
    const designResult2 = CraftingDesign.calculateSecondDesignProgress(
      state.designProgress2.progress,
      state.designProgress2.required,
      computedEffects,
      false
    );
    if (designResult2.isComplete) {
      const completedDesign = CraftingDesign.createCompletedDesignFromProgress(
        {
          designId: state.designProgress2.designId,
          name: state.designProgress2.name,
          equipmentType: state.designProgress2.equipmentType,
          effects: state.designProgress2.effects,
          required: state.designProgress2.required,
        },
        ((state.skillUpgrades || {})['efficientEnchant'] || []).length * 0.05
      );
      const shouldTransitionToMeditate = !state.designProgress;
      updates = {
        ...updates,
        designProgress2: null,
        currentAction: shouldTransitionToMeditate ? 'meditate' as const : state.currentAction,
        enchantmentDesigns: [...state.enchantmentDesigns, completedDesign],
        log: [`✅ Enchantment design "${completedDesign.name}" complete! (2nd slot)`, ...log],
      };
    } else {
      updates = {
        ...updates,
        designProgress2: { ...state.designProgress2, progress: designResult2.progress },
      };
    }
  }

  // Process preparation progress
  if (state.currentAction === 'prepare' && state.preparationProgress) {
    const instance = state.equipmentInstances[state.preparationProgress.equipmentInstanceId];
    const manaPerTick = instance ? CraftingPrep.getPreparationManaCostForTick(instance) : 0;

    if (rawMana >= manaPerTick) {
      const tickResult = CraftingPrep.calculatePreparationTick(
        state.preparationProgress.progress,
        state.preparationProgress.required,
        manaPerTick
      );

      if (tickResult.isComplete) {
        if (instance) {
          const completeResult = CraftingPrep.completePreparation(instance, state.preparationProgress.manaCostPaid);
          updates = {
            ...updates,
            rawMana: rawMana - tickResult.manaConsumed + completeResult.manaRecovered,
            preparationProgress: null,
            currentAction: 'meditate' as const,
            equipmentInstances: {
              ...state.equipmentInstances,
              [instance.instanceId]: completeResult.updatedInstance,
            },
            log: [completeResult.logMessage, ...log],
          };
        } else {
          updates = {
            ...updates,
            preparationProgress: null,
            currentAction: 'meditate' as const,
            rawMana: rawMana - tickResult.manaConsumed,
            log: ['✅ Preparation complete!', ...log],
          };
        }
      } else {
        updates = {
          ...updates,
          rawMana: rawMana - tickResult.manaConsumed,
          preparationProgress: {
            ...state.preparationProgress,
            progress: tickResult.progress,
            manaCostPaid: tickResult.manaCostPaid,
          },
        };
      }
    }
  }

  // Process application progress
  if (state.currentAction === 'enchant' && state.applicationProgress && !state.applicationProgress.paused) {
    const app = state.applicationProgress;
    const manaPerTick = CraftingApply.getApplicationManaCostForTick(app.manaPerHour);

    if (rawMana >= manaPerTick) {
      const tickResult = CraftingApply.calculateApplicationTick(
        app.progress,
        app.required,
        app.manaSpent,
        manaPerTick,
        computedEffects
      );

      if (tickResult.isComplete) {
        const instance = state.equipmentInstances[app.equipmentInstanceId];
        const design = state.enchantmentDesigns.find(d => d.id === app.designId);
        if (instance && design) {
          const applyResult = CraftingApply.applyEnchantments(instance, design, computedEffects);
          const xpGain = CraftingAttunements.gainEnchantingXP(state.attunements, applyResult.xpGained);
          updates = {
            ...updates,
            rawMana: rawMana - tickResult.manaConsumed,
            applicationProgress: null,
            currentAction: 'meditate' as const,
            attunements: {
              ...state.attunements,
              enchanter: xpGain.attunements.enchanter,
            },
            equipmentInstances: {
              ...state.equipmentInstances,
              [instance.instanceId]: applyResult.updatedInstance,
            },
            log: [applyResult.logMessage, ...log],
          };
        }
      } else {
        updates = {
          ...updates,
          rawMana: rawMana - tickResult.manaConsumed,
          applicationProgress: { ...app, progress: tickResult.progress, manaSpent: tickResult.manaSpent },
        };
      }
    }
  }

  // Process equipment crafting progress
  if (state.currentAction === 'craft' && state.equipmentCraftingProgress) {
    const craft = state.equipmentCraftingProgress;
    const tickResult = CraftingEquipment.calculateCraftingTick(craft.progress, craft.required);

    if (tickResult.isComplete) {
      const recipe = CraftingEquipment.getRecipe(craft.blueprintId);
      if (recipe) {
        const craftResult = CraftingEquipment.completeEquipmentCrafting(craft.blueprintId, recipe);
        updates = {
          ...updates,
          equipmentCraftingProgress: null,
          currentAction: 'meditate' as const,
          equipmentInstances: {
            ...state.equipmentInstances,
            [craftResult.instanceId]: craftResult.instance,
          },
          totalCraftsCompleted: (state.totalCraftsCompleted || 0) + 1,
          log: [craftResult.logMessage, ...log],
        };
      } else {
        updates = {
          ...updates,
          equipmentCraftingProgress: null,
          currentAction: 'meditate' as const,
          log: ['⚠️ Crafting failed - invalid recipe!', ...log],
        };
      }
    } else {
      updates = {
        ...updates,
        equipmentCraftingProgress: { ...craft, progress: tickResult.progress },
      };
    }
  }

  return updates;
}

// ─── Export helper to get equipment instance spells ─────────────────────────

export function getSpellsFromEquipment(instances: Record<string, EquipmentInstance>, equippedIds: (string | null)[]): string[] {
  const spells: string[] = [];
  for (const id of equippedIds) {
    if (!id) continue;
    const instance = instances[id];
    if (!instance) continue;
    for (const ench of instance.enchantments) {
      const effectDef = ENCHANTMENT_EFFECTS[ench.effectId];
      if (effectDef?.effect.type === 'spell' && effectDef.effect.spellId) {
        spells.push(effectDef.effect.spellId);
      }
    }
  }
  return [...new Set(spells)];
}
