import createDebug from "debug";
// @ts-ignore - JavaScript module without TypeScript declarations
import { PklDynamicEvaluator } from "../../scripts/pkl-utils/dynamic-evaluator.js";

const debugPkl = createDebug("anrubic:pkl");

let pklEvaluator: PklDynamicEvaluator | null = null;
let pklAvailable = false;
let initializationAttempted = false;

export interface PklInitResult {
  success: boolean;
  pklAvailable: boolean;
  error?: string;
  version?: string;
}

/**
 * Initialize Pkl evaluator with configurable command
 * @param pklCommand - Pkl command to use (default: 'pkl')
 * @returns Initialization result
 */
export async function initializePkl(pklCommand = "pkl"): Promise<PklInitResult> {
  if (initializationAttempted && pklEvaluator) {
    return { success: true, pklAvailable };
  }

  initializationAttempted = true;

  try {
    pklEvaluator = new PklDynamicEvaluator({
      tempDir: "/tmp/pkl-eval-anrubic",
      cacheEnabled: true,
      pklCommand,
    });

    // Test if Pkl is available with a simple evaluation
    const testTemplate = `result = "pkl-available"`;
    const testResult = await pklEvaluator.evaluateTemplate(testTemplate);

    if (testResult?.result === "pkl-available") {
      pklAvailable = true;
      debugPkl("Pkl integration ONLINE! Advanced combat analysis enabled!");

      return {
        success: true,
        pklAvailable: true,
        version: "detected",
      };
    } else {
      throw new Error("Pkl test evaluation failed");
    }
  } catch (error) {
    pklAvailable = false;
    debugPkl("Pkl not available - falling back to JSON mode for basic analysis");

    return {
      success: false,
      pklAvailable: false,
      error: error instanceof Error ? error.message : String(error),
    };
  }
}

/**
 * Check if Pkl is available for advanced analysis
 */
export function isPklAvailable(): boolean {
  return pklAvailable;
}

/**
 * Get the Pkl evaluator instance (may be null if not available)
 */
export function getPklEvaluator(): PklDynamicEvaluator | null {
  return pklEvaluator;
}

/**
 * Execute combat analysis using Pkl API files
 * @param unitA - First unit identifier
 * @param unitB - Second unit identifier
 * @returns Combat analysis result
 */
export async function executeCombatAnalysis(unitA: string, unitB: string): Promise<any> {
  if (!pklEvaluator || !pklAvailable) {
    throw new Error("Pkl not available - cannot perform advanced combat analysis");
  }

  const template = `
import "iolin/api/unit-combat-meta.pkl" as CombatMeta

// Execute the combat analysis
result = CombatMeta.result

metadata = new {
  analysis = "pkl-powered-combat"
  version = "anrubic-v1"
  units = List("${escapeString(unitA)}", "${escapeString(unitB)}")
}
`;

  try {
    const result = await pklEvaluator.evaluateTemplate(
      template,
      {
        unitAId: unitA,
        unitBId: unitB,
      },
      {
        timeout: 15000,
        format: "json",
      },
    );

    return {
      success: true,
      data: result,
      source: "pkl-api",
      units: [unitA, unitB],
    };
  } catch (error) {
    throw new Error(
      `Combat analysis failed: ${error instanceof Error ? error.message : String(error)}`,
    );
  }
}

/**
 * Execute unit comparison using Pkl API
 * @param units - Array of unit identifiers
 * @returns Unit comparison result
 */
