# SPDX-License-Identifier: LSL-1.0
# Copyright (c) 2026 Markus Maiwald
# Stewardship: Self Sovereign Society Foundation
#
# This file is part of the Nexus Sovereign Core.
# See legal/LICENSE_SOVEREIGN.md for license terms.

## variant_mappings.nim
## Maps NIP variant domains to package manager specific flags
## Each package can have custom mappings, with fallback to generic mappings

import std/[tables, strutils, json, os]

type
  PackageManagerFlag* = object
    nix*: string          # Nix override attribute
    pkgsrc*: string       # PKGSRC PKG_OPTIONS flag
    gentoo*: string       # Gentoo USE flag
    description*: string

  VariantMapping* = object
    domain*: string
    value*: string
    flags*: PackageManagerFlag

# Generic variant mappings (work for most packages)
const GenericMappings* = {
  # Graphics domain
  ("graphics", "wayland"): PackageManagerFlag(
    nix: "waylandSupport = true",
    pkgsrc: "wayland",
    gentoo: "wayland",
    description: "Wayland display server support"
  ),
  ("graphics", "X"): PackageManagerFlag(
    nix: "x11Support = true",
    pkgsrc: "x11",
    gentoo: "X",
    description: "X11 display server support"
  ),
  ("graphics", "vulkan"): PackageManagerFlag(
    nix: "vulkanSupport = true",
    pkgsrc: "vulkan",
    gentoo: "vulkan",
    description: "Vulkan graphics API"
  ),

  # Audio domain
  ("audio", "pipewire"): PackageManagerFlag(
    nix: "pipewireSupport = true",
    pkgsrc: "pipewire",
    gentoo: "pipewire",
    description: "PipeWire audio server"
  ),
  ("audio", "pulseaudio"): PackageManagerFlag(
    nix: "pulseaudioSupport = true",
    pkgsrc: "pulseaudio",
    gentoo: "pulseaudio",
    description: "PulseAudio sound server"
  ),
  ("audio", "alsa"): PackageManagerFlag(
    nix: "alsaSupport = true",
    pkgsrc: "alsa",
    gentoo: "alsa",
    description: "ALSA audio support"
  ),

  # Optimization domain
  ("optimization", "lto"): PackageManagerFlag(
    nix: "enableLTO = true",
    pkgsrc: "-flto",
    gentoo: "lto",
    description: "Link-time optimization"
  ),
  ("optimization", "pgo"): PackageManagerFlag(
    nix: "enablePGO = true",
    pkgsrc: "-fprofile-generate",
    gentoo: "pgo",
    description: "Profile-guided optimization"
  ),

  # Security domain
  ("security", "pie"): PackageManagerFlag(
    nix: "hardeningEnable = [\"pie\"]",
    pkgsrc: "-fPIE",
    gentoo: "pie",
    description: "Position independent executable"
  ),
  ("security", "hardened"): PackageManagerFlag(
    nix: "hardeningEnable = [\"all\"]",
    pkgsrc: "hardened",
    gentoo: "hardened",
    description: "Full hardening"
  )
}.toTable

# Package-specific mappings (override generic for specific packages)
const PackageSpecificMappings* = {
  # Firefox specific
  ("firefox", "graphics", "wayland"): PackageManagerFlag(
    nix: "waylandSupport = true",
    pkgsrc: "wayland",
    gentoo: "wayland",
    description: "Firefox Wayland support"
  ),
  ("firefox", "audio", "pipewire"): PackageManagerFlag(
    nix: "pipewireSupport = true",
    pkgsrc: "pulseaudio",  # PKGSRC firefox uses pulseaudio flag
    gentoo: "pipewire",
    description: "Firefox audio via PipeWire"
  ),

  # Chromium specific
  ("chromium", "graphics", "wayland"): PackageManagerFlag(
    nix: "enableWayland = true",
    pkgsrc: "wayland",
    gentoo: "wayland",
    description: "Chromium Wayland support"
  ),

  # NGINX specific
  ("nginx", "network", "ipv6"): PackageManagerFlag(
    nix: "withIPv6 = true",
    pkgsrc: "inet6",
    gentoo: "ipv6",
    description: "IPv6 support"
  )
}.toTable

proc getVariantMapping*(packageName: string, domain: string, value: string): PackageManagerFlag =
  ## Get the package manager flags for a variant
  ## Checks package-specific mappings first, then falls back to generic

  # Check package-specific mapping
  let specificKey = (packageName.toLower(), domain, value)
  if PackageSpecificMappings.hasKey(specificKey):
    return PackageSpecificMappings[specificKey]

  # Fall back to generic mapping
  let genericKey = (domain, value)
  if GenericMappings.hasKey(genericKey):
    return GenericMappings[genericKey]

  # Return empty if not found
  result = PackageManagerFlag(
    nix: "",
    pkgsrc: "",
    gentoo: "",
    description: "Unknown variant"
  )

proc loadCustomMappings*(mappingFile: string): Table[(string, string, string), PackageManagerFlag] =
  ## Load custom variant mappings from a JSON file
  ## Format: { "package": { "domain": { "value": { "nix": "...", "pkgsrc": "...", "gentoo": "..." } } } }
  result = initTable[(string, string, string), PackageManagerFlag]()

  if not fileExists(mappingFile):
    return

  try:
    let content = readFile(mappingFile)
    let json = parseJson(content)

    for packageName, packageData in json.pairs:
      for domain, domainData in packageData.pairs:
        for value, flagData in domainData.pairs:
          let flags = PackageManagerFlag(
            nix: flagData{"nix"}.getStr(""),
            pkgsrc: flagData{"pkgsrc"}.getStr(""),
            gentoo: flagData{"gentoo"}.getStr(""),
            description: flagData{"description"}.getStr("")
          )
          result[(packageName, domain, value)] = flags
  except:
    discard

proc showVariantMappings*(packageName: string = "", domain: string = "") =
  ## Show available variant mappings
  echo "🗺️  Variant Mappings"
  echo ""

  if packageName != "":
    echo "Package-specific mappings for: " & packageName
    echo ""
    for key, flags in PackageSpecificMappings:
      let (pkg, dom, val) = key
      if pkg == packageName.toLower():
        echo "  " & dom & "=" & val
        echo "    Nix:     " & flags.nix
        echo "    PKGSRC:  " & flags.pkgsrc
        echo "    Gentoo:  " & flags.gentoo
        echo ""
  else:
    echo "Generic mappings:"
    echo ""
    for key, flags in GenericMappings:
      let (dom, val) = key
      if domain == "" or dom == domain:
        echo "  " & dom & "=" & val
        echo "    Nix:     " & flags.nix
        echo "    PKGSRC:  " & flags.pkgsrc
        echo "    Gentoo:  " & flags.gentoo
        echo "    " & flags.description
        echo ""

proc generateMappingTemplate*(outputFile: string) =
  ## Generate a template JSON file for custom mappings
  let mappingTemplate = %*{
    "firefox": {
      "graphics": {
        "wayland": {
          "nix": "waylandSupport = true",
          "pkgsrc": "wayland",
          "gentoo": "wayland",
          "description": "Wayland support"
        }
      }
    },
    "nginx": {
      "network": {
        "ipv6": {
          "nix": "withIPv6 = true",
          "pkgsrc": "inet6",
          "gentoo": "ipv6",
          "description": "IPv6 support"
        }
      }
    }
  }

  writeFile(outputFile, mappingTemplate.pretty())
  echo "✅ Generated mapping template: " & outputFile
