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 {
    immutable ulong id;
    immutable SysTime createdAt;
    immutable bool archived;
    immutable AccountType type;
    immutable string numberSuffix;
    immutable string name;
    immutable Currency currency;
    immutable string description;
}

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

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

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

enum AccountValueRecordType : string {
    BALANCE = "BALANCE"
}

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