#!/usr/bin/env nu
# reflection/modules/forms.nu — form listing and execution.
#
# Error handling policy:
#   forms list   — daemon-export-safe; graceful skip on broken form file
#   form run     — daemon-export (fail loud); agent path renders NCL template via tera
#   render-*     — tera-render direct; fail loud on template error

use env.nu *
use store.nu [daemon-export, daemon-export-safe]

export def "forms list" [] {
  form-files | each { |f|
    let data = (daemon-export-safe $f)
    if $data != null {
      {
        name:        ($f | path basename | str replace ".ncl" ""),
        description: ($data.description? | default ""),
      }
    } else { null }
  } | compact
}

export def "form run" [
  name: string,
  --backend: string = "cli",  # Backend: cli (default) | tui | web
] {
  let actor     = ($env.ONTOREF_ACTOR? | default "developer")
  let forms_dir = $"($env.ONTOREF_ROOT)/reflection/forms"
  let form_file = $"($forms_dir)/($name).ncl"

  # Guard: form must exist
  if not ($form_file | path exists) {
    let available = (form-files | each { |f| $f | path basename | str replace ".ncl" "" })
    print $"Form '($name)' not found."
    print $"Available: ($available | str join ', ')"
    exit 1
  }

  if $actor == "agent" {
    agent-render $name $form_file
    return
  }

  # Guard: typedialog must be present for interactive path
  if (which typedialog | is-empty) {
    print ""
    print "typedialog is required for interactive forms."
    print "Install: cargo install typedialog"
    print ""
    print "Agent path (no typedialog needed):"
    agent-render-hint $name $form_file
    exit 1
  }

  run-interactive-form $name $form_file $backend
}

# Render an ADR from a piped record via tera-render.
# { id: "adr-005", title: "...", status: "Proposed" } | form render-adr | save adrs/adr-005-title.ncl
export def "form render-adr" [
  --output: path,
] {
  let tmpl = $"($env.ONTOREF_ROOT)/reflection/templates/adr.ncl.j2"
  let rendered = $in | tera-render $tmpl
  if ($output | is-not-empty) {
    $rendered | save --force $output
    print $"Written: ($output)"
  } else {
    $rendered
  }
}

# Render a new-project script from a piped record via tera-render.
# { project_name: "myapp", project_dir: "/tmp/myapp" } | form render-project --output ~/create.nu
export def "form render-project" [
  --output: path,
] {
  let tmpl = $"($env.ONTOREF_ROOT)/reflection/templates/create_project.nu.j2"
  let rendered = $in | tera-render $tmpl
  if ($output | is-not-empty) {
    $rendered | save --force $output
    print $"Written: ($output)"
  } else {
    $rendered
  }
}

export def "forms help" [] {
  let actor = ($env.ONTOREF_ACTOR? | default "developer")
  print ""
  print "Form commands:"
  print "  forms list                        list available forms"
  print "  form run <name>                   run a form (interactive or agent)"
  print "  form render-adr [--output <path>] render ADR from piped record"
  print "  form render-project [--output]    render new-project script from piped record"
  print ""
  for f in (forms list) {
    print $"  ($f.name)"
    print $"    ($f.description)"
  }
  if $actor == "agent" {
    print ""
    print "Agent render pipeline:"
    print "  nickel-export adrs/_template.ncl | form render-adr --output adrs/adr-005-title.ncl"
    print "  { project_name: 'myapp', ... }  | form render-project --output ~/create.nu"
    print ""
    print "Inspect form fields:"
    print "  nickel-export reflection/forms/<name>.ncl | get elements"
    print "    | where type != 'section_header' | select name prompt required nickel_path"
  }
  print ""
}

# ── Internal ───────────────────────────────────────────────────────────────────

def form-files [] {
  glob $"($env.ONTOREF_ROOT)/reflection/forms/*.ncl"
}

