import "server-only";

import { Query } from "node-appwrite";

import { canAccessRow } from "./scope-permissions";
import { createAdminClient } from "./server";
import {
  DATABASE_ID,
  TABLES,
  type BankLoan,
  type LoanInstallment,
} from "./schema";

export async function listLoans(
  tenantId: string,
  currentUserId?: string,
): Promise<BankLoan[]> {
  try {
    const { tablesDB } = createAdminClient();
    const result = await tablesDB.listRows({
      databaseId: DATABASE_ID,
      tableId: TABLES.bankLoans,
      queries: [
        Query.equal("tenantId", tenantId),
        Query.orderDesc("$createdAt"),
        Query.limit(200),
      ],
    });
    const rows = result.rows as unknown as BankLoan[];
    if (!currentUserId) return rows;
    return rows.filter((r) => canAccessRow(r, currentUserId));
  } catch {
    return [];
  }
}

export async function listInstallmentsForLoan(
  tenantId: string,
  loanId: string,
): Promise<LoanInstallment[]> {
  try {
    const { tablesDB } = createAdminClient();
    const result = await tablesDB.listRows({
      databaseId: DATABASE_ID,
      tableId: TABLES.loanInstallments,
      queries: [
        Query.equal("tenantId", tenantId),
        Query.equal("loanId", loanId),
        Query.orderAsc("installmentNo"),
        Query.limit(500),
      ],
    });
    return result.rows as unknown as LoanInstallment[];
  } catch {
    return [];
  }
}

/**
 * Pulls all installments and filters to those whose parent loan is visible to the user.
 */
export async function listAllInstallments(
  tenantId: string,
  currentUserId?: string,
): Promise<LoanInstallment[]> {
  try {
    const { tablesDB } = createAdminClient();
    const [allInst, allLoans] = await Promise.all([
      tablesDB.listRows({
        databaseId: DATABASE_ID,
        tableId: TABLES.loanInstallments,
        queries: [Query.equal("tenantId", tenantId), Query.limit(2000)],
      }),
      tablesDB.listRows({
        databaseId: DATABASE_ID,
        tableId: TABLES.bankLoans,
        queries: [Query.equal("tenantId", tenantId), Query.limit(500)],
      }),
    ]);
    const visibleLoanIds = new Set(
      (allLoans.rows as unknown as BankLoan[])
        .filter((l) => !currentUserId || canAccessRow(l, currentUserId))
        .map((l) => l.$id),
    );
    return (allInst.rows as unknown as LoanInstallment[]).filter((i) =>
      visibleLoanIds.has(i.loanId),
    );
  } catch {
    return [];
  }
}
