import "server-only";

import { Query } from "node-appwrite";

import {
  DATABASE_ID,
  TABLES,
  type ClinicPricing,
  type Prosthetic,
  type ProstheticType,
  type TenantSettings,
} from "./schema";
import { createAdminClient } from "./server";

export type JobPriceQuote = {
  amount: number;
  currency: string;
  source: "clinic_custom" | "clinic_discount" | "catalog";
  unitPrice: number;
  /** Lab's listed catalog price before any clinic override, if a catalog row exists. */
  catalogUnitPrice?: number;
  /** catalogUnitPrice × teethCount; useful for showing the clinic the saving. */
  catalogTotal?: number;
  /** catalogTotal - amount; positive when the clinic is getting a discount. */
  savings?: number;
  /** teethCount passed in, echoed back so the client can format breakdowns. */
  teethCount: number;
  discountPercent?: number;
};

/**
 * Price an explicit catalog row for a clinic. Use this when the clinic picked
 * a specific product from the lab catalog — the catalog row is the source of
 * truth for the unit price, clinic_pricing only adds an override.
 */
export async function calculateJobPriceForProsthetic(opts: {
  prosthetic: Prosthetic;
  clinicTenantId: string;
  teethCount: number;
}): Promise<JobPriceQuote | null> {
  if (opts.teethCount <= 0) return null;
  const { tablesDB } = createAdminClient();
  const [pricingRes, labSettingsRes] = await Promise.all([
    tablesDB.listRows({
      databaseId: DATABASE_ID,
      tableId: TABLES.clinicPricing,
      queries: [
        Query.equal("labTenantId", opts.prosthetic.tenantId),
        Query.equal("clinicTenantId", opts.clinicTenantId),
        Query.equal("prostheticType", opts.prosthetic.type),
        Query.limit(1),
      ],
    }),
    tablesDB.listRows({
      databaseId: DATABASE_ID,
      tableId: TABLES.tenantSettings,
      queries: [Query.equal("tenantId", opts.prosthetic.tenantId), Query.limit(1)],
    }),
  ]);
  const override = pricingRes.rows[0] as unknown as ClinicPricing | undefined;
  const labSettings = labSettingsRes.rows[0] as unknown as TenantSettings | undefined;
  const fallbackCurrency = labSettings?.defaultCurrency ?? "TRY";
  const catalogUnitPrice = opts.prosthetic.unitPrice;
  const catalogTotal = catalogUnitPrice * opts.teethCount;

  if (override?.customUnitPrice !== undefined && override.customUnitPrice !== null) {
    const unit = override.customUnitPrice;
    const amount = unit * opts.teethCount;
    return {
      amount,
      currency: override.currency || opts.prosthetic.currency || fallbackCurrency,
      source: "clinic_custom",
      unitPrice: unit,
      catalogUnitPrice,
      catalogTotal,
      savings: catalogTotal > amount ? catalogTotal - amount : undefined,
      teethCount: opts.teethCount,
    };
  }

  if (
    override?.discountPercent !== undefined &&
    override.discountPercent !== null &&
    override.discountPercent > 0
  ) {
    const discounted = catalogUnitPrice * (1 - override.discountPercent / 100);
    const amount = discounted * opts.teethCount;
    return {
      amount,
      currency: override.currency || opts.prosthetic.currency || fallbackCurrency,
      source: "clinic_discount",
      unitPrice: discounted,
      catalogUnitPrice,
      catalogTotal,
      savings: catalogTotal - amount,
      discountPercent: override.discountPercent,
      teethCount: opts.teethCount,
    };
  }

  return {
    amount: catalogTotal,
    currency: opts.prosthetic.currency || fallbackCurrency,
    source: "catalog",
    unitPrice: catalogUnitPrice,
    catalogUnitPrice,
    catalogTotal,
    teethCount: opts.teethCount,
  };
}

