import { env } from "@/lib/runtime-env";
import { ensureSchema } from "./ensure-schema";

const factors: Record<string, number> = {
  P01: 13500, P02: 12000, P03: 15200, P04: 14800, P05: 12400,
  P06: 14200, P07: 11600, P08: 13200, P09: 14400, P10: 13800,
  P11: 12800, P12: 11800, P13: 10800, P14: 13100, P15: 12200,
  P16: 12600, P17: 15600, P18: 14600, P19: 16200, P20: 15000,
};

let seeded: Promise<void> | null = null;

export async function ensurePricingProfiles() {
  await ensureSchema();
  seeded ??= env.DB.batch([
    ...Object.entries(factors).map(([code, factor]) =>
      env.DB.prepare(`INSERT OR IGNORE INTO pricing_profiles
        (code, factor_bp, base_price_cents, rate_per_cm_letter_cents, professional_discount_bp, price_mode, enabled, version, updated_at)
        VALUES (?, ?, 22000, 450, 1800, 'estimate', 1, 1, ?)`)
        .bind(code, factor, Date.now())
    ),
    env.DB.prepare("UPDATE pricing_profiles SET base_price_cents = 22000, version = 3, updated_at = ? WHERE version < 3").bind(Date.now()),
  ]).then(() => undefined);
  await seeded;
}

export type PriceInput = {
  profileCode: string;
  signText: string;
  heightCm: number;
  widthCm: number;
  depthMm: number;
  mounting: string;
  isProfessional: boolean;
};

export async function calculatePrice(input: PriceInput) {
  await ensurePricingProfiles();
  const row = await env.DB.prepare(`SELECT factor_bp, base_price_cents, rate_per_cm_letter_cents, professional_discount_bp,
    price_mode, enabled, version FROM pricing_profiles WHERE code = ?`).bind(input.profileCode).first<{
      factor_bp: number; base_price_cents: number; rate_per_cm_letter_cents: number; professional_discount_bp: number;
      price_mode: string; enabled: number; version: number;
    }>();
  if (!row || !row.enabled) throw new Error("Profil indisponible");

  const characters = Math.max(Array.from(input.signText).filter((character) => /[\p{L}\p{N}]/u.test(character)).length, 1);
  const mountingBp = input.mounting === "rail" ? 10800 : input.mounting === "entretoises" ? 10500 : 10000;
  const letterProduction = input.heightCm * characters * row.rate_per_cm_letter_cents;
  const depthSurcharge = Math.max(input.depthMm - 60, 0) * characters * 35;
  const subtotal = Math.max(row.base_price_cents, letterProduction + depthSurcharge);
  let amount = subtotal * row.factor_bp / 10000 * mountingBp / 10000;
  const mountingSurchargeCents = input.mounting === "dibond" ? 25000 : 0;
  amount += mountingSurchargeCents;
  if (input.isProfessional) amount *= (10000 - row.professional_discount_bp) / 10000;
  const mode = input.widthCm > 400 ? "quote" : row.price_mode;

  return {
    amountCents: Math.round(amount / 1000) * 1000,
    mode,
    version: row.version,
    letterCount: characters,
    heightCm: input.heightCm,
    ratePerCmLetterCents: row.rate_per_cm_letter_cents,
    mountingSurchargeCents,
    professionalDiscountPercent: row.professional_discount_bp / 100,
  };
}
