import "server-only";

import { ID, Permission, Query, Role } from "node-appwrite";

import {
  DATABASE_ID,
  TABLES,
  type FinanceType,
  type Job,
} from "./schema";
import { createAdminClient } from "./server";

/**
 * Idempotent finance reconciliation for a job. Safe to call from every job
 * mutation that might land the job in `sent` or `delivered`. Memory rule
 * [[feedback_cross_entity_sync_helpers]]: never re-throw, best-effort, single
 * named function called from every write path.
 *
 * Two rows are created the first time a job becomes sent/delivered:
 *   - clinic side  → payable  (status: pending)
 *   - lab side     → receivable (status: pending)
 *
 * On `delivered`, pending rows can stay pending — actually settling them is
 * the user's job through the /finance UI (mark as paid). We just ensure both
 * rows exist.
 */
export async function syncFinanceForJob(job: Job): Promise<void> {
  try {
    if (!job.price || job.price <= 0) return;
    if (job.status !== "sent" && job.status !== "delivered") return;

    const { tablesDB } = createAdminClient();
    const currency = job.currency || "TRY";

    const sides: Array<{
      tenantId: string;
      counterpartTenantId: string;
      type: FinanceType;
    }> = [
      { tenantId: job.clinicTenantId, counterpartTenantId: job.labTenantId, type: "payable" },
      { tenantId: job.labTenantId, counterpartTenantId: job.clinicTenantId, type: "receivable" },
    ];

    for (const side of sides) {
      const existing = await tablesDB.listRows({
        databaseId: DATABASE_ID,
        tableId: TABLES.financeEntries,
        queries: [
          Query.equal("jobId", job.$id),
          Query.equal("tenantId", side.tenantId),
          Query.equal("type", side.type),
          Query.limit(1),
        ],
      });
      if (existing.total > 0) continue;

      await tablesDB.createRow(
        DATABASE_ID,
        TABLES.financeEntries,
        ID.unique(),
        {
          tenantId: side.tenantId,
          createdBy: job.createdBy,
          jobId: job.$id,
          counterpartTenantId: side.counterpartTenantId,
          type: side.type,
          amount: job.price,
          currency,
          status: "pending",
          date: new Date().toISOString(),
          description: `Hasta ${job.patientCode} — ${job.prostheticType.replace(/_/g, " ")}`.slice(0, 1000),
        },
        [
          Permission.read(Role.team(side.tenantId)),
          Permission.update(Role.team(side.tenantId, "owner")),
          Permission.update(Role.team(side.tenantId, "admin")),
          Permission.delete(Role.team(side.tenantId, "owner")),
        ],
      );
    }
  } catch (err) {
    // Best-effort: never block the parent job mutation.
    console.error("[syncFinanceForJob]", err);
  }
}