/**
 * Resolves the price a clinic should be charged for a job, given the lab's
 * catalog and any clinic-specific pricing overrides.
 *
 * Cascade (first match wins):
 *   1. clinic_pricing row for (lab, clinic, type) with customUnitPrice → use it
 *   2. clinic_pricing row with discountPercent → catalog unitPrice × (1 - d/100)
 *   3. lab's prosthetics catalog row matching `type` (not archived)
 *   4. nothing → returns null, the lab will need to set the price manually
 *
 * Currency precedence: clinic override → catalog → lab tenant default → "TRY".
 *
 * @param teethCount  multiplied with the resolved unit price
 */
export async function calculateJobPrice(opts: {
  labTenantId: string;
  clinicTenantId: string;
  prostheticType: ProstheticType;
  teethCount: number;
}): Promise<JobPriceQuote | null> {
  if (opts.teethCount <= 0) return null;
  const { tablesDB } = createAdminClient();

  const [pricingRes, catalogRes, labSettingsRes] = await Promise.all([
    tablesDB.listRows({
      databaseId: DATABASE_ID,
      tableId: TABLES.clinicPricing,
      queries: [
        Query.equal("labTenantId", opts.labTenantId),
        Query.equal("clinicTenantId", opts.clinicTenantId),
        Query.equal("prostheticType", opts.prostheticType),
        Query.limit(1),
      ],
    }),
    tablesDB.listRows({
      databaseId: DATABASE_ID,
      tableId: TABLES.prosthetics,
      queries: [
        Query.equal("tenantId", opts.labTenantId),
        Query.equal("type", opts.prostheticType),
        Query.notEqual("archived", true),
        Query.orderAsc("$createdAt"),
        Query.limit(1),
      ],
    }),
    tablesDB.listRows({
      databaseId: DATABASE_ID,
      tableId: TABLES.tenantSettings,
      queries: [Query.equal("tenantId", opts.labTenantId), Query.limit(1)],
    }),
  ]);

  const override = pricingRes.rows[0] as unknown as ClinicPricing | undefined;
  const catalog = catalogRes.rows[0] as unknown as Prosthetic | undefined;
  const labSettings = labSettingsRes.rows[0] as unknown as TenantSettings | undefined;

  const fallbackCurrency = labSettings?.defaultCurrency ?? "TRY";
  const catalogUnitPrice = catalog?.unitPrice;
  const catalogTotal =
    catalogUnitPrice !== undefined ? catalogUnitPrice * opts.teethCount : undefined;

  if (override?.customUnitPrice !== undefined && override.customUnitPrice !== null) {
    const unit = override.customUnitPrice;
    const amount = unit * opts.teethCount;
    return {
      amount,
      currency: override.currency || catalog?.currency || fallbackCurrency,
      source: "clinic_custom",
      unitPrice: unit,
      catalogUnitPrice,
      catalogTotal,
      savings:
        catalogTotal !== undefined && catalogTotal > amount
          ? catalogTotal - amount
          : undefined,
      teethCount: opts.teethCount,
    };
  }

  if (!catalog) return null;

  if (
    override?.discountPercent !== undefined &&
    override.discountPercent !== null &&
    override.discountPercent > 0
  ) {
    const discounted = catalog.unitPrice * (1 - override.discountPercent / 100);
    const amount = discounted * opts.teethCount;
    return {
      amount,
      currency: override.currency || catalog.currency || fallbackCurrency,
      source: "clinic_discount",
      unitPrice: discounted,
      catalogUnitPrice: catalog.unitPrice,
      catalogTotal,
      savings: catalogTotal !== undefined ? catalogTotal - amount : undefined,
      discountPercent: override.discountPercent,
      teethCount: opts.teethCount,
    };
  }

  return {
    amount: catalog.unitPrice * opts.teethCount,
    currency: catalog.currency || fallbackCurrency,
    source: "catalog",
    unitPrice: catalog.unitPrice,
    catalogUnitPrice: catalog.unitPrice,
    catalogTotal,
    teethCount: opts.teethCount,
  };
}
