"use client"

import {
  getProvinces,
  getCitiesByProvinceId,
  getDistrictsByCityId,
  getSubdistrictsByDistrictId,
} from "@lib/data/rajaongkir"
import {
  RajaOngkirProvince,
  RajaOngkirCity,
  RajaOngkirDistrict,
  RajaOngkirSubdistrict,
} from "@lib/data/rajaongkir-constants"
import NativeSelect from "@modules/common/components/native-select"
import { useEffect, useRef, useState } from "react"

type Props = {
  onSelect: (data: {
    subdistrict_id: number
    province_display: string
    province: string
    city: string
    district: string
    subdistrict: string
    postal_code: string
  }) => void
  selectedProvince?: string
  selectedCity?: string
  selectedDistrict?: string
  selectedSubdistrict?: string
}

function matchName(items: { id: number; name: string }[], name: string) {
  if (!name) return null
  const lower = name.toLowerCase()
  return (
    items.find(
      (item) =>
        item.name.toLowerCase() === lower ||
        item.name.toLowerCase().includes(lower) ||
        lower.includes(item.name.toLowerCase())
    ) || null
  )
}

const RajaOngkirAddressSelector = ({
  onSelect,
  selectedProvince,
  selectedCity,
  selectedDistrict,
  selectedSubdistrict,
}: Props) => {
  const [provinces, setProvinces] = useState<RajaOngkirProvince[]>([])
  const [provinceId, setProvinceId] = useState<number | null>(null)
  const [provinceName, setProvinceName] = useState("")

  const [cities, setCities] = useState<RajaOngkirCity[]>([])
  const [cityId, setCityId] = useState<number | null>(null)
  const [cityName, setCityName] = useState("")

  const [districts, setDistricts] = useState<RajaOngkirDistrict[]>([])
  const [districtId, setDistrictId] = useState<number | null>(null)
  const [districtName, setDistrictName] = useState("")

  const [subdistricts, setSubdistricts] = useState<RajaOngkirSubdistrict[]>([])
  const [subdistrictName, setSubdistrictName] = useState("")

  const [loadingCities, setLoadingCities] = useState(false)
  const [loadingDistricts, setLoadingDistricts] = useState(false)
  const [loadingSubdistricts, setLoadingSubdistricts] = useState(false)

  const didInit = useRef(false)

  useEffect(() => {
    getProvinces().then((data) => {
      setProvinces(data)
      if (!didInit.current && selectedProvince) {
        didInit.current = true
        const matched = matchName(data, selectedProvince)
        if (matched) {
          setProvinceId(matched.id)
          setProvinceName(matched.name)
        }
      }
    })
  }, [])

  useEffect(() => {
    if (!provinceId) return
    setLoadingCities(true)
    setCityId(null)
    setCityName("")
    setDistricts([])
    setDistrictId(null)
    setDistrictName("")
    setSubdistricts([])
    setSubdistrictName("")

    getCitiesByProvinceId(provinceId).then((data) => {
      setCities(data)
      setLoadingCities(false)
      if (selectedCity) {
        const matched = matchName(data, selectedCity)
        if (matched) {
          setCityId(matched.id)
          setCityName(matched.name)
        }
      }
    })
  }, [provinceId])

  useEffect(() => {
    if (!cityId) return
    setLoadingDistricts(true)
    setDistrictId(null)
    setDistrictName("")
    setSubdistricts([])
    setSubdistrictName("")

    getDistrictsByCityId(cityId).then((data) => {
      setDistricts(data)
      setLoadingDistricts(false)
      if (selectedDistrict) {
        const matched = matchName(data, selectedDistrict)
        if (matched) {
          setDistrictId(matched.id)
          setDistrictName(matched.name)
        }
      }
    })
  }, [cityId])

  useEffect(() => {
    if (!districtId) return
    setLoadingSubdistricts(true)
    setSubdistrictName("")

    getSubdistrictsByDistrictId(districtId).then((data) => {
      setSubdistricts(data)
      setLoadingSubdistricts(false)
      if (selectedSubdistrict) {
        const matched = matchName(data, selectedSubdistrict)
        if (matched) {
          setSubdistrictName(matched.name)
        }
      }
    })
  }, [districtId])

  const handleProvinceChange = (value: string) => {
    const selected = provinces.find(
      (p) => p.name === value || p.name.toLowerCase() === value.toLowerCase()
    )
    if (selected) {
      setProvinceId(selected.id)
      setProvinceName(selected.name)
    } else {
      setProvinceId(null)
      setProvinceName(value)
    }
    setCityId(null)
    setCityName("")
    setDistrictId(null)
    setDistrictName("")
    setSubdistrictName("")
    setCities([])
    setDistricts([])
    setSubdistricts([])
  }

  const handleCityChange = (value: string) => {
    const selected = cities.find(
      (c) => c.name === value || c.name.toLowerCase() === value.toLowerCase()
    )
    if (selected) {
      setCityId(selected.id)
      setCityName(selected.name)
    } else {
      setCityId(null)
      setCityName(value)
    }
    setDistrictId(null)
    setDistrictName("")
    setSubdistrictName("")
    setDistricts([])
    setSubdistricts([])
  }

  const handleDistrictChange = (value: string) => {
    const selected = districts.find(
      (d) => d.name === value || d.name.toLowerCase() === value.toLowerCase()
    )
    if (selected) {
      setDistrictId(selected.id)
      setDistrictName(selected.name)
    } else {
      setDistrictId(null)
      setDistrictName(value)
    }
    setSubdistrictName("")
    setSubdistricts([])
  }

  const handleSubdistrictChange = (value: string) => {
    if (!value) return

    const selected = subdistricts.find(
      (s) => s.name === value || s.name.toLowerCase() === value.toLowerCase()
    )
    if (selected) {
      setSubdistrictName(selected.name)
      onSelect({
        subdistrict_id: selected.id,
        province_display: provinceName,
        province: provinceName,
        city: cityName,
        district: districtName,
        subdistrict: selected.name,
        postal_code: selected.zip_code || "",
      })
    }
  }

  const displayProvince = provinceName || ""
  const displayCity = cityName || ""
  const displayDistrict = districtName || ""

  return (
    <div className="grid grid-cols-2 gap-4">
      <div>
        <label className="block text-sm font-medium mb-1">Province</label>
        <NativeSelect
          name="rajaongkir_province"
          value={displayProvince}
          onChange={(e) => handleProvinceChange(e.target.value)}
          placeholder="Select province"
        >
          {provinces.map((p) => (
            <option key={p.id} value={p.name}>
              {p.name}
            </option>
          ))}
        </NativeSelect>
      </div>

      <div>
        <label className="block text-sm font-medium mb-1">City</label>
        <NativeSelect
          name="rajaongkir_city"
          value={displayCity}
          onChange={(e) => handleCityChange(e.target.value)}
          placeholder={loadingCities ? "Loading..." : "Select city"}
          disabled={!provinceId || loadingCities}
        >
          {cities.map((c) => (
            <option key={c.id} value={c.name}>
              {c.name}
            </option>
          ))}
        </NativeSelect>
      </div>

      <div>
        <label className="block text-sm font-medium mb-1">District</label>
        <NativeSelect
          name="rajaongkir_district"
          value={displayDistrict}
          onChange={(e) => handleDistrictChange(e.target.value)}
          placeholder={loadingDistricts ? "Loading..." : "Select district"}
          disabled={!cityId || loadingDistricts}
        >
          {districts.map((d) => (
            <option key={d.id} value={d.name}>
              {d.name}
            </option>
          ))}
        </NativeSelect>
      </div>

      <div>
        <label className="block text-sm font-medium mb-1">Subdistrict</label>
        <NativeSelect
          name="rajaongkir_subdistrict"
          value={subdistrictName}
          onChange={(e) => handleSubdistrictChange(e.target.value)}
          placeholder={loadingSubdistricts ? "Loading..." : "Select subdistrict"}
          disabled={!districtId || loadingSubdistricts}
        >
          {subdistricts.map((s) => (
            <option key={s.id} value={s.name}>
              {s.name}
            </option>
          ))}
        </NativeSelect>
      </div>
    </div>
  )
}

export default RajaOngkirAddressSelector