export async function executeUnitComparison(units: string[]): Promise<any> {
  if (!pklEvaluator || !pklAvailable) {
    throw new Error("Pkl not available - cannot perform advanced unit comparison");
  }

  const unitsListStr = units.map((u) => `"${escapeString(u)}"`).join("; ");

  const template = `
import "iolin/api/unit-comparison.pkl" as UnitComparison

// Override the module's parameters by creating a new context
result = (UnitComparison) {
  units = new Listing { ${unitsListStr} }
  analysis = "full"
  includeTiers = true
  includeUpgrades = false
}.result

metadata = new {
  analysis = "pkl-powered-comparison"
  version = "anrubic-v1"
  searchedUnits = new Listing { ${unitsListStr} }
}
`;

  try {
    const result = await pklEvaluator.evaluateTemplate(
      template,
      {},
      {
        timeout: 20000,
        format: "json",
      },
    );

    return {
      success: true,
      data: result,
      source: "pkl-api",
      units,
    };
  } catch (error) {
    throw new Error(
      `Unit comparison failed: ${error instanceof Error ? error.message : String(error)}`,
    );
  }
}

/**
 * Find counters for a specific unit using custom Pkl analysis
 * @param targetUnit - Unit to find counters for
 * @param limit - Maximum number of counters to return
 * @returns Counter analysis result
 */
export async function findCounters(targetUnit: string, limit = 10): Promise<any> {
  if (!pklEvaluator || !pklAvailable) {
    throw new Error("Pkl not available - cannot perform counter analysis");
  }

  const template = `
import "iolin/meta/all.pkl" as AllData

// Hide intermediate variables to reduce output size
local targetUnitName = "${escapeString(targetUnit)}"

// Find the target unit
local function findUnit(identifier: String) = AllData.all
  .filter((entity) -> entity.type == "unit")
  .find((unit) ->
    unit.name.toLowerCase() == identifier.toLowerCase() ||
    (unit.slug != null && unit.slug.toLowerCase().contains(identifier.toLowerCase()))
  )

local targetUnit = findUnit(targetUnitName)

// Get all combat units for analysis
local allUnits = AllData.all
  .filter((entity) -> entity.type == "unit")
  .filter((unit) -> unit.name != targetUnitName)

// Calculate who wins against target unit
local function calculateWinners(target) =
  allUnits
    .map((challenger) ->
      let (targetAttack = target.ability?.keys?.map((key) -> target.ability[key])?.filter((a) -> a.subtype == "attack")?.firstOrNull)
      let (challengerAttack = challenger.ability?.keys?.map((key) -> challenger.ability[key])?.filter((a) -> a.subtype == "attack")?.firstOrNull)
      let (targetDamage = targetAttack?.damage ?? 0)
      let (challengerDamage = challengerAttack?.damage ?? 0)
      let (targetArmor = target.armor ?? 0)
      let (challengerArmor = challenger.armor ?? 0)
      let (targetArmorReduction = targetArmor / (targetArmor + 6))
      let (challengerArmorReduction = challengerArmor / (challengerArmor + 6))
      let (effectiveDamageToTarget = challengerDamage * (1 - targetArmorReduction))
      let (effectiveDamageToChallenger = targetDamage * (1 - challengerArmorReduction))
      let (shotsToKillTarget = if (effectiveDamageToTarget > 0) (target.hp / effectiveDamageToTarget).ceil else 999)
      let (shotsToKillChallenger = if (effectiveDamageToChallenger > 0) (challenger.hp / effectiveDamageToChallenger).ceil else 999)
      let (timeToKillTarget = shotsToKillTarget * (challengerAttack?.cooldown ?? 1))
      let (timeToKillChallenger = shotsToKillChallenger * (targetAttack?.cooldown ?? 1))
      let (challengerWins = timeToKillTarget < timeToKillChallenger)
      let (advantage = if (challengerWins) (timeToKillChallenger - timeToKillTarget) else 0)
        new Dynamic {
          name = challenger.name
          faction = challenger.id?.split("/")[1] ?? "unknown"
          tier = challenger.tier ?? "unknown"
          wins = challengerWins
          timeAdvantage = advantage
          costEfficiency = if ((challenger.hexiteCost ?? 0) > 0 && (target.hexiteCost ?? 0) > 0)
            ((target.hexiteCost ?? 0) / (challenger.hexiteCost ?? 0)) else 0
          damageDealt = effectiveDamageToTarget.floor
          shotsNeeded = shotsToKillTarget
          timeToKill = timeToKillTarget
        }
    )
    .filter((result) -> result.wins)
    .sortWith((a, b) -> if (b.timeAdvantage > a.timeAdvantage) 1 else if (b.timeAdvantage < a.timeAdvantage) -1 else 0)
    .take(${limit})

result = if (targetUnit != null)
  new Dynamic {
    target = new Dynamic {
      name = targetUnit.name
      faction = targetUnit.id?.split("/")[1] ?? "unknown"
      tier = targetUnit.tier ?? "unknown"
      health = targetUnit.hp ?? 0
      armor = targetUnit.armor ?? 0
      cost = targetUnit.hexiteCost ?? 0
    }
    counters = calculateWinners(targetUnit)
    totalCountersFound = calculateWinners(targetUnit).length
    analysis = "Strong counters based on time-to-kill advantage"
    success = true
  }
else
  new Dynamic {
    error = "Target unit not found: " + targetUnitName
    suggestions = allUnits.take(5).map((u) -> u.name)
    success = false
  }

metadata = new Dynamic {
  analysis = "pkl-powered-counters"
  version = "anrubic-v1"
  targetUnit = targetUnitName
}
`;

  try {
    const result = await pklEvaluator.evaluateTemplate(
      template,
      {},
      {
        timeout: 20000,
        format: "json",
      },
    );

    return {
      success: true,
      data: result,
      source: "pkl-counter-analysis",
      targetUnit,
    };
  } catch (error) {
    throw new Error(
      `Counter analysis failed: ${error instanceof Error ? error.message : String(error)}`,
    );
  }
}

