module transaction.data;

import handy_http_primitives : Optional, StringMultiValueMap;
import std.datetime;

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

interface TransactionVendorRepository {
    Optional!TransactionVendor findById(ulong id);
    TransactionVendor[] findAll();
    bool existsByName(string name);
    bool existsById(ulong id);
    TransactionVendor insert(string name, string description);
    void deleteById(ulong id);
    TransactionVendor updateById(ulong id, string name, string description);
}

interface TransactionCategoryRepository {
    Optional!TransactionCategory findById(ulong id);
    Optional!TransactionCategory findByName(string name);
    bool existsById(ulong id);
    bool existsByName(string name);
    TransactionCategory[] findAll();
    TransactionCategory[] findAllByParentId(Optional!ulong parentId);
    TransactionCategory insert(Optional!ulong parentId, string name, string description, string color);
    void deleteById(ulong id);
    TransactionCategory updateById(ulong id, string name, string description, string color, Optional!ulong parentId);
    TransactionCategoryBalance[] getBalance(
        ulong id,
        bool includeChildren,
        Optional!SysTime afterTimestamp,
        Optional!SysTime beforeTimestamp
    );
}

// TODO: Migrate into transaction repo, similar to drafts!
interface TransactionTagRepository {
    string[] findAllByTransactionId(ulong transactionId);
    void updateTags(ulong transactionId, in string[] tags);
    string[] findAll();
}

interface TransactionRepository {
    Page!TransactionsListItem findAll(in PageRequest pr);
    Page!TransactionsListItem search(in PageRequest pr, in StringMultiValueMap searchParams);
    AggregateTransactionData getAggregateData(in StringMultiValueMap searchParams);
    Optional!TransactionDetail findById(ulong id);
    TransactionDetail insert(in AddTransactionPayload data);
    void linkAttachment(ulong transactionId, ulong attachmentId);
    TransactionDetail update(ulong transactionId, in AddTransactionPayload data);
    void deleteById(ulong id);
}

interface TransactionDraftRepository {
    Page!TransactionDraftListItem findAllDrafts(in PageRequest pr);
    Page!TransactionDraftListItem findAllTemplates(in PageRequest pr);
    Page!TransactionDraftListItem findAll(in PageRequest pr);
    Optional!TransactionDraftResponse findById(ulong id);
    TransactionDraftResponse insert(in TransactionDraftPayload data);
    void linkAttachment(ulong draftId, ulong attachmentId);
    TransactionDraftResponse update(ulong draftId, in TransactionDraftPayload data);
    void deleteById(ulong id);

    void updateTags(ulong draftId, in string[] tags);
    string[] findAllTags();
}

interface RecurringTransactionRepository {
    Page!RecurringTransactionResponse findAll(in PageRequest pr);
    RecurringTransactionResponse[] findAllByDraftId(ulong draftId);
    Optional!RecurringTransactionResponse findById(ulong id);
    RecurringTransactionResponse insert(in RecurringTransactionPayload data);
    void deleteById(ulong id);
    void deleteAllByDraftId(ulong draftId);

    void addToQueue(ulong id, string timestamp);
    Optional!string findInQueue(ulong id);
    void removeFromQueue(ulong id);
}
