// ─── Equipment Crafting System ──────────────────────────────────────────────
// Equipment crafting functions

import type { EquipmentInstance, EquipmentCraftingProgress } from './types';
import { CRAFTING_RECIPES, canCraftRecipe, type CraftingRecipe } from './data/crafting-recipes';
import { EQUIPMENT_TYPES } from './data/equipment';
import { generateInstanceId } from './crafting-utils';
import { ok, fail, ErrorCode } from './utils/result';
import type { Result } from './utils/result';

// ─── Equipment Crafting Validation ──────────────────────────────────────────

// Check if equipment crafting can start
export function canStartEquipmentCrafting(
  blueprintId: string,
  hasBlueprint: boolean,
  materials: Record<string, number>,
  currentMana: number,
  currentAction: string
): { canCraft: boolean; reason?: string; recipe?: CraftingRecipe; missingMaterials?: Record<string, number>; missingMana?: number } {
  if (currentAction !== 'meditate') {
    return { canCraft: false, reason: 'Must be in meditate state' };
  }

  const recipe = CRAFTING_RECIPES[blueprintId];
  if (!recipe) {
    return { canCraft: false, reason: 'Invalid blueprint' };
  }

  if (!hasBlueprint) {
    return { canCraft: false, reason: 'Blueprint not acquired' };
  }

  const { canCraft, missingMaterials } = canCraftRecipe(recipe, materials, currentMana);

  if (!canCraft) {
    const missingMana = Math.max(0, recipe.manaCost - currentMana);
    return { 
      canCraft: false, 
      reason: missingMana > 0 ? 'Insufficient mana' : 'Missing materials',
      recipe,
      missingMaterials,
      missingMana: missingMana > 0 ? missingMana : undefined,
    };
  }

  return { canCraft: true, recipe };
}

// ─── Equipment Crafting Execution ───────────────────────────────────────────

// Deduct crafting costs and initialize progress
export interface CraftingInitResult {
  recipe: CraftingRecipe;
  newMaterials: Record<string, number>;
  manaCost: number;
  progress: EquipmentCraftingProgress;
}

export function initializeEquipmentCrafting(
  blueprintId: string,
  materials: Record<string, number>,
  currentMana: number
): CraftingInitResult {
  const recipe = CRAFTING_RECIPES[blueprintId];

  // Deduct materials
  const newMaterials = { ...materials };
  for (const [matId, amount] of Object.entries(recipe.materials)) {
    newMaterials[matId] = (newMaterials[matId] || 0) - amount;
    if (newMaterials[matId] <= 0) {
      delete newMaterials[matId];
    }
  }

  // Create progress
  const progress: EquipmentCraftingProgress = {
    blueprintId,
    equipmentTypeId: recipe.equipmentTypeId,
    progress: 0,
    required: recipe.craftTime,
    manaSpent: recipe.manaCost,
  };

  return {
    recipe,
    newMaterials,
    manaCost: recipe.manaCost,
    progress,
  };
}

// ─── Crafting Progress ──────────────────────────────────────────────────────

// Calculate crafting progress after a tick
export interface CraftingTickResult {
  progress: number;
  isComplete: boolean;
}

export function calculateCraftingTick(currentProgress: number, required: number): CraftingTickResult {
  const progress = currentProgress + 0.04; // HOURS_PER_TICK
  return {
    progress,
    isComplete: progress >= required,
  };
}

// ─── Crafting Completion ───────────────────────────────────────────────────

// Create equipment instance from completed crafting
export function completeEquipmentCrafting(
  blueprintId: string,
  recipe: CraftingRecipe
): Result<{
  instanceId: string;
  instance: EquipmentInstance;
  logMessage: string;
}> {
  const equipType = EQUIPMENT_TYPES[recipe.equipmentTypeId];
  if (!equipType) {
    return fail(ErrorCode.INVALID_EQUIPMENT_TYPE, `Invalid equipment type: ${recipe.equipmentTypeId}`);
  }

  const instanceId = `equip_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
  const newInstance: EquipmentInstance = {
    instanceId,
    typeId: recipe.equipmentTypeId,
    name: recipe.name,
    enchantments: [],
    usedCapacity: 0,
    totalCapacity: equipType.baseCapacity,
    rarity: recipe.rarity,
    quality: 100,
    tags: [],
  };

  return ok({
    instanceId,
    instance: newInstance,
    logMessage: `🔨 Crafted ${recipe.name}!`,
  });
}

// ─── Crafting Cancellation ──────────────────────────────────────────────────

// Cancel active crafting and refund partial resources
export interface CraftingCancelResult {
  manaRefund: number;
  logMessage: string;
}

export function cancelEquipmentCrafting(blueprintId: string, manaSpent: number): CraftingCancelResult {
  const recipe = CRAFTING_RECIPES[blueprintId];
  if (!recipe) {
    return {
      manaRefund: 0,
      logMessage: 'Invalid crafting recipe.',
    };
  }

  // Refund 50% of mana
  const manaRefund = Math.floor(manaSpent * 0.5);

  return {
    manaRefund,
    logMessage: `🚫 Equipment crafting cancelled. Refunded ${manaRefund} mana.`,
  };
}

// ─── Recipe Information ─────────────────────────────────────────────────────

export function getRecipe(blueprintId: string): CraftingRecipe | null {
  return CRAFTING_RECIPES[blueprintId] || null;
}

export function getCraftableRecipes(
  blueprints: string[],
  materials: Record<string, number>,
  currentMana: number
): CraftingRecipe[] {
  const craftable: CraftingRecipe[] = [];

  for (const blueprintId of blueprints) {
    const recipe = CRAFTING_RECIPES[blueprintId];
    if (!recipe) continue;

    const { canCraft } = canCraftRecipe(recipe, materials, currentMana);
    if (canCraft) {
      craftable.push(recipe);
    }
  }

  return craftable;
}

// ─── Material Management ────────────────────────────────────────────────────

// Delete materials from inventory
export function deleteMaterials(materialId: string, amount: number, materials: Record<string, number>): {
  newMaterials: Record<string, number>;
  deleted: number;
} {
  const currentAmount = materials[materialId] || 0;
  const deleted = Math.min(amount, currentAmount);
  const remaining = Math.max(0, currentAmount - amount);
  const newMaterials = { ...materials };

  if (remaining <= 0) {
    delete newMaterials[materialId];
  } else {
    newMaterials[materialId] = remaining;
  }

  return {
    newMaterials,
    deleted,
  };
}

// Get total material count
export function getMaterialCount(materials: Record<string, number>, materialId: string): number {
  return materials[materialId] || 0;
}

// Add materials to inventory
export function addMaterials(materials: Record<string, number>, materialId: string, amount: number): Record<string, number> {
  const newMaterials = { ...materials };
  newMaterials[materialId] = (newMaterials[materialId] || 0) + amount;
  return newMaterials;
}
