import "server-only";

import { Query } from "node-appwrite";

import { createAdminClient } from "./server";
import {
  DATABASE_ID,
  TABLES,
  type BankAccount,
  type FinanceEntry,
} from "./schema";

export async function listBankAccounts(tenantId: string): Promise<BankAccount[]> {
  try {
    const { tablesDB } = createAdminClient();
    const result = await tablesDB.listRows({
      databaseId: DATABASE_ID,
      tableId: TABLES.bankAccounts,
      queries: [
        Query.equal("tenantId", tenantId),
        Query.orderAsc("bankName"),
        Query.limit(200),
      ],
    });
    return result.rows as unknown as BankAccount[];
  } catch {
    return [];
  }
}

/**
 * Computes a current balance for each account: openingBalance + Σ(income/receivable) − Σ(expense/debt).
 */
export async function getBankAccountBalances(
  tenantId: string,
): Promise<Map<string, number>> {
  const balances = new Map<string, number>();
  try {
    const { tablesDB } = createAdminClient();
    const accounts = await tablesDB.listRows({
      databaseId: DATABASE_ID,
      tableId: TABLES.bankAccounts,
      queries: [Query.equal("tenantId", tenantId), Query.limit(200)],
    });
    for (const a of accounts.rows as unknown as BankAccount[]) {
      balances.set(a.$id, a.openingBalance ?? 0);
    }

    const entries = await tablesDB.listRows({
      databaseId: DATABASE_ID,
      tableId: TABLES.financeEntries,
      queries: [
        Query.equal("tenantId", tenantId),
        Query.isNotNull("bankAccountId"),
        Query.limit(5000),
      ],
    });
    for (const e of entries.rows as unknown as FinanceEntry[]) {
      if (!e.bankAccountId) continue;
      const cur = balances.get(e.bankAccountId);
      if (cur === undefined) continue;
      if (e.type === "income") balances.set(e.bankAccountId, cur + e.amount);
      else if (e.type === "expense") balances.set(e.bankAccountId, cur - e.amount);
      // debt/receivable don't affect cash balance
    }
  } catch {
    /* ignore */
  }
  return balances;
}

export async function listEntriesForAccount(
  tenantId: string,
  bankAccountId: string,
  limit = 25,
): Promise<FinanceEntry[]> {
  try {
    const { tablesDB } = createAdminClient();
    const result = await tablesDB.listRows({
      databaseId: DATABASE_ID,
      tableId: TABLES.financeEntries,
      queries: [
        Query.equal("tenantId", tenantId),
        Query.equal("bankAccountId", bankAccountId),
        Query.orderDesc("date"),
        Query.limit(limit),
      ],
    });
    return result.rows as unknown as FinanceEntry[];
  } catch {
    return [];
  }
}
