import type { AccountAccountType, AccountClassification, AccountStatus } from "../generated/enums";
import type { DB } from "../generated/kysely-tailordb";
import {
  ok,
  type ReadonlyDB,
  type PaginationInput,
  buildPaginatedResult,
  DEFAULT_PAGE_SIZE,
} from "@tailor-platform/erp-kit/module";

type AccountOrderByField =
  | "code"
  | "name"
  | "accountType"
  | "classification"
  | "status"
  | "createdAt";

export interface ListAccountsInput extends PaginationInput<AccountOrderByField> {
  chartOfAccountsId: string;
  accountType?: string;
  classification?: string;
  accountGroupId?: string;
  tags?: string[];
  status?: string;
  currencyRestriction?: string;
}

/**
 * Function: listAccounts
 *
 * Lists accounts within a CoA with optional filters for type, classification,
 * group, tags, status, and currency restriction.
 */
export async function run(db: ReadonlyDB<DB>, input: ListAccountsInput) {
  const limit = input.limit ?? DEFAULT_PAGE_SIZE;
  const offset = input.offset ?? 0;
  const orderBy = input.orderBy ?? "code";
  const orderDirection = input.orderDirection ?? "asc";

  let query = db
    .selectFrom("Account")
    .selectAll()
    .where("chartOfAccountsId", "=", input.chartOfAccountsId);

  if (input.accountType) {
    query = query.where("accountType", "=", input.accountType as AccountAccountType);
  }
  if (input.classification) {
    query = query.where("classification", "=", input.classification as AccountClassification);
  }
  if (input.accountGroupId) {
    query = query.where("accountGroupId", "=", input.accountGroupId);
  }
  if (input.status) {
    query = query.where("status", "=", input.status as AccountStatus);
  }
  if (input.currencyRestriction) {
    query = query.where("currencyRestriction", "=", input.currencyRestriction);
  }
  if (input.tags && input.tags.length > 0) {
    query = query.where((eb) => {
      const conditions = input.tags!.map((tag) =>
        eb.or([
          eb("tags", "=", tag),
          eb("tags", "like", `${tag},%`),
          eb("tags", "like", `%,${tag}`),
          eb("tags", "like", `%,${tag},%`),
        ]),
      );
      return eb.or(conditions);
    });
  }

  const accounts = await query
    .orderBy(orderBy, orderDirection)
    .limit(limit + 1)
    .offset(offset)
    .execute();

  return ok(buildPaginatedResult(accounts, limit));
}
