# SPDX-License-Identifier: Apache-2.0
# © SuperNovae Studio · nika.sh/library
nika: v1
workflow:
  id: etl-quarantine
# zero model · a schema gate splits the batch

# the file IS the blast radius
permits:
  fs: { read: [ ./data/incoming/* ], write: [ ./data/* ] }
  tools: [ "nika:read", "nika:convert", "nika:validate", "nika:jq", "nika:write" ]

tasks:
  # the deterministic fallback if parsing dies
  empty_batch:
    invoke: { tool: "nika:jq", args: { input: [], expression: "." } }

  raw:
    invoke: { tool: "nika:read", args: { path: ./data/incoming/orders.csv } }

  rows:
    with:
      raw: ${{ tasks.raw.output }}
    invoke:
      tool: "nika:convert"
      args: { input: "${{ with.raw }}", from: csv, to: json, has_header: true }
    # malformed CSV → empty batch · the run survives
    on_error:
      recover: ${{ tasks.empty_batch.output }}

  check:
    with:
      rows: ${{ tasks.rows.output }}
    invoke:
      tool: "nika:validate"
      args:
        data: "${{ with.rows }}"
        format: json
        schema:
          type: array
          items:
            type: object
            required: [ order_id, amount, currency ]
            properties:
              order_id: { type: string }
              amount: { type: string }
              currency: { type: string, enum: [ EUR, USD, GBP ] }

  good:
    with:
      rows: ${{ tasks.rows.output }}
      valid: ${{ tasks.check.output.valid }}
    when: ${{ with.valid == true }}
    invoke:
      tool: "nika:jq"
      args:
        input: "${{ with.rows }}"
        expression: 'group_by(.currency) | map({currency: .[0].currency, orders: length, total: (map(.amount | tonumber) | add)})'

  quarantine:
    with:
      valid: ${{ tasks.check.output.valid }}
      errors: ${{ tasks.check.output.errors }}
    when: ${{ with.valid == false }}
    invoke:
      tool: "nika:write"
      args:
        path: ./data/quarantine/rejected.json
        content: "${{ with.errors }}"
        create_dirs: true

  report:
    with:
      totals: ${{ tasks.good.output }}   # value edge · passes when good is skipped (reads null)
    when: ${{ with.totals != null && size(with.totals) > 0 }}
    invoke:
      tool: "nika:write"
      args:
        path: ./data/daily-totals.json
        content: "${{ with.totals }}"
        create_dirs: true

outputs:
  totals: "${{ tasks.good.output }}"
