// ─── Room Enchantments Utilities ───────────────────────────────────────────────
// Coverage computation, effect application, and equipment scanning for the
// Room Enchantments system.

import { SPECIAL_EFFECTS } from '../data/enchantments/special-effects';
import type { EquipmentInstance, EnemyState } from '../types';

/** Base coverage growth rate per tick (0.2 = 100 seconds to fill at 200ms/tick) */
export const BASE_COVERAGE_RATE = 0.2;

/** Set of specialIds that are room enchantment effects */
const ROOM_ENCHANTMENT_SPECIAL_IDS = new Set([
  'room_fire_damage',
  'room_frost_debuff',
  'room_death_damage',
  'room_lightning_damage',
  'room_dark_dodge_debuff',
  'room_earth_armor_debuff',
  'room_transference_buff',
  'room_transference_regen',
]);

/**
 * Room enchantment effect info extracted from equipped footwear.
 */
export interface RoomEnchantmentEffect {
  specialId: string;
  baseMagnitude: number;
}

/**
 * Result of applying room enchantment effects for one tick.
 */
export interface RoomEnchantmentTickResult {
  enemies: EnemyState[];
  rawManaDelta: number;
  playerBuffs: {
    castSpeedMultiplier: number;
    transferenceRegenPerHour: number;
  };
  logMessages: string[];
}

/**
 * Compute coverage per tick from discipline bonus.
 * @param disciplineBonus - roomCoverageRate bonus from the `room-coverage-rate` capped perk
 * @returns coverage amount per tick
 */
export function computeCoveragePerTick(disciplineBonus: number): number {
  return BASE_COVERAGE_RATE + disciplineBonus;
}

/**
 * Check if a specialId is a room enchantment effect.
 */
export function isRoomEnchantmentSpecialId(specialId: string): boolean {
  return ROOM_ENCHANTMENT_SPECIAL_IDS.has(specialId);
}

/**
 * Set of enchantment effect IDs that are room enchantment effects.
 * These are the keys in SPECIAL_EFFECTS / ENCHANTMENT_EFFECTS whose
 * effect.specialId is a room enchantment.
 */
const ROOM_ENCHANTMENT_EFFECT_IDS = new Set([
  'boots_sigil_fire',
  'boots_sigil_frost',
  'boots_sigil_death',
  'boots_sigil_lightning',
  'boots_sigil_dark',
  'boots_sigil_earth',
  'boots_sigil_transference_ground',
  'boots_sigil_transference_path',
]);

/**
 * Check if an enchantment effect ID is a room enchantment effect.
 * Use this in the EffectSelector to tag room enchantments.
 */
export function isRoomEnchantmentEffectId(effectId: string): boolean {
  return ROOM_ENCHANTMENT_EFFECT_IDS.has(effectId);
}

/**
 * Get the base magnitude for a room enchantment specialId.
 * These are the tick-level effect strengths at 100% coverage.
 */
export function getRoomEnchantmentBaseMagnitude(specialId: string): number {
  switch (specialId) {
    case 'room_fire_damage': return 5;       // 5 dmg/tick at 100% coverage
    case 'room_frost_debuff': return 0.10;    // 10% slow at 100% coverage
    case 'room_death_damage': return 3;       // 3 dmg/tick at 100% coverage
    case 'room_lightning_damage': return 3;   // 3 dmg/tick at 100% coverage
    case 'room_dark_dodge_debuff': return 0.10; // 10% dodge reduction at 100% coverage
    case 'room_earth_armor_debuff': return 0.05; // 5% armor reduction at 100% coverage
    case 'room_transference_buff': return 0.05;  // 5% cast speed at 100% coverage
    case 'room_transference_regen': return 0.10; // 10%/hr regen at 100% coverage
    default: return 0;
  }
}

/**
 * Get the display name for a room enchantment specialId.
 */
export function getRoomEnchantmentName(specialId: string): string {
  switch (specialId) {
    case 'room_fire_damage': return 'Blazing Footsteps';
    case 'room_frost_debuff': return 'Frozen Trail';
    case 'room_death_damage': return 'Necrotic Tread';
    case 'room_lightning_damage': return 'Shocking Stride';
    case 'room_dark_dodge_debuff': return 'Shadow Patch';
    case 'room_earth_armor_debuff': return 'Scoured Earth';
    case 'room_transference_buff': return 'Transference Grounds';
    case 'room_transference_regen': return 'Conductive Path';
    default: return specialId;
  }
}

/**
 * Get the element color for a room enchantment specialId.
 */
export function getRoomEnchantmentColor(specialId: string): string {
  switch (specialId) {
    case 'room_fire_damage': return '#EF4444';
    case 'room_frost_debuff': return '#3B82F6';
    case 'room_death_damage': return '#6B21A8';
    case 'room_lightning_damage': return '#F59E0B';
    case 'room_dark_dodge_debuff': return '#374151';
    case 'room_earth_armor_debuff': return '#92400E';
    case 'room_transference_buff': return '#8B5CF6';
    case 'room_transference_regen': return '#A78BFA';
    default: return '#9CA3AF';
  }
}

/**
 * Get list of room enchantment effects from equipped footwear.
 * Scans the equippedInstances for the 'feet' slot, then checks the
 * equipment instance's enchantments for room enchantment specialIds.
 */
export function getEquippedRoomEnchantments(
  equippedInstances: Record<string, string | null>,
  equipmentInstances: Record<string, EquipmentInstance>,
): RoomEnchantmentEffect[] {
  const result: RoomEnchantmentEffect[] = [];
  const feetInstanceId = equippedInstances['feet'];
  if (!feetInstanceId) return result;

  const feetInstance = equipmentInstances[feetInstanceId];
  if (!feetInstance || !feetInstance.enchantments) return result;

  for (const enchant of feetInstance.enchantments) {
    const effectDef = SPECIAL_EFFECTS[enchant.effectId];
    if (!effectDef) continue;
    const specialId = effectDef.effect.specialId;
    if (!specialId || !isRoomEnchantmentSpecialId(specialId)) continue;

    const baseMagnitude = getRoomEnchantmentBaseMagnitude(specialId);
    result.push({ specialId, baseMagnitude });
  }

  return result;
}

/**
 * Apply all room enchantment effects for one tick.
 * Processes DoT effects, debuffs, and buffs.
 *
 * @param params - Coverage, aura magnitude, equipped effects, enemies, rawMana
 * @returns Updated enemies, rawMana delta, player buffs, and log messages
 */
export function applyRoomEnchantmentTick(params: {
  coverage: number;
  auraMagnitudeMultiplier: number;
  equippedRoomEnchantments: RoomEnchantmentEffect[];
  enemies: EnemyState[];
  rawMana: number;
}): RoomEnchantmentTickResult {
  const { coverage, auraMagnitudeMultiplier, equippedRoomEnchantments, enemies, rawMana } = params;
  const coverageFraction = coverage / 100;
  const logMessages: string[] = [];
  let rawManaDelta = 0;
  let castSpeedMultiplier = 0;
  let transferenceRegenPerHour = 0;

  if (enemies.length === 0 || equippedRoomEnchantments.length === 0) {
    return {
      enemies,
      rawManaDelta: 0,
      playerBuffs: { castSpeedMultiplier: 0, transferenceRegenPerHour: 0 },
      logMessages: [],
    };
  }

  // Filter to living enemies
  const livingEnemies = enemies.filter(e => e.hp > 0);
  if (livingEnemies.length === 0) {
    return {
      enemies,
      rawManaDelta: 0,
      playerBuffs: { castSpeedMultiplier: 0, transferenceRegenPerHour: 0 },
      logMessages: [],
    };
  }

  // Process each equipped room enchantment
  for (const roomEnchant of equippedRoomEnchantments) {
    const effectiveMagnitude = roomEnchant.baseMagnitude * coverageFraction * auraMagnitudeMultiplier;

    switch (roomEnchant.specialId) {
      // ── DoT effects (bypass armor, hit all living enemies) ──────────────
      case 'room_fire_damage':
      case 'room_death_damage': {
        for (let i = 0; i < enemies.length; i++) {
          if (enemies[i].hp > 0) {
            enemies[i] = { ...enemies[i], hp: Math.max(0, enemies[i].hp - effectiveMagnitude) };
          }
        }
        break;
      }

      // ── Single-target chain (lightning: random enemy) ───────────────────
      case 'room_lightning_damage': {
        const livingIndices = enemies.map((e, i) => e.hp > 0 ? i : -1).filter(i => i >= 0);
        if (livingIndices.length > 0) {
          const targetIdx = livingIndices[Math.floor(Math.random() * livingIndices.length)];
          enemies[targetIdx] = {
            ...enemies[targetIdx],
            hp: Math.max(0, enemies[targetIdx].hp - effectiveMagnitude),
          };
        }
        break;
      }

      // ── Debuff effects (applied to all living enemies) ─────────────────
      case 'room_frost_debuff': {
        // Slow: reduces enemy dodge chance
        for (let i = 0; i < enemies.length; i++) {
          if (enemies[i].hp > 0) {
            enemies[i] = {
              ...enemies[i],
              dodgeChance: Math.max(0, enemies[i].dodgeChance - effectiveMagnitude),
            };
          }
        }
        break;
      }

      case 'room_dark_dodge_debuff': {
        // Dodge reduction
        for (let i = 0; i < enemies.length; i++) {
          if (enemies[i].hp > 0) {
            enemies[i] = {
              ...enemies[i],
              dodgeChance: Math.max(0, enemies[i].dodgeChance - effectiveMagnitude),
            };
          }
        }
        break;
      }

      case 'room_earth_armor_debuff': {
        // Armor reduction (effectiveArmor minimum 0)
        for (let i = 0; i < enemies.length; i++) {
          if (enemies[i].hp > 0) {
            enemies[i] = {
              ...enemies[i],
              effectiveArmor: Math.max(0, (enemies[i].effectiveArmor ?? enemies[i].armor) - effectiveMagnitude),
            };
          }
        }
        break;
      }

      // ── Buff/Regen effects (applied to player stats) ───────────────────
      case 'room_transference_buff': {
        // Cast speed bonus: added as multiplier
        castSpeedMultiplier += effectiveMagnitude;
        break;
      }

      case 'room_transference_regen': {
        // Transference mana regen per hour
        transferenceRegenPerHour += effectiveMagnitude;
        break;
      }
    }
  }

  // Consume transference mana for regen buff (simplified: raw mana delta)
  // In the full system, transference regen would be handled by the mana store.
  // Here we just report it for the combat tick result to factor in.

  return {
    enemies,
    rawManaDelta,
    playerBuffs: { castSpeedMultiplier, transferenceRegenPerHour },
    logMessages,
  };
}