/**
 * Execute Emperor sacrifice calculation using Pkl API
 * @param thralls - Number of Thralls to sacrifice
 * @param steelsworn - Number of Steelsworn to sacrifice
 * @param darkDisciples - Number of Dark Disciples to sacrifice
 * @returns Emperor calculation result
 */
export async function executeEmperorCalculation(
  thralls: number,
  steelsworn: number,
  darkDisciples: number,
): Promise<any> {
  if (!pklEvaluator || !pklAvailable) {
    throw new Error("Pkl not available - cannot perform Emperor calculation");
  }

  const template = `
import "iolin/api/emperor-calculator.pkl" as EmperorCalc

// Override the module's parameters by creating a new context
result = (EmperorCalc) {
  thrallCount = ${thralls}
  steelswornCount = ${steelsworn}
  darkDiscipleCount = ${darkDisciples}
}.result

metadata = new {
  analysis = "pkl-powered-emperor-calculator"
  version = "anrubic-v1"
  sacrifices = new {
    thralls = ${thralls}
    steelsworn = ${steelsworn}
    darkDisciples = ${darkDisciples}
  }
}
`;

  try {
    const result = await pklEvaluator.evaluateTemplate(
      template,
      {},
      {
        timeout: 15000,
        format: "json",
      },
    );

    return {
      success: true,
      data: result,
      source: "pkl-emperor-calculator",
      sacrifices: { thralls, steelsworn, darkDisciples },
    };
  } catch (error) {
    throw new Error(
      `Emperor calculation failed: ${error instanceof Error ? error.message : String(error)}`,
    );
  }
}

/**
 * Get health status of Pkl integration
 */
export async function getPklHealth(): Promise<any> {
  if (!pklEvaluator) {
    return {
      available: false,
      status: "not-initialized",
      message: "Pkl evaluator not initialized",
    };
  }

  try {
    // Simple test evaluation to verify PKL is working
    const testTemplate = `
result = "pkl-health-ok"
version = "test"
`;
    const testResult = await pklEvaluator.evaluateTemplate(testTemplate, {}, { timeout: 5000 });

    return {
      available: pklAvailable,
      status: "healthy",
      message: "Pkl evaluator is working correctly",
      testResult: testResult.result,
    };
  } catch (error) {
    return {
      available: false,
      status: "error",
      error: error instanceof Error ? error.message : String(error),
    };
  }
}

/**
 * Escape string for safe Pkl template insertion
 */
function escapeString(str: string): string {
  return str.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
}
