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

export const neonPricingDefaults = [
  { code: "base.fabrication", label: "Forfait fabrication atelier", section: "Base générale", value: 9500, unit: "cents", position: 10 },
  { code: "base.transformer", label: "Transformateur de base", section: "Base générale", value: 6900, unit: "cents", position: 20 },
  { code: "transformer.extra_m", label: "Transformateur au-delà de 4 m", section: "Base générale", value: 700, unit: "cents_per_m", position: 30 },
  { code: "tube.6", label: "Néon Flex 6 mm", section: "Tube lumineux", value: 6200, unit: "cents_per_m", position: 40 },
  { code: "tube.8", label: "Néon Flex 8 mm", section: "Tube lumineux", value: 7200, unit: "cents_per_m", position: 50 },
  { code: "tube.10", label: "Néon Flex 10 mm", section: "Tube lumineux", value: 8300, unit: "cents_per_m", position: 60 },
  { code: "support.contour.base", label: "Plexiglas découpé à la forme", section: "Supports", value: 12500, unit: "cents", position: 70 },
  { code: "support.rectangle.base", label: "Plaque plexiglas rectangulaire", section: "Supports", value: 17500, unit: "cents", position: 80 },
  { code: "support.none.base", label: "Sans plaque apparente", section: "Supports", value: 6500, unit: "cents", position: 90 },
  { code: "support.contour.area", label: "Surface plexiglas découpée", section: "Supports", value: 11500, unit: "cents_per_m2", position: 100 },
  { code: "support.rectangle.area", label: "Surface plaque rectangulaire", section: "Supports", value: 17500, unit: "cents_per_m2", position: 110 },
  { code: "installation.entretoises", label: "Entretoises murales", section: "Fixations", value: 6500, unit: "cents", position: 120 },
  { code: "installation.suspendu", label: "Fixation suspendue", section: "Fixations", value: 8500, unit: "cents", position: 130 },
  { code: "installation.vitrine", label: "Fixation vitrine", section: "Fixations", value: 4500, unit: "cents", position: 140 },
  { code: "installation.direct", label: "Pose directe", section: "Fixations", value: 2500, unit: "cents", position: 150 },
  { code: "font.pacifico", label: "Signature", section: "Écritures", value: 11800, unit: "factor_bp", position: 160 },
  { code: "font.dancing", label: "Dancing", section: "Écritures", value: 10800, unit: "factor_bp", position: 170 },
  { code: "font.allura", label: "Allura", section: "Écritures", value: 10200, unit: "factor_bp", position: 180 },
  { code: "font.sacramento", label: "Sacramento", section: "Écritures", value: 9800, unit: "factor_bp", position: 190 },
  { code: "font.satisfy", label: "Satisfy", section: "Écritures", value: 10800, unit: "factor_bp", position: 200 },
  { code: "discount.quantity_2", label: "Remise dès 2 exemplaires", section: "Remises", value: 300, unit: "discount_bp", position: 210 },
  { code: "discount.quantity_5", label: "Remise dès 5 exemplaires", section: "Remises", value: 600, unit: "discount_bp", position: 220 },
  { code: "discount.quantity_10", label: "Remise dès 10 exemplaires", section: "Remises", value: 1200, unit: "discount_bp", position: 230 },
  { code: "discount.professional", label: "Remise compte revendeur", section: "Remises", value: 1800, unit: "discount_bp", position: 240 },
] as const;

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

export async function ensureNeonPricingRules() {
  await ensureSchema();
  seeded ??= env.DB.batch(neonPricingDefaults.map((rule) =>
    env.DB.prepare(`INSERT OR IGNORE INTO neon_pricing_rules
      (code, label, section, value, unit, position, version, updated_at)
      VALUES (?, ?, ?, ?, ?, ?, 1, ?)`)
      .bind(rule.code, rule.label, rule.section, rule.value, rule.unit, rule.position, Date.now()),
  )).then(() => undefined);
  await seeded;
}

export async function calculateNeonPrice(input: {
  text: string;
  font: string;
  fontFactorBp?: number;
  widthCm: number;
  heightCm: number;
  tubeMm: number;
  support: string;
  installation: string;
  quantity: number;
  isProfessional: boolean;
}) {
  await ensureNeonPricingRules();
  const rows = await env.DB.prepare("SELECT code, value, version FROM neon_pricing_rules").all<{
    code: string; value: number; version: number;
  }>();
  const rules = new Map(rows.results.map((row) => [row.code, row.value]));
  const rule = (code: string) => {
    const value = rules.get(code);
    if (typeof value !== "number") throw new Error(`Règle néon manquante : ${code}`);
    return value;
  };

  const characters = Array.from(input.text).filter((character) => character.trim()).length;
  if (!characters) throw new Error("Configuration néon invalide");

  const fontFactor = (rules.get(`font.${input.font}`) ?? input.fontFactorBp ?? 10000) / 10000;
  const estimatedTubeLengthM = Math.max(1.2, characters * input.heightCm / 100 * 2.25 * fontFactor);
  const tubeRateCents = rule(`tube.${input.tubeMm}`);
  const supportAreaM2 = input.widthCm / 100 * input.heightCm / 100;
  const supportCents = rule(`support.${input.support}.base`)
    + (input.support === "none" ? 0 : supportAreaM2 * rule(`support.${input.support}.area`));
  const transformerCents = rule("base.transformer")
    + Math.max(0, estimatedTubeLengthM - 4) * rule("transformer.extra_m");
  const unitAmountCents = rule("base.fabrication") + estimatedTubeLengthM * tubeRateCents + supportCents
    + rule(`installation.${input.installation}`) + transformerCents;

  const quantityDiscountBp = input.quantity >= 10 ? rule("discount.quantity_10")
    : input.quantity >= 5 ? rule("discount.quantity_5")
      : input.quantity >= 2 ? rule("discount.quantity_2") : 0;
  const professionalDiscountBp = input.isProfessional ? rule("discount.professional") : 0;
  const amountCents = unitAmountCents * input.quantity
    * (10000 - quantityDiscountBp) / 10000 * (10000 - professionalDiscountBp) / 10000;

  return {
    amountCents: Math.round(amountCents / 100) * 100,
    unitAmountCents: Math.round(unitAmountCents / 100) * 100,
    estimatedTubeLengthM,
    supportAreaM2,
    version: Math.max(...rows.results.map((row) => row.version), 1),
    professionalDiscountPercent: rule("discount.professional") / 100,
    quantityDiscountPercent: quantityDiscountBp / 100,
  };
}
