## variant_migration.nim
## Migration utilities for transitioning from legacy USE flags to variant domains
## Task 15: Legacy flag translation and migration warnings

import std/[tables, strutils, os, strformat]
import variant_domains
import config

type
  MigrationResult* = object
    ## Result of flag migration
    success*: bool
    translatedFlags*: Table[string, seq[string]]  # domain -> flags
    warnings*: seq[string]
    errors*: seq[string]
    skippedFlags*: seq[string]  # Flags that couldn't be migrated

  LegacyFlagInfo* = object
    ## Information about a legacy flag
    name*: string
    category*: string
    enabled*: bool
    suggestedDomain*: string
    suggestedFlag*: string

# #############################################################################
# Legacy Flag Detection
# #############################################################################

proc detectLegacyFlags*(flags: seq[UseFlag]): seq[LegacyFlagInfo] =
  ## Detect legacy USE flags and provide migration suggestions
  result = @[]

  for flag in flags:
    if isLegacyCategory(flag.category):
      let suggestedDomain = mapLegacyCategoryToDomain(flag.category)

      var info = LegacyFlagInfo(
        name: flag.name,
        category: flag.category,
        enabled: flag.enabled,
        suggestedDomain: suggestedDomain,
        suggestedFlag: flag.name
      )

      result.add(info)

proc isLegacyFlagString*(flagStr: string): bool =
  ## Check if a flag string uses legacy syntax
  ## Legacy: category/flag or just flag
  ## New: +domain=flag

  if flagStr.startsWith("+"):
    return false  # New syntax

  if '/' in flagStr:
    return true  # Old category/flag syntax

  # Could be either - assume legacy if no domain marker
  return true

# #############################################################################
# Flag Translation
# #############################################################################

proc translateLegacyFlag*(
  flagName: string,
  category: string
): tuple[domain: string, flag: string, success: bool] =
  ## Translate a single legacy flag to new domain syntax

  if not isLegacyCategory(category):
    return ("", "", false)

  let domain = mapLegacyCategoryToDomain(category)

  # Special cases that shouldn't be migrated (returns empty string)
  if domain.len == 0:
    return ("", "", false)

  return (domain, flagName, true)

proc translateLegacyFlags*(flags: seq[UseFlag]): MigrationResult =
  ## Translate a list of legacy USE flags to domain-scoped flags

  result = MigrationResult(
    success: true,
    translatedFlags: initTable[string, seq[string]](),
    warnings: @[],
    errors: @[],
    skippedFlags: @[]
  )

  for flag in flags:
    if not flag.enabled:
      continue  # Skip disabled flags

    if not isLegacyCategory(flag.category):
      # Not a legacy flag - skip
      result.warnings.add(fmt"Skipping non-legacy flag: {flag.name} (category: {flag.category})")
      continue

    let (domain, translatedFlag, success) = translateLegacyFlag(flag.name, flag.category)

    if not success:
      result.skippedFlags.add(fmt"{flag.category}/{flag.name}")
      result.warnings.add(fmt"Cannot migrate {flag.category}/{flag.name} - special category")
      continue

    # Add to translated flags
    if not result.translatedFlags.hasKey(domain):
      result.translatedFlags[domain] = @[]

    if translatedFlag notin result.translatedFlags[domain]:
      result.translatedFlags[domain].add(translatedFlag)

proc translateFlagString*(flagStr: string): string =
  ## Translate a single flag string from legacy to new syntax
  ## Examples:
  ##   "gui/wayland" -> "+graphics=wayland"
  ##   "optimization/lto" -> "+optimization=lto"

  if flagStr.startsWith("+"):
    return flagStr  # Already new syntax

  if '/' in flagStr:
    let parts = flagStr.split('/', 1)
    if parts.len == 2:
      let category = parts[0]
      let flag = parts[1]

      if isLegacyCategory(category):
        let domain = mapLegacyCategoryToDomain(category)
        if domain notin ["profile", "build-mode"]:
          return fmt"+{domain}={flag}"

  # Couldn't translate - return as-is with warning marker
  return flagStr

# #############################################################################
# Migration Warnings
# #############################################################################

proc generateMigrationWarning*(flag: LegacyFlagInfo): string =
  ## Generate a deprecation warning for a legacy flag

  if flag.suggestedDomain in ["profile", "build-mode"]:
    return fmt"⚠️  Legacy flag '{flag.category}/{flag.name}' uses deprecated category. " &
           fmt"This should be handled as a {flag.suggestedDomain} instead."

  return fmt"⚠️  Legacy flag '{flag.category}/{flag.name}' is deprecated. " &
         fmt"Use: +{flag.suggestedDomain}={flag.suggestedFlag}"

