// An old Quicken file brought into a program: accounts, transactions with their splits, exact
// totals, the odd date and amount forms, and an export written back.
//
//   quillo run qif.qwe      then open http://localhost:8080/read, /splits, /invest, /totals, /rows, /forms, /write and /broken

use "qif.qwer"

let TEXT = read_file("qif_sample.qif")

route GET /read {
    let d = qif_read_file("qif_sample.qif", {})?
    let bank = d.groups[0]
    {
        accounts: d.accounts, categories: d.categories, classes: d.classes, securities: d.securities, memorized: d.memorized,
        order: d.dates, records: d.records, problems: d.problems,
        group: [bank.type, bank.account, len(bank.transactions)], first: bank.transactions[0], transfer: bank.transactions[4],
    }
}

route GET /splits = qif_parse(TEXT, {})?.groups[0].transactions[2]

route GET /invest = qif_parse(TEXT, {})?.groups[1]

route GET /totals = qif_totals(TEXT, { opening_cents: 150000 })?

route GET /rows = qif_rows(TEXT, {})? | map((r) => [r.date, r.payee, r.category, r.transfer, r.amount, r.split])

route GET /forms = {
    amounts: ["1,234.56", "1.234,56", "1 234,56", "-$12", "(5.00)", "12,50", "1,234", "1,234,567.89", "1.234.567,89", "5.", ".5", "7-", "+3", "0.125", "0"] | map((a) => [qif_amount(a, "")?.text, qif_amount(a, "")?.cents]),
    told: [qif_amount("1,234", ",")?.text, qif_amount("1.234", ",")?.text, qif_amount("1.234", ".")?.text],
    dates: [["1/ 2' 5", "mdy"], ["1/2/05", "mdy"], ["12/31/99", "mdy"], ["12/31'99", "mdy"], ["31/12/2025", "dmy"], ["2/1/26", "dmy"], ["12-31-2025", "mdy"], ["31.12.25", "dmy"], ["2025-12-31", "mdy"], ["2/29/2024", "mdy"]] | map((x) => qif_date(x[0], x[1])?),
    day_first: qif_parse("!Type:Bank\nD31/12/2025\nT1\n^\nD1/2/2026\nT2\n^\n", {})?.groups[0].transactions | map((t) => t.date),
    told_order: qif_parse("!Type:Bank\nD1/2/2026\nT1\n^\n", { dates: "dmy" })?.groups[0].transactions[0].date,
    european: qif_parse("!Type:Bank\nD1/2/26\nT1.234\n^\n", { decimal: "," })?.groups[0].transactions[0].amount,
}

let MINE = [
    { date: "2026-03-01", amount: "-1,000.50", payee: "Shop", memo: "Two things", number: "1002", cleared: "cleared", category: "Food", class: "Home", address: ["1 Road"], splits: [{ category: "Food", memo: "bread", amount: "-400.25" }, { transfer: "Savings", amount: -600.25 }] },
    { date: "2026-03-02", amount: 50, payee: "Refund", category: "Food" },
]

route GET /write {
    let text = qif_write("Bank", MINE, { account: { name: "Main", description: "Spending" } })?
    let back = qif_parse(text, {})?
    let t = back.groups[0].transactions
    let same = qif_parse(TEXT, {})?.groups[0].transactions
    {
        text: text, account: back.groups[0].account,
        again: t | map((x) => [x.date, x.amount, x.amount_cents, x.payee]), splits: t[0].splits, problems: back.problems,
        day_first: split(qif_write("Cash", [MINE[1]], { dates: "dmy" })?, "\n")[1],
        round_trip: qif_parse(qif_write("Bank", same, {})?, {})?.groups[0].transactions == same,
        off_by_one: qif_write("Bank", [{ date: "2026-01-01", amount: "10.00", splits: [{ category: "A", amount: "9.99" }] }], {}).error,
        bad_kind: qif_write("Savings", [], {}).error,
        no_date: qif_write("Bank", [{ amount: 1 }], {}).error,
        bad_date: qif_write("Bank", [{ date: "soon", amount: 1 }], {}).error,
        bad_amount: qif_write("Bank", [{ date: "2026-01-01", amount: "abc" }], {}).error,
        split_line: qif_write("Bank", [{ date: "2026-01-01", amount: 1, memo: "a\n^\nD1/1/26" }], {}).error,
    }
}

route GET /broken = {
    no_header: qif_parse("D1/2/26\nT1\n^\n", {}).error,
    bad_type: qif_parse("!Type:Crypto\n", {}).error,
    bad_date: qif_parse("!Type:Bank\nD13/13/2026\nT1\n^\n", { dates: "mdy" }).error,
    bad_amount: qif_parse("!Type:Bank\nD1/2/26\nTabc\n^\n", {}).error,
    bad_groups: qif_parse("!Type:Bank\nD1/2/26\nT1,23,4\n^\n", {}).error,
    split_order: qif_parse("!Type:Bank\nD1/2/26\nT1\n$1\n^\n", {}).error,
    no_caret: qif_parse("!Type:Bank\nD1/2/26\nT1\n!Type:Cash\n", {}).error,
    bad_order: qif_parse("!Type:Bank\n", { dates: "ydm" }).error,
    bad_sum: qif_parse("!Type:Bank\nD1/2/26\nT-10.00\nSA\n$-9.99\n^\n", {})?.problems,
    open_end: qif_parse("!Type:Bank\nD1/2/26\nT1\n", {})?.problems,
    no_date: qif_parse("!Type:Bank\nT1\n^\n", {})?.problems,
    odd_field: qif_parse("!Type:Bank\nD1/2/26\nZ1\n^\n", {})?.problems,
    unknown: qif_parse("!Foo\nx\n^\n!Type:Bank\nD1/2/26\nT1\n^\n", {})?.problems,
    no_file: qif_read_file("nothing.qif", {}).error != null,
}
