// ─── Fabricator Crafting Helpers ──────────────────────────────────────────────
// Separate file to avoid exceeding the 400-line limit in craftingStore.ts.

import type { EquipmentCraftingProgress } from './types';
import type { ElementState } from './types';
import type { FabricatorRecipe } from './data/fabricator-recipes';
import { FABRICATOR_RECIPES } from './data/fabricator-recipes';
import { useManaStore } from './stores/manaStore';
import { computeDisciplineEffects } from './effects/discipline-effects';

// ─── Lookup ───────────────────────────────────────────────────────────────────

export function getFabricatorRecipe(recipeId: string): FabricatorRecipe | undefined {
  return FABRICATOR_RECIPES.find(r => r.id === recipeId);
}

// ─── Crafting Cost Reduction ──────────────────────────────────────────────────

/**
 * Returns the current crafting cost reduction percentage from discipline effects.
 * Spec: actualCost = baseCost × (1 - craftingCostReduction / 100), capped at 75%.
 */
export function getCraftingCostReduction(): number {
  const disciplineEffects = computeDisciplineEffects();
  const raw = disciplineEffects.bonuses.craftingCostReduction || 0;
  return Math.min(75, raw);
}

/**
 * Apply cost reduction to a material amount, rounding up to ensure
 * the player never pays more than the displayed reduced cost.
 */
export function applyCostReduction(baseAmount: number, costReduction: number): number {
  if (costReduction <= 0) return baseAmount;
  return Math.max(1, Math.ceil(baseAmount * (1 - costReduction / 100)));
}

// ─── Cost Check ───────────────────────────────────────────────────────────────

export interface FabricatorCostCheck {
  canCraft: boolean;
  missingMana: number;
  missingMaterials: Record<string, number>;
}

export function checkFabricatorCosts(
  recipe: FabricatorRecipe,
  materials: Record<string, number>,
  rawMana: number,
  elements: Record<string, ElementState>,
  costReduction?: number,
): FabricatorCostCheck {
  const reduction = costReduction ?? getCraftingCostReduction();
  const missingMaterials: Record<string, number> = {};
  let canCraft = true;

  for (const [matId, rawRequired] of Object.entries(recipe.materials)) {
    const required = applyCostReduction(rawRequired, reduction);
    const available = materials[matId] || 0;
    if (available < required) {
      missingMaterials[matId] = required - available;
      canCraft = false;
    }
  }

  const manaAvailable = recipe.manaType === 'raw'
    ? rawMana
    : (elements[recipe.manaType]?.current ?? 0);
  const missingMana = Math.max(0, recipe.manaCost - manaAvailable);
  if (missingMana > 0) canCraft = false;

  return { canCraft, missingMana, missingMaterials };
}

// ─── Mana Deduction ───────────────────────────────────────────────────────────

export interface ManaDeduction {
  rawMana: number;
  elements: Record<string, ElementState>;
}

export function deductFabricatorMana(
  recipe: FabricatorRecipe,
  rawMana: number,
  elements: Record<string, ElementState>,
): ManaDeduction | null {
  if (recipe.manaType === 'raw') {
    if (rawMana < recipe.manaCost) return null;
    return { rawMana: rawMana - recipe.manaCost, elements };
  }

  const elemState = elements[recipe.manaType];
  if (!elemState || !elemState.unlocked || elemState.current < recipe.manaCost) return null;

  return {
    rawMana,
    elements: {
      ...elements,
      [recipe.manaType]: {
        ...elements[recipe.manaType],
        current: elements[recipe.manaType].current - recipe.manaCost,
      },
    },
  };
}

// ─── Mana Refund (on cancel) ──────────────────────────────────────────────────

export interface ManaRefund {
  rawMana: number;
  elements: Record<string, ElementState>;
}

export function refundFabricatorMana(
  recipe: FabricatorRecipe,
  refundAmount: number,
  rawMana: number,
  elements: Record<string, ElementState>,
): ManaRefund {
  if (recipe.manaType === 'raw') {
    return { rawMana: rawMana + refundAmount, elements };
  }

  return {
    rawMana,
    elements: {
      ...elements,
      [recipe.manaType]: {
        ...elements[recipe.manaType],
        current: Math.min(
          elements[recipe.manaType].max,
          elements[recipe.manaType].current + refundAmount,
        ),
      },
    },
  };
}

// ─── Material Deduction ───────────────────────────────────────────────────────

export function deductMaterials(
  recipe: FabricatorRecipe,
  materials: Record<string, number>,
  costReduction?: number,
): Record<string, number> {
  const reduction = costReduction ?? getCraftingCostReduction();
  const newMaterials = { ...materials };
  for (const [matId, rawAmount] of Object.entries(recipe.materials)) {
    const amount = applyCostReduction(rawAmount, reduction);
    newMaterials[matId] = (newMaterials[matId] || 0) - amount;
    if (newMaterials[matId] <= 0) delete newMaterials[matId];
  }
  return newMaterials;
}

// ─── Progress Init ────────────────────────────────────────────────────────────

export function makeFabricatorProgress(
  recipeId: string,
  equipmentTypeId: string,
  craftTime: number,
  manaCost: number,
): EquipmentCraftingProgress {
  return {
    blueprintId: `fabricator-${recipeId}`,
    equipmentTypeId,
    progress: 0,
    required: craftTime,
    manaSpent: manaCost,
  };
}

// ─── Material Crafting ──────────────────────────────────────────────────────

export interface CraftMaterialResult {
  success: boolean;
  newMaterials: Record<string, number>;
  newRawMana: number;
  newElements: Record<string, ElementState>;
  logMessage: string;
}

export function executeMaterialCraft(
  recipe: FabricatorRecipe,
  materials: Record<string, number>,
): CraftMaterialResult | null {
  if (recipe.recipeType !== 'material' || !recipe.resultMaterial || !recipe.resultAmount) return null;

  const rawMana = useManaStore.getState().rawMana;
  const elements = useManaStore.getState().elements;

  const deducted = deductFabricatorMana(recipe, rawMana, elements);
  if (!deducted) return null;

  const newMaterials = deductMaterials(recipe, materials);
  newMaterials[recipe.resultMaterial] = (newMaterials[recipe.resultMaterial] || 0) + recipe.resultAmount;

  return {
    success: true,
    newMaterials,
    newRawMana: deducted.rawMana,
    newElements: deducted.elements,
    logMessage: `✨ Crafted ${recipe.resultAmount}x ${recipe.name}!`,
  };
}
