import { syncFeatureMarkers } from './mapMarkerSync.js'

const ICON_SIZE = 28
const CONE_SIZE = 52
const ALPR_COLOR = '#ef4444'
const DEFAULT_FOV = 60

function escapeHtml(text) {
  const div = document.createElement('div')
  div.textContent = text
  return div.innerHTML
}

function conePath(fov) {
  const half = Math.min(Math.max(fov / 2, 10), 85)
  const cx = 26
  const cy = 26
  const r = 24
  const toRad = deg => ((deg - 90) * Math.PI) / 180
  const x1 = cx + r * Math.cos(toRad(-half))
  const y1 = cy + r * Math.sin(toRad(-half))
  const x2 = cx + r * Math.cos(toRad(half))
  const y2 = cy + r * Math.sin(toRad(half))
  return `M ${cx} ${cy} L ${x1} ${y1} A ${r} ${r} 0 0 1 ${x2} ${y2} Z`
}

function compassLabel(deg) {
  if (!Number.isFinite(deg)) return null
  const dirs = ['N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW']
  const idx = Math.round((((deg % 360) + 360) % 360) / 45) % 8
  return dirs[idx]
}

function wikidataLink(label, qid) {
  if (!qid) return escapeHtml(label)
  const id = escapeHtml(qid)
  return `<a href="https://www.wikidata.org/wiki/${id}" target="_blank" rel="noopener">${escapeHtml(label)}</a>`
}

function popupLine(parts) {
  const line = parts.filter(Boolean).join(' · ')
  return line ? `<div class="text-kestrel-muted text-xs mt-1">${line}</div>` : ''
}

function titleHtml(props) {
  if (props.name) return escapeHtml(props.name)
  if (props.model) {
    const mfr = props.manufacturer ? escapeHtml(props.manufacturer) : null
    return mfr ? `${mfr} <span class="text-kestrel-accent">${escapeHtml(props.model)}</span>` : escapeHtml(props.model)
  }
  const makeModel = [props.manufacturer, props.model].filter(Boolean).join(' ')
  if (makeModel) {
    if (props.manufacturerWikidata && !props.model) return wikidataLink(makeModel, props.manufacturerWikidata)
    return escapeHtml(makeModel)
  }
  if (props.operator) return wikidataLink(props.operator, props.operatorWikidata)
  if (props.ref) return escapeHtml(props.ref)
  return 'ALPR camera'
}

function titleText(props) {
  if (props.name) return props.name
  if (props.model) {
    return [props.manufacturer, props.model].filter(Boolean).join(' ')
  }
  const makeModel = [props.manufacturer, props.model].filter(Boolean).join(' ')
  if (makeModel) return makeModel
  if (props.operator) return props.operator
  if (props.ref) return props.ref
  return 'ALPR camera'
}

function modelLineHtml(props) {
  if (props.model) {
    return `<div class="text-sm mt-0.5"><span class="text-kestrel-muted">Model</span> <strong>${escapeHtml(props.model)}</strong></div>`
  }
  if (props.modelUnknown) {
    return '<div class="text-kestrel-muted text-xs mt-0.5">Model not recorded in OpenStreetMap</div>'
  }
  return ''
}

/** Human-readable ALPR popup (GeoJSON properties in, HTML out). */
export function formatAlprPopup(props) {
  const title = titleHtml(props)
  const headline = titleText(props)
  const makeModel = [props.manufacturer, props.model].filter(Boolean).join(' ')

  const identity = []
  if (props.name && makeModel) identity.push(escapeHtml(makeModel))
  if (props.operator && headline !== props.operator) {
    identity.push(wikidataLink(props.operator, props.operatorWikidata))
  }
  if (props.ref && headline !== props.ref) identity.push(escapeHtml(props.ref))
  if (props.brand) identity.push(escapeHtml(props.brand))

  const view = []
  if (props.direction != null) {
    const deg = Math.round(props.direction)
    const compass = compassLabel(props.direction)
    view.push(compass ? `Facing ${compass} (${deg}°)` : `Facing ${deg}°`)
  }
  if (props.fov != null && props.direction != null) view.push(`~${Math.round(props.fov)}° view`)

  const note = props.description || props.note
  const noteHtml = note ? `<div class="text-kestrel-muted text-xs mt-1">${escapeHtml(note)}</div>` : ''
  const identityHtml = identity.length
    ? `<div class="text-kestrel-muted text-xs mt-0.5">${identity.join(' · ')}</div>`
    : ''
  const modelHtml = (props.model || props.modelUnknown) ? modelLineHtml(props) : ''
  const foot = `<div class="text-kestrel-muted text-xs mt-2"><a href="https://www.openstreetmap.org/node/${props.osmId}" target="_blank" rel="noopener">View on OpenStreetMap</a></div>`

  return `<div class="kestrel-live-popup"><strong>${title}</strong> <span class="text-kestrel-muted">License plate reader</span>${modelHtml}${identityHtml}${popupLine(view)}${noteHtml}${foot}</div>`
}

