## Review-gate integration for worker CLI
##
## Shells out to review-gate CLI for review state management.
## Uses taskId as the session ID for consistent mapping.

import std/[os, osproc, json, strutils, options, streams]
import ./utils

const
  ReviewGateCmd* = "review-gate"
  ReviewStateDir* = ".review-state"

type
  ReviewStatus* = enum
    rsNone = "none"         # No review registered
    rsPending = "pending"
    rsApproved = "approved"
    rsRejected = "rejected"

  ReviewState* = object
    sessionId*: string
    status*: ReviewStatus
    reason*: Option[string]
    issues*: seq[string]

proc runReviewGate(args: openArray[string]): tuple[output: string, exitCode: int] =
  ## Run review-gate command, return output and exit code.
  ## Returns exitCode=-1 if command not found.
  try:
    let process = startProcess(ReviewGateCmd, args = @args,
                               options = {poUsePath, poStdErrToStdOut})
    result.output = process.outputStream.readAll()
    result.exitCode = process.waitForExit()
    process.close()
  except OSError:
    # review-gate not installed - graceful degradation
    result.output = "review-gate not found"
    result.exitCode = -1

proc enableReview*(taskId: string): bool =
  ## Enable review requirement for a task. Returns true on success.
  let (output, code) = runReviewGate(["enable", taskId])
  if code != 0:
    logWarn("enableReview", "failed for " & taskId & ": " & output.strip())
    return false
  return true

proc approveReview*(taskId: string): bool =
  ## Approve review for a task. Returns true on success.
  let (output, code) = runReviewGate(["approve", taskId])
  if code != 0:
    logWarn("approveReview", "failed for " & taskId & ": " & output.strip())
    return false
  return true

proc rejectReview*(taskId: string, reason: string = ""): bool =
  ## Reject review for a task. Returns true on success.
  var args = @["reject", taskId]
  if reason != "":
    args.add(reason)
  let (output, code) = runReviewGate(args)
  if code != 0:
    logWarn("rejectReview", "failed for " & taskId & ": " & output.strip())
    return false
  return true

proc getReviewState*(taskId: string): ReviewState =
  ## Get review state for a task by reading state file directly.
  ## Faster than shelling out for status display.
  result.sessionId = taskId
  result.status = rsNone

  let stateFile = ReviewStateDir / (taskId & ".json")
  if not fileExists(stateFile):
    return

  try:
    let content = readFile(stateFile)
    let j = parseJson(content)

    let statusStr = j{"status"}.getStr("none")
    result.status = case statusStr
      of "pending": rsPending
      of "approved": rsApproved
      of "rejected": rsRejected
      else: rsNone

    if j.hasKey("reason"):
      result.reason = some(j["reason"].getStr())

    if j.hasKey("issues"):
      for issue in j["issues"]:
        result.issues.add(issue.getStr())
  except CatchableError as e:
    logWarn("getReviewState", "failed to read " & stateFile & ": " & e.msg)

proc reviewStatusStr*(rs: ReviewState): string =
  ## Format review status for display
  case rs.status
  of rsNone: "--"
  of rsPending: "PENDING"
  of rsApproved: "APPROVED"
  of rsRejected:
    if rs.reason.isSome:
      "REJECTED: " & rs.reason.get()
    else:
      "REJECTED"

proc cleanReviewState*(taskId: string) =
  ## Remove review state file for a task
  let stateFile = ReviewStateDir / (taskId & ".json")
  if fileExists(stateFile):
    try:
      removeFile(stateFile)
    except OSError as e:
      logWarn("cleanReviewState", "failed to remove " & stateFile & ": " & e.msg)
