module account.data;

import handy_http_primitives : Optional;

import account.model;
import account.dto;
import util.money;
import util.pagination;

import std.datetime : SysTime;

interface AccountRepository {
    Optional!Account findById(ulong id);
    bool existsById(ulong id);
    Account insert(AccountType type, string numberSuffix, string name, Currency currency, string description);
    void setArchived(ulong id, bool archived);
    Account update(ulong id, in Account newData);
    void deleteById(ulong id);
    Account[] findAll();
    AccountCreditCardProperties getCreditCardProperties(ulong id);
    void setCreditCardProperties(ulong id, in AccountCreditCardProperties props);

    Page!AccountHistoryItemResponse getHistory(ulong accountId, in PageRequest pagination);
}

interface AccountJournalEntryRepository {
    Optional!AccountJournalEntry findById(ulong id);
    AccountJournalEntry insert(
        SysTime timestamp,
        ulong accountId,
        ulong transactionId,
        ulong amount,
        AccountJournalEntryType type,
        Currency currency
    );
    void deleteById(ulong id);
    void deleteByAccountIdAndTransactionId(ulong accountId, ulong transactionId);
    AccountJournalEntry[] findAllBetween(SysTime startIncl, SysTime endIncl, ulong accountId);
}

interface AccountValueRecordRepository {
    Optional!AccountValueRecord findById(ulong accountId, ulong id);
    AccountValueRecord insert(
        SysTime timestamp,
        ulong accountId,
        AccountValueRecordType type,
        long value,
        Currency currency
    );
    void linkAttachment(ulong valueRecordId, ulong attachmentId);
    Page!AccountValueRecord findAllByAccountId(ulong accountId, in PageRequest pr);
    void deleteById(ulong accountId, ulong id);
    Optional!AccountValueRecord findNearestByAccountIdBefore(ulong accountId, SysTime timestamp);
    Optional!AccountValueRecord findNearestByAccountIdAfter(ulong accountId, SysTime timestamp);
}

version(unittest) {
    class TestAccountRepositoryStub : AccountRepository {
        Optional!Account findById(ulong id) {
            throw new Exception("Not implemented");
        }
        bool existsById(ulong id) {
            throw new Exception("Not implemented");
        }
        Account insert(AccountType type, string numberSuffix, string name, Currency currency, string description) {
            throw new Exception("Not implemented");
        }
        void setArchived(ulong id, bool archived) {
            throw new Exception("Not implemented");
        }
        Account update(ulong id, in Account newData) {
            throw new Exception("Not implemented");
        }
        void deleteById(ulong id) {
            throw new Exception("Not implemented");
        }
        Account[] findAll() {
            throw new Exception("Not implemented");
        }
        AccountCreditCardProperties getCreditCardProperties(ulong id) {
            throw new Exception("Not implemented");
        }
        void setCreditCardProperties(ulong id, in AccountCreditCardProperties props) {
            throw new Exception("Not implemented");
        }
        Page!AccountHistoryItemResponse getHistory(ulong accountId, in PageRequest pagination) {
            throw new Exception("Not implemented");
        }
    }

    class TestAccountJournalEntryRepositoryStub : AccountJournalEntryRepository {
        Optional!AccountJournalEntry findById(ulong id) {
            throw new Exception("Not implemented");
        }
        AccountJournalEntry insert(
            SysTime timestamp,
            ulong accountId,
            ulong transactionId,
            ulong amount,
            AccountJournalEntryType type,
            Currency currency
        ) {
            throw new Exception("Not implemented");
        }
        void deleteById(ulong id) {

        }
        void deleteByAccountIdAndTransactionId(ulong accountId, ulong transactionId) {
            throw new Exception("Not implemented");
        }
        AccountJournalEntry[] findAllBetween(SysTime startIncl, SysTime endIncl, ulong accountId) {
            throw new Exception("Not implemented");
        }
    }

    class TestAccountValueRecordRepositoryStub : AccountValueRecordRepository {
        Optional!AccountValueRecord findById(ulong accountId, ulong id) {
            throw new Exception("Not implemented");
        }
        AccountValueRecord insert(
            SysTime timestamp,
            ulong accountId,
            AccountValueRecordType type,
            long value,
            Currency currency
        ) {
            throw new Exception("Not implemented");
        }
        void deleteById(ulong id) {
            throw new Exception("Not implemented");
        }
        Optional!AccountValueRecord findNearestByAccountIdBefore(ulong accountId, SysTime timestamp) {
            throw new Exception("Not implemented");
        }
        Optional!AccountValueRecord findNearestByAccountIdAfter(ulong accountId, SysTime timestamp) {
            throw new Exception("Not implemented");
        }
        void linkAttachment(ulong valueRecordId, ulong attachmentId) {
            throw new Exception("Not implemented");
        }
        Page!AccountValueRecord findAllByAccountId(ulong accountId, in PageRequest pr) {
            throw new Exception("Not implemented");
        }
        void deleteById(ulong accountId, ulong id) {
            throw new Exception("Not implemented");
        }
    }
}
