export type FlatAddress = {
  uprn: string;
  address: string;
  propertyType?: PropertyType;
  builtForm?: BuiltForm;
};

export type PropertyType = "House" | "Flat" | "Maisonette" | "Bungalow";
export type BuiltForm =
  | "Detached"
  | "Semi-Detached"
  | "Mid-Terrace"
  | "End-Terrace"
  | "Enclosed End-Terrace"
  | "Enclosed Mid-Terrace";

export function mapOsClassToProperty(classification?: string): {
  propertyType?: PropertyType;
  builtForm?: BuiltForm;
} {
  if (!classification) return {};

  const code = classification.toUpperCase();

  if (code.startsWith("RD02")) {
    return { propertyType: "House", builtForm: "Detached" };
  }
  if (code.startsWith("RD03")) {
    return { propertyType: "House", builtForm: "Semi-Detached" };
  }
  if (code.startsWith("RD04")) {
    return { propertyType: "House", builtForm: "Mid-Terrace" };
  }
  if (code.startsWith("RD06")) {
    return { propertyType: "Flat" };
  }

  return {};
}

export function inferPropertyFromAddress(address: string): {
  propertyType?: PropertyType;
  builtForm?: BuiltForm;
} {
  const addr = address.toLowerCase();

  // Detect explicit mentions
  if (addr.includes("bungalow")) return { propertyType: "Bungalow" };
  if (addr.includes("maisonette")) return { propertyType: "Maisonette" };
  if (addr.includes("flat") || addr.includes("apartment"))
    return { propertyType: "Flat" };

  // If it says "terrace" in address, but no RD code, assume terraced house
  if (addr.includes("terrace") || addr.includes("terraced"))
    return { propertyType: "House", builtForm: "Mid-Terrace" };

  // Minimal fallback if text only shows 'house' or street number
  if (addr.match(/\d+\s+[a-z]/)) return { propertyType: "House" };

  return {};
}

export function mapOsPlacesToFlat(
  results?: Array<{ DPA?: any; LPI?: any }>
): FlatAddress[] {
  if (!results?.length) return [];

  const items = results
    .map((r) => r.DPA ?? r.LPI)
    .filter(Boolean)
    .map((rec: any) => {
      const classification = rec.CLASSIFICATION_CODE as string | undefined;
      const base = mapOsClassToProperty(classification);
      const textBased = inferPropertyFromAddress(String(rec.ADDRESS ?? ""));

      // Merge — classification has priority, but text fills in missing gaps
      const propertyType = base.propertyType ?? textBased.propertyType;
      const builtForm = base.builtForm ?? textBased.builtForm;

      return {
        uprn: String(rec.UPRN ?? ""),
        address: String(rec.ADDRESS ?? ""),
        propertyType,
        builtForm,
      };
    })
    .filter((x) => x.uprn && x.address);

  // De-duplicate by UPRN
  const seen = new Set<string>();
  const deduped: FlatAddress[] = [];
  for (const it of items) {
    if (!seen.has(it.uprn)) {
      seen.add(it.uprn);
      deduped.push(it);
    }
  }
  return deduped;
}
