## nimpak/cli/publish_commands.nim
## Package publishing CLI commands
##
## This module implements Task 15.1e (partial):
## - nip publish command

import std/[os, strutils, strformat, asyncdispatch, json, options]
import ../repo/publish
import ../types_fixed except showInfo
import ../cas
import remote_commands
import core

proc nipPublish*(sourceDir: string, 
                packageName: string = "", 
                version: string = "",
                repoUrl: string = "",
                keyId: string = ""): Future[RemoteCommandResult] {.async.} =
  ## Publish a package from a local directory
  try:
    showInfo(fmt"📦 Publishing package from: {sourceDir}")
    
    # Defaults
    let home = getHomeDir()
    let casRoot = home / ".nip" / "cas"
    let keysRoot = home / ".nip" / "keys"
    let outputDir = home / ".nip" / "dist"
    
    createDir(casRoot)
    createDir(keysRoot)
    createDir(outputDir)
    
    # Initialize builder
    let builder = newArtifactBuilder(casRoot, keysRoot, outputDir)
    
    # Configure signing if key provided
    if keyId.len > 0:
      builder.config.signPackage = true
      builder.config.keyId = keyId
      showInfo(fmt"🔐 Signing with key: {keyId}")
    else:
      builder.config.signPackage = false
      showInfo("⚠️  Package will be unsigned (no key provided)")
      
    if repoUrl.len > 0:
      builder.config.repoId = repoUrl
      showInfo(fmt"🌐 Target Repository ID: {repoUrl}")
      
    # Determine name/version from directory if not provided
    # TODO: Parse from KDL/manifest in directory
    let finalName = if packageName.len > 0: packageName else: sourceDir.extractFilename
    let finalVersion = if version.len > 0: version else: "0.1.0"
    
    showInfo(fmt"📋 Metadata: {finalName} v{finalVersion}")
    
    # Create source definition
    let source = ArtifactSource(
      kind: FromDirectory,
      sourceDir: sourceDir
    )
    
    # Execute publish pipeline
    showInfo("🚀 Starting publish pipeline...")
    let result = await builder.publish(source, finalName, finalVersion)
    
    if result.success:
      showInfo("✅ Publish successful!")
      showInfo(fmt"📦 Integrity: {result.casHash}")
      if result.repoUrl.len > 0:
        showInfo(fmt"🌐 Uploaded to: {result.repoUrl}")
      else:
        showInfo(fmt"💾 Saved locally to: {outputDir}")
      
      return RemoteCommandResult(
        success: true,
        message: "Publish successful",
        data: %*{
          "package": finalName,
          "version": finalVersion,
          "hash": result.casHash,
          "archive": outputDir / fmt"{finalName}-{finalVersion}.npk.zst",
          "url": result.repoUrl
        },
        exitCode: 0
      )
    else:
      # Format errors
      var errMsg = "Publish failed:"
      for err in result.errors:
        errMsg &= "\n  - " & err
      
      return RemoteCommandResult(
        success: false,
        message: errMsg,
        data: newJNull(),
        exitCode: 1
      )

  except Exception as e:
    return RemoteCommandResult(
      success: false,
      message: fmt"Publish command failed: {e.msg}",
      data: newJNull(),
      exitCode: 1
    )

proc registerPublishCommands*() =
  ## Register publish commands
  discard
