import type { NormalizedListing, RawListing } from "./contracts"

const normalizeText = (value?: string) =>
  value
    ?.normalize("NFD")
    .replace(/\p{Diacritic}/gu, "")
    .toUpperCase()
    .replace(/[^A-Z0-9]+/g, " ")
    .trim() ?? ""

const multiWordMakes = new Set(["LAND ROVER", "MERCEDES BENZ"])
const multiWordModels = new Set(["LAND CRUISER"])

const inferTransmission = (value?: string): NormalizedListing["transmission"] => {
  const text = normalizeText(value)

  if (text.includes("CVT")) return "CVT"
  if (text.includes("DCT") || text.includes("DOBLE EMBRAGUE")) return "DCT"
  if (text.includes("AT") || text.includes("AUT")) return "AUTOMATIC"
  if (text.includes("MT") || text.includes("MEC")) return "MANUAL"
  return "UNKNOWN"
}

const inferFuel = (value?: string): NormalizedListing["fuel"] => {
  const text = normalizeText(value)

  if (text.includes("DIESEL")) return "DIESEL"
  if (text.includes("HIBRID")) return "HYBRID"
  if (text.includes("ELECTR")) return "ELECTRIC"
  if (text.includes("BENC") || text.includes("GASOL")) return "GASOLINE"
  if (text.includes("GLP") || text.includes("GAS LICUADO")) return "LPG"
  return "UNKNOWN"
}

const parseTitle = (title: string) => {
  const fillerTokens = new Set(["NEW", "NUEVO", "NUEVA"])
  const tokens = normalizeText(title).split(" ").filter(Boolean)
  let offset = 0

  let make = tokens[offset] ?? ""

  if (tokens[offset + 1] && multiWordMakes.has(`${tokens[offset]} ${tokens[offset + 1]}`)) {
    make = `${tokens[offset]} ${tokens[offset + 1]}`
    offset += 1
  }

  offset += 1

  while (tokens[offset] && fillerTokens.has(tokens[offset])) {
    offset += 1
  }

  let model = tokens[offset] ?? ""

  if (tokens[offset + 1] && multiWordModels.has(`${tokens[offset]} ${tokens[offset + 1]}`)) {
    model = `${tokens[offset]} ${tokens[offset + 1]}`
    offset += 1
  }

  const rest = tokens.slice(offset + 1)

  return {
    make,
    model,
    version: rest.join(" ").trim() || undefined
  }
}

export function normalizeListing(input: RawListing): NormalizedListing {
  const parsedTitle = parseTitle(input.title)
  const transmission = inferTransmission(input.transmissionText ?? input.title)
  const fuel = inferFuel(input.fuelText)
  const normalizedLabel = [parsedTitle.make, parsedTitle.model, parsedTitle.version, input.year, transmission]
    .filter(Boolean)
    .join(" ")
    .trim()
  const comparisonKey = [parsedTitle.make, parsedTitle.model, parsedTitle.version, transmission]
    .filter(Boolean)
    .join("|")

  return {
    source: input.source,
    externalId: input.externalId,
    sourceUrl: input.url,
    title: input.title,
    make: parsedTitle.make,
    model: parsedTitle.model,
    version: parsedTitle.version,
    year: input.year,
    priceClp: input.priceClp,
    mileageKm: input.mileageKm,
    imageUrl: input.imageUrl,
    transmission,
    fuel,
    region: input.region,
    commune: input.commune,
    sellerName: input.sellerName,
    rawPayload: input.rawPayload,
    comparisonKey,
    normalizedLabel
  }
}