proc generateMigrationSummary*(migrationResult: MigrationResult): string =
  ## Generate a human-readable summary of migration results

  var lines: seq[string] = @[]

  lines.add("🔄 Legacy Flag Migration Summary")
  lines.add("")

  if migrationResult.translatedFlags.len > 0:
    lines.add("✅ Translated Flags:")
    for domain, flags in migrationResult.translatedFlags.pairs:
      let flagsStr = flags.join(", ")
      lines.add(fmt"   {domain}: {flagsStr}")
    lines.add("")

  if migrationResult.skippedFlags.len > 0:
    lines.add("⏭️  Skipped Flags:")
    for flag in migrationResult.skippedFlags:
      lines.add(fmt"   {flag}")
    lines.add("")

  if migrationResult.warnings.len > 0:
    lines.add("⚠️  Warnings:")
    for warning in migrationResult.warnings:
      lines.add(fmt"   {warning}")
    lines.add("")

  if migrationResult.errors.len > 0:
    lines.add("❌ Errors:")
    for error in migrationResult.errors:
      lines.add(fmt"   {error}")
    lines.add("")

  return lines.join("\n")

# #############################################################################
# Config File Migration
# #############################################################################

proc migrateConfigFile*(
  inputPath: string,
  outputPath: string = ""
): tuple[success: bool, message: string] =
  ## Migrate a config file from legacy USE flags to domain syntax
  ## If outputPath is empty, overwrites the input file

  let actualOutputPath = if outputPath.len > 0: outputPath else: inputPath

  if not fileExists(inputPath):
    return (false, fmt"Input file not found: {inputPath}")

  try:
    let content = readFile(inputPath)
    var newLines: seq[string] = @[]
    var migrationCount = 0

    for line in content.splitLines():
      let trimmed = line.strip()

      # Skip comments and empty lines
      if trimmed.len == 0 or trimmed.startsWith("#"):
        newLines.add(line)
        continue

      # Check if line contains legacy flag syntax
      if '/' in trimmed and not trimmed.startsWith("+"):
        # Try to translate
        let translated = translateFlagString(trimmed)
        if translated != trimmed:
          newLines.add(translated)
          migrationCount += 1
          continue

      # Keep line as-is
      newLines.add(line)

    # Write output
    writeFile(actualOutputPath, newLines.join("\n"))

    if migrationCount > 0:
      return (true, fmt"✅ Migrated {migrationCount} flag(s) in {actualOutputPath}")
    else:
      return (true, fmt"ℹ️  No legacy flags found in {inputPath}")

  except IOError as e:
    return (false, fmt"Failed to migrate config: {e.msg}")

proc createMigrationBackup*(filePath: string): bool =
  ## Create a backup of a file before migration

  if not fileExists(filePath):
    return false

  let backupPath = filePath & ".backup"
  try:
    copyFile(filePath, backupPath)
    return true
  except:
    return false

# #############################################################################
# CLI Helper Functions
# #############################################################################

proc suggestDomainFlags*(legacyFlags: seq[string]): seq[string] =
  ## Suggest domain-scoped equivalents for legacy flags

  result = @[]
  for flagStr in legacyFlags:
    let translated = translateFlagString(flagStr)
    if translated != flagStr:
      result.add(translated)
    else:
      result.add(flagStr)  # Keep as-is if can't translate

proc printMigrationHelp*() =
  ## Print help for migration command

  echo """
🔄 NIP Flag Migration Utility

USAGE:
  nip migrate-flags [options] [file]

OPTIONS:
  --dry-run          Show what would be migrated without making changes
  --backup           Create backup before migration (default: true)
  --output <file>    Write to different file instead of overwriting
  --help             Show this help

EXAMPLES:
  # Migrate config file
  nip migrate-flags ~/.nip/config

  # Dry run to see changes
  nip migrate-flags --dry-run ~/.nip/config

  # Migrate to new file
  nip migrate-flags --output new-config.conf old-config.conf

LEGACY CATEGORIES → NEW DOMAINS:
  gui              → graphics
  gaming           → graphics
  container        → integration
  virtualization   → integration
  mesh             → network
  ai-ml            → runtime
  bindings         → runtime
  features         → runtime
  init             → init (unchanged)
  audio            → audio (unchanged)
  optimization     → optimization (unchanged)
  security         → security (unchanged)

SYNTAX CHANGES:
  OLD: gui/wayland
  NEW: +graphics=wayland

  OLD: optimization/lto
  NEW: +optimization=lto
"""
