import {
  PRICES,
  PUMP_TRUCK_FEES,
  CONSTRAINTS,
  COVERAGE_AREAS,
  FLOORING_TYPES,
  type FlooringType,
} from "./constants"

export interface CalculationInput {
  area: number // m²
  height: number // cm
  postalCode: string
  distance: number // km (round trip)
  // Optional components
  includeInsulation?: boolean // default: true
  includeFloorHeating?: boolean // default: true
  includeCompound?: boolean // default: true
  flooringType?: FlooringType // default: KLINKER
}

export interface CalculationDetails {
  // Input values
  area: number
  height: number
  postalCode: string
  distance: number

  // Optional component selections
  includeInsulation: boolean
  includeFloorHeating: boolean
  includeCompound: boolean
  flooringType: FlooringType

  // Calculated values
  insulationThickness: number // cm
  insulationVolume: number // m³
  compoundWeight: number // kg

  // Component prices
  insulation: number
  floorHeating: number
  syntheticNet: number
  selfLevelingCompound: number
  pumpTruckFee: number
  startFee: number

  // Subtotals
  subtotal: number
  coveringFee: number
  wasteFee: number
  totalFees: number

  // Transport
  transport: number
  bridgeFee: number

  // Totals
  totalExclVat: number
  vat: number
  totalInclVat: number
}

export function calculateInsulation(
  area: number,
  height: number
): {
  thickness: number
  volume: number
  volumePrice: number
  baseLabor: number
  price: number
} {
  const thickness = Math.max(0, height - CONSTRAINTS.CONCRETE_THICKNESS)
  const volume = area * (thickness / 100)

  // Volume-based cost (materials + labor per m³)
  const volumePrice = thickness > 0 ? volume * PRICES.INSULATION_TOTAL_PER_M3 : 0

  // Base labor cost (always applied per m² when insulation is included)
  const baseLabor = area * PRICES.INSULATION_BASE_LABOR

  // Total insulation price
  const price = volumePrice + baseLabor

  return { thickness, volume, volumePrice, baseLabor, price }
}

export function calculatePumpTruckFee(weight: number): number {
  const tier = PUMP_TRUCK_FEES.find((tier) => weight > tier.minWeight)
  return tier?.fee ?? PUMP_TRUCK_FEES[PUMP_TRUCK_FEES.length - 1].fee
}

export function getBridgeFee(postalCode: string): number {
  const postalNumber = parseInt(postalCode)

  for (const area of Object.values(COVERAGE_AREAS)) {
    if (postalNumber >= area.start && postalNumber <= area.end) {
      return area.bridgeFee
    }
  }

  return 0
}

export function calculatePrice(input: CalculationInput): CalculationDetails {
  const {
    area,
    height,
    postalCode,
    distance,
    includeInsulation = true,
    includeFloorHeating = true,
    includeCompound = true,
    flooringType = "STANDARD",
  } = input

  // Step 1: Calculate derived values
  const insulation = calculateInsulation(area, height)
  const compoundWeight = includeCompound ? area * PRICES.COMPOUND_WEIGHT_PER_M2 : 0

  // Get flooring type multiplier
  const flooringConfig = FLOORING_TYPES[flooringType]
  const compoundMultiplier = flooringConfig?.compoundMultiplier ?? 1.0

  // Step 2: Calculate components (only if included)
  const insulationPrice = includeInsulation ? insulation.price : 0
  const floorHeating = includeFloorHeating ? area * PRICES.FLOOR_HEATING_TOTAL : 0
  const syntheticNet = includeFloorHeating ? area * PRICES.SYNTHETIC_NET_TOTAL : 0 // Net only with heating
  const selfLevelingCompound = includeCompound
    ? area * PRICES.SELF_LEVELING_COMPOUND * compoundMultiplier
    : 0
  const pumpTruckFee = includeCompound ? calculatePumpTruckFee(compoundWeight) : 0
  const startFee = PRICES.START_FEE

  // Step 3: Calculate subtotal
  const subtotal =
    insulationPrice + floorHeating + syntheticNet + selfLevelingCompound + pumpTruckFee + startFee

  // Step 4: Calculate percentage fees
  const coveringFee = subtotal * PRICES.COVERING_PERCENTAGE
  const wasteFee = subtotal * PRICES.WASTE_PERCENTAGE
  const totalFees = coveringFee + wasteFee

  // Step 5: Calculate transport
  const transport = distance * PRICES.TRANSPORT_PER_KM
  const bridgeFee = getBridgeFee(postalCode)

  // Step 6: Calculate totals
  const totalExclVat = subtotal + totalFees + transport + bridgeFee
  const vat = totalExclVat * PRICES.VAT
  const totalInclVat = totalExclVat * (1 + PRICES.VAT)

  return {
    // Input values
    area,
    height,
    postalCode,
    distance,

    // Optional component selections
    includeInsulation,
    includeFloorHeating,
    includeCompound,
    flooringType,

    // Calculated values
    insulationThickness: insulation.thickness,
    insulationVolume: insulation.volume,
    compoundWeight,

    // Component prices
    insulation: insulationPrice,
    floorHeating,
    syntheticNet,
    selfLevelingCompound,
    pumpTruckFee,
    startFee,

    // Subtotals
    subtotal,
    coveringFee,
    wasteFee,
    totalFees,

    // Transport
    transport,
    bridgeFee,

    // Totals
    totalExclVat,
    vat,
    totalInclVat,
  }
}

export function formatPrice(price: number): string {
  return new Intl.NumberFormat("da-DK", {
    style: "currency",
    currency: "DKK",
    minimumFractionDigits: 0,
    maximumFractionDigits: 0,
  }).format(price)
}

export function formatEstimate(price: number): string {
  // Round to nearest 500
  const rounded = Math.round(price / 500) * 500
  return `Ca. ${formatPrice(rounded)}`
}