function popupHtml(props) {
  return formatAlprPopup(props)
}

function pointIcon(L, direction, fov) {
  const hasDirection = Number.isFinite(direction)
  if (!hasDirection) {
    const html = `<span class="poi-icon-svg"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="${ALPR_COLOR}" stroke-width="2"><rect x="3" y="5" width="18" height="12" rx="2"/><circle cx="12" cy="11" r="3"/><path d="M8 21h8"/></svg></span>`
    return L.divIcon({
      className: 'poi-div-icon alpr-icon',
      html,
      iconSize: [ICON_SIZE, ICON_SIZE],
      iconAnchor: [ICON_SIZE / 2, ICON_SIZE],
    })
  }
  const spread = Number.isFinite(fov) ? fov : DEFAULT_FOV
  const html = `<span class="alpr-cone" style="transform:rotate(${direction}deg)"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 52 52" width="${CONE_SIZE}" height="${CONE_SIZE}"><path d="${conePath(spread)}" fill="${ALPR_COLOR}" fill-opacity="0.3" stroke="${ALPR_COLOR}" stroke-width="1.5"/><circle cx="26" cy="26" r="3" fill="${ALPR_COLOR}"/></svg></span>`
  return L.divIcon({
    className: 'poi-div-icon alpr-icon',
    html,
    iconSize: [CONE_SIZE, CONE_SIZE],
    iconAnchor: [CONE_SIZE / 2, CONE_SIZE / 2],
  })
}

function clusterIcon(L, count) {
  const size = count < 10 ? 28 : count < 100 ? 34 : 40
  return L.divIcon({
    className: 'alpr-cluster-icon',
    html: `<span class="alpr-cluster">${count}</span>`,
    iconSize: [size, size],
    iconAnchor: [size / 2, size / 2],
  })
}

export function createAlprControl(L, { showAlpr, onToggle }) {
  const control = L.control({ position: 'topleft' })
  control.onAdd = function () {
    const el = document.createElement('button')
    el.type = 'button'
    el.className = 'leaflet-bar leaflet-control-alpr'
    el.title = 'Toggle ALPR cameras (OSM)'
    el.setAttribute('aria-label', 'Toggle ALPR cameras')
    el.setAttribute('aria-pressed', showAlpr ? 'true' : 'false')
    el.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="20" height="20"><rect x="3" y="5" width="18" height="12" rx="2"/><circle cx="12" cy="11" r="3"/></svg>'
    el.addEventListener('click', onToggle)
    control._button = el
    return el
  }
  return control
}

export function setAlprControlPressed(control, pressed) {
  control?._button?.setAttribute('aria-pressed', pressed ? 'true' : 'false')
}

function featureKey(feature) {
  const props = feature.properties ?? {}
  if (props.cluster) return `c:${props.cluster_id}`
  const id = props.osmId
  return id != null ? `a:${id}` : null
}

function coords(feature) {
  const [lng, lat] = feature.geometry.coordinates
  return { lat, lng }
}

function attachClusterClick(marker, feature, map) {
  marker.on('click', () => {
    const { lat, lng } = coords(feature)
    const props = feature.properties ?? {}
    const zoom = props.expansionZoom ?? map.getZoom() + 2
    map.setView([lat, lng], Math.min(zoom, 19), { animate: true })
  })
}

export function createAlprLayer(L, map) {
  return L.layerGroup().addTo(map)
}

export function syncAlprLayer(L, map, layer, features) {
  syncFeatureMarkers(layer, features, {
    keyFor: featureKey,
    create: (feature) => {
      const { lat, lng } = coords(feature)
      const props = feature.properties ?? {}
      const isCluster = Boolean(props.cluster)
      const icon = isCluster ? clusterIcon(L, props.point_count) : pointIcon(L, props.direction, props.fov)
      const marker = L.marker([lat, lng], { icon })
      if (isCluster) attachClusterClick(marker, feature, map)
      else marker.bindPopup(popupHtml(props), { className: 'kestrel-live-popup-wrap', maxWidth: 320 })
      return marker
    },
    update: (marker, feature) => {
      const { lat, lng } = coords(feature)
      const props = feature.properties ?? {}
      const isCluster = Boolean(props.cluster)
      marker.setLatLng([lat, lng])
      const icon = isCluster ? clusterIcon(L, props.point_count) : pointIcon(L, props.direction, props.fov)
      marker.setIcon(icon)
      if (!isCluster) marker.setPopupContent(popupHtml(props))
    },
  })
}