def next-adr-id [] {
  let root = ($env.ONTOREF_PROJECT_ROOT? | default $env.ONTOREF_ROOT)
  let nums = (
    glob $"($root)/adrs/adr-*.ncl"
    | each { |f| $f | path basename }
    | parse "adr-{n}-{rest}.ncl"
    | get n
    | each { |n| $n | into int }
    | sort
  )
  let next = if ($nums | is-empty) { 1 } else { ($nums | last) + 1 }
  $"adr-($next | fill --alignment right --width 3 --character '0')"
}

def agent-render [name: string, form_file: string] {
  if $name == "new_adr" {
    let root     = ($env.ONTOREF_PROJECT_ROOT? | default $env.ONTOREF_ROOT)
    let template = $"($env.ONTOREF_ROOT)/adrs/_template.ncl"
    let tmpl     = $"($env.ONTOREF_ROOT)/reflection/templates/adr.ncl.j2"
    let next_id  = (next-adr-id)
    let out      = $"($root)/adrs/($next_id)-draft.ncl"
    print $"Rendering ($next_id) from template — output: ($out)"
    daemon-export $template | to json | tera-render $tmpl | save --force $out
    print $"Run: nickel-validate ($out)"
  } else {
    agent-render-hint $name $form_file
  }
}

def agent-render-hint [name: string, form_file: string] {
  print ""
  print $"Fields for '($name)':"
  print $"  nickel-export ($form_file) | get elements"
  print "    | where type != \"section_header\" | select name prompt required nickel_path"
  print ""
}

def td-roundtrip [backend: string, input: string, form: string, output: string, ncl_template: string] {
  match $backend {
    "web" => { ^typedialog web nickel-roundtrip $input $form --output $output --ncl-template $ncl_template --open },
    "tui" => { ^typedialog tui nickel-roundtrip $input $form --output $output --ncl-template $ncl_template },
    _     => { ^typedialog nickel-roundtrip $input $form --output $output --ncl-template $ncl_template },
  }
}

def td-form [backend: string, form: string, ...extra: string] {
  match $backend {
    "web" => { ^typedialog web form $form ...$extra },
    "tui" => { ^typedialog tui $form ...$extra },
    _     => { ^typedialog form $form ...$extra },
  }
}

def run-interactive-form [name: string, form_file: string, backend: string] {
  if $name == "new_adr" {
    let root     = ($env.ONTOREF_PROJECT_ROOT? | default $env.ONTOREF_ROOT)
    let template = $"($env.ONTOREF_ROOT)/adrs/_template.ncl"
    let tmpl     = $"($env.ONTOREF_ROOT)/reflection/templates/adr.ncl.j2"
    let next_id  = (next-adr-id)
    let out      = $"($root)/adrs/($next_id)-draft.ncl"
    let tmp      = $"($env.HOME)/.ontoref-adr-tmp.ncl"
    open $template | str replace '"adr-000"' $'"($next_id)"' | save --force $tmp
    print $"Creating ($next_id) — output: ($out)"
    td-roundtrip $backend $tmp $form_file $out $tmpl
    rm --force $tmp
    print $"Run: nickel typecheck ($out)"
  } else if $name == "new_project" {
    let tmpl = $"($env.ONTOREF_ROOT)/reflection/templates/create_project.nu.j2"
    let out  = $"($env.HOME)/ontoref-create-project.nu"
    td-form $backend $form_file "--ncl-template" $tmpl "--output" $out
    print $"Script generated: ($out)"
    print $"Review then: nu ($out)"
  } else if $name == "supersede_adr" {
    let tmpl = $"($env.ONTOREF_ROOT)/reflection/templates/supersede_adr.nu.j2"
    let out  = $"($env.HOME)/ontoref-supersede.nu"
    td-form $backend $form_file "--ncl-template" $tmpl "--output" $out
    print $"Script generated: ($out)"
    print $"Review then: nu ($out)"
  } else {
    td-form $backend $form_file
  }
}
