module transaction.dto;

import handy_http_primitives : Optional;
import asdf : serdeTransformOut;
import std.typecons;

import util.data;
import util.money;

/// The transaction data provided when a list of transactions is requested.
struct TransactionsListItem {
    ulong id;
    string timestamp;
    string addedAt;
    ulong amount;
    Currency currency;
    string description;
    @serdeTransformOut!serializeOptional
    Optional!Vendor vendor;
    @serdeTransformOut!serializeOptional
    Optional!Category category;
    @serdeTransformOut!serializeOptional
    Optional!Account creditedAccount;
    @serdeTransformOut!serializeOptional
    Optional!Account debitedAccount;
    string[] tags;

    static struct Account {
        ulong id;
        string name;
        string type;
        string numberSuffix;
    }

    static struct Vendor {
        ulong id;
        string name;
    }

    static struct Category {
        ulong id;
        string name;
        string color;
    }
}

/// Transaction data provided when fetching a single transaction.
struct TransactionDetail {
    ulong id;
    string timestamp;
    string addedAt;
    ulong amount;
    Currency currency;
    string description;
    Nullable!Vendor vendor;
    Nullable!Category category;
    Nullable!Account creditedAccount;
    Nullable!Account debitedAccount;
    string[] tags;
    LineItem[] lineItems;

    static struct Vendor {
        ulong id;
        string name;
        string description;
    }

    static struct Category {
        ulong id;
        Nullable!ulong parentId;
        string name;
        string description;
        string color;
    }

    static struct LineItem {
        uint idx;
        long valuePerItem;
        ulong quantity;
        string description;
        Nullable!Category category;
    }

    static struct Account {
        ulong id;
        string name;
        string type;
        string numberSuffix;
    }
}

/// Data provided when a new transaction is added by a user.
struct AddTransactionPayload {
    string timestamp;
    ulong amount;
    string currencyCode;
    string description;
    Nullable!ulong vendorId;
    Nullable!ulong categoryId;
    Nullable!ulong creditedAccountId;
    Nullable!ulong debitedAccountId;
    string[] tags;
    LineItem[] lineItems;

    static struct LineItem {
        long valuePerItem;
        ulong quantity;
        string description;
        Nullable!ulong categoryId;
    }
}
