*******************************************************************************
* yaml_write
*! v 1.5.1   18Feb2026               by Joao Pedro Azevedo (UNICEF)
* Write Stata data to YAML file
*******************************************************************************

program define yaml_write
    version 14.0

    syntax using/ [, Scalars(string) FRAME(string) Replace Verbose INDENT(integer 2) HEADER(string)]

    * If frame specified, add yaml_ prefix if not present
    if ("`frame'" != "") {
        if (`c(stata_version)' < 16) {
            di as err "frame() option requires Stata 16 or later"
            exit 198
        }
        if (substr("`frame'", 1, 5) != "yaml_") {
            local frame "yaml_`frame'"
        }
    }

    * Check if file exists and handle replace
    capture confirm file "`using'"
    if (_rc == 0 & "`replace'" == "") {
        di as err "file `using' already exists. Use 'replace' option."
        exit 602
    }

    * Open file for writing
    tempname fh
    file open `fh' using "`using'", write text replace

    * Write header comment if specified
    if ("`header'" != "") {
        file write `fh' "# `header'" _n
    }
    else {
        file write `fh' "# Generated by Stata yaml write" _n
        file write `fh' "# Date: `c(current_date)' `c(current_time)'" _n
    }

    * If scalars option, write scalars
    if ("`scalars'" != "") {
        foreach s of local scalars {
            * Confirm scalar exists
            capture scalar `s'
            if (_rc == 0) {
                local val = scalar(`s')
                file write `fh' "`s': `val'" _n
            }
        }
    }
    else {
        * Write from dataset or frame
        if ("`frame'" != "") {
            * Ensure frame exists
            capture frame `frame': describe
            if (_rc != 0) {
                di as err "frame `frame' not found"
                exit 198
            }
            frame `frame' {
                _yaml_write_impl `fh', indent(`indent')
            }
        }
        else {
            _yaml_write_impl `fh', indent(`indent')
        }
    }

    file close `fh'

    if ("`verbose'" != "") {
        di as text "YAML written to `using'"
    }
end

program define _yaml_write_impl
    syntax anything(name=fh) [, INDENT(integer 2)]

    * Ensure required variables exist
    capture confirm variable key value level type
    if (_rc != 0) {
        di as err "Data must include key, value, level, type variables. Use yaml read first."
        exit 198
    }

    * Check for parent variable (needed for leaf key extraction)
    capture confirm variable parent
    local has_parent = (_rc == 0)

    * Write rows in observation order (do NOT sort -- insertion order = file order)
    local n = _N
    forvalues i = 1/`n' {
        local k = key[`i']
        local v = value[`i']
        local l = level[`i']
        local t = type[`i']
        local p = ""
        if (`has_parent') {
            local p = parent[`i']
        }

        * Build indentation: (level - 1) * indent spaces
        local nspaces = (`l' - 1) * `indent'
        local spaces ""
        forvalues j = 1/`nspaces' {
            local spaces "`spaces' "
        }

        * Extract leaf key name by stripping parent prefix
        local leaf "`k'"
        if (`has_parent' & "`p'" != "") {
            local plen = length("`p'")
            if (substr("`k'", 1, `plen') == "`p'" & substr("`k'", `plen' + 1, 1) == "_") {
                local leaf = substr("`k'", `plen' + 2, .)
            }
        }

        if ("`t'" == "parent") {
            file write `fh' "`spaces'`leaf':" _n
        }
        else if ("`t'" == "list_item") {
            file write `fh' `"`spaces'- `v'"' _n
        }
        else {
            file write `fh' `"`spaces'`leaf': `v'"' _n
        }
    }
end