module account.model;

import std.datetime;
import std.traits : EnumMembers;

import util.money;

struct AccountType {
    immutable string id;
    immutable string name;
    immutable bool debitsPositive;

    static AccountType fromId(string id) {
        static foreach (t; ALL_ACCOUNT_TYPES) {
            if (t.id == id) return t;
        }
        throw new Exception("Invalid account type id " ~ id);
    }
}

enum AccountTypes : AccountType {
    CHECKING = AccountType("CHECKING", "Checking", true),
    SAVINGS = AccountType("SAVINGS", "Savings", true),
    CREDIT_CARD = AccountType("CREDIT_CARD", "Credit Card", false),
    BROKERAGE = AccountType("BROKERAGE", "Brokerage", true)
}

immutable(AccountType[]) ALL_ACCOUNT_TYPES = cast(AccountType[]) [ EnumMembers!AccountTypes ];

struct Account {
    ulong id;
    SysTime createdAt;
    bool archived;
    AccountType type;
    string numberSuffix;
    string name;
    Currency currency;
    string description;
}

struct AccountCreditCardProperties {
    immutable ulong account_id;
    immutable long creditLimit;
}

enum AccountJournalEntryType : string {
    CREDIT = "CREDIT",
    DEBIT = "DEBIT"
}

struct AccountJournalEntry {
    ulong id;
    SysTime timestamp;
    ulong accountId;
    ulong transactionId;
    ulong amount;
    AccountJournalEntryType type;
    Currency currency;
}

enum AccountValueRecordType : string {
    BALANCE = "BALANCE"
}

struct AccountValueRecord {
    ulong id;
    SysTime timestamp;
    ulong accountId;
    AccountValueRecordType type;
    long value;
    Currency currency;
}

enum AccountHistoryItemType : string {
    Text = "TEXT",
    PropertyChange = "PROPERTY_CHANGE",
    ValueRecord = "VALUE_RECORD",
    JournalEntry = "JOURNAL_ENTRY"
}
