import { EQUIPMENT_TYPES } from '@/lib/game/data/equipment';
import { ENCHANTMENT_EFFECTS, calculateEffectCapacityCost } from '@/lib/game/data/enchantment-effects';
import type { DesignEffect, EquipmentInstance, EquipmentCategory } from '@/lib/game/types';
import { calculateDesignCapacityCost as calcCapacityCost, calculateDesignTime as calcDesignTime } from '@/lib/game/crafting-design';

/**
 * Get available effects for selected equipment type (only unlocked ones)
 * Requirement (task3 bug #7): Show incompatible enchantments in greyed-out "Unavailable" section
 */
export function getAvailableEffects(
  selectedEquipmentType: string | null,
  unlockedEffects: string[]
) {
  if (!selectedEquipmentType) return [];
  const type = EQUIPMENT_TYPES[selectedEquipmentType];
  if (!type) return [];

  return Object.values(ENCHANTMENT_EFFECTS).filter(
    effect =>
      effect.allowedEquipmentCategories.includes(type.category) &&
      (unlockedEffects.length === 0 || unlockedEffects.includes(effect.id))
  );
}

/**
 * Get incompatible effects (unlocked but not for this equipment type)
 */
export function getIncompatibleEffects(
  selectedEquipmentType: string | null,
  unlockedEffects: string[]
) {
  if (!selectedEquipmentType) return [];
  const type = EQUIPMENT_TYPES[selectedEquipmentType];
  if (!type) return [];

  return Object.values(ENCHANTMENT_EFFECTS).filter(
    effect =>
      !effect.allowedEquipmentCategories.includes(type.category) &&
      unlockedEffects.includes(effect.id)
  );
}

/**
 * Get equipment types that the player actually owns (has instances of)
 * This ensures enchantment compatibility is based on owned items, not just blueprints
 */
export function getOwnedEquipmentTypes(equipmentInstances: Record<string, EquipmentInstance>) {
  // Get all unique equipment type IDs from owned instances
  const ownedEquipmentTypeIds = new Set<string>();

  // Check all equipment instances the player owns
  for (const instance of Object.values(equipmentInstances || {})) {
    ownedEquipmentTypeIds.add(instance.typeId);
  }

  // Filter EQUIPMENT_TYPES to only include types the player owns
  return Object.values(EQUIPMENT_TYPES).filter(type => ownedEquipmentTypeIds.has(type.id));
}

/**
 * Get the reason why an effect is incompatible
 */
export function getIncompatibilityReason(
  effect: { id: string; name: string; description: string; allowedEquipmentCategories: EquipmentCategory[] },
  selectedEquipmentType: string | null
): string {
  if (!selectedEquipmentType) return 'No equipment selected';
  const type = EQUIPMENT_TYPES[selectedEquipmentType];
  if (!type) return 'Unknown equipment type';

  // Check what categories this effect is allowed for
  const allowedCategories = effect.allowedEquipmentCategories;
  const equipmentCategory = type.category;

  if (allowedCategories.includes(equipmentCategory)) {
    return 'Compatible';
  }

  // Provide specific reasons
  if (allowedCategories.includes('weapon' as EquipmentCategory) && equipmentCategory !== 'sword' && equipmentCategory !== 'caster' && equipmentCategory !== 'catalyst') {
    return `Requires a weapon (${allowedCategories.filter(c => ['sword', 'caster', 'catalyst'].includes(c)).join(', ')})`;
  }

  return `Requires ${allowedCategories.join(' or ')} equipment`;
}

/**
 * Calculate total capacity cost for current design
 * Delegates to canonical calculateDesignCapacityCost from crafting-design
 */
export function calculateDesignCapacityCost(
  selectedEffects: DesignEffect[],
  efficiencyBonus: number
): number {
  return calcCapacityCost(selectedEffects, efficiencyBonus);
}

/**
 * Get capacity limit for selected equipment type
 */
export function getEquipmentCapacity(selectedEquipmentType: string | null): number {
  return selectedEquipmentType ? EQUIPMENT_TYPES[selectedEquipmentType]?.baseCapacity || 0 : 0;
}

/**
 * Calculate design time
 * Delegates to canonical calculateDesignTime from crafting-design
 */
export function calculateDesignTime(selectedEffects: DesignEffect[]): number {
  return calcDesignTime(selectedEffects);
}

/**
 * Add effect to design
 */
export function addEffectToDesign(
  effectId: string,
  selectedEffects: DesignEffect[],
  efficiencyBonus: number,
  setSelectedEffects: (effects: DesignEffect[]) => void
) {
  const existing = selectedEffects.find(e => e.effectId === effectId);
  const effectDef = ENCHANTMENT_EFFECTS[effectId];
  if (!effectDef) return;

  if (existing) {
    if (existing.stacks < effectDef.maxStacks) {
      setSelectedEffects(selectedEffects.map(e =>
        e.effectId === effectId
          ? { ...e, stacks: e.stacks + 1 }
          : e
      ));
    }
  } else {
    setSelectedEffects([...selectedEffects, {
      effectId,
      stacks: 1,
      capacityCost: calculateEffectCapacityCost(effectId, 1, efficiencyBonus),
    }]);
  }
}

/**
 * Remove effect from design
 */
export function removeEffectFromDesign(
  effectId: string,
  selectedEffects: DesignEffect[],
  setSelectedEffects: (effects: DesignEffect[]) => void
) {
  const existing = selectedEffects.find(e => e.effectId === effectId);
  if (!existing) return;

  if (existing.stacks > 1) {
    setSelectedEffects(selectedEffects.map(e =>
      e.effectId === effectId
        ? { ...e, stacks: e.stacks - 1 }
        : e
    ));
  } else {
    setSelectedEffects(selectedEffects.filter(e => e.effectId !== effectId));
  }
}
