import {BASE} from '@/services/api.ts';
import Map from 'ol/Map'
import { Feature } from 'ol'
import Point from 'ol/geom/Point'
import { fromLonLat } from 'ol/proj'
import { Style, Icon, Text, Fill, Stroke } from 'ol/style'
import { Vector as VectorLayer } from 'ol/layer'
import { Vector as VectorSource } from 'ol/source'
import { adjustedInterval } from '@ztimson/utils'

const API = BASE + '/api'

const SHIP_COLORS: Record<string, string> = {
	'Base Station':      '#00aaff',
	'Class A':           '#00ff00',
	'Class B':           '#8450ea',
	'SAR Aircraft':      '#ff6600',
	'Aid to Navigation': '#ffff00',
	'Class B CS':        '#8450ea',
	'Sart/Epirb/MOB':   '#ff0000',
	'Unknown':           '#fad106',
}

function buildBoatIcon(boat: any): string {
	const color = SHIP_COLORS[boat.type] || SHIP_COLORS['Unknown']

	if (boat.type === 'Base Station') {
		return `data:image/svg+xml,${encodeURIComponent(`
            <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
                <polygon points="16,2 30,16 16,30 2,16" fill="${color}" stroke="#000" stroke-width="1.5"/>
                <circle cx="16" cy="9" r="1.8" fill="#000"/>
                <line x1="16" y1="9" x2="16" y2="23" stroke="#000" stroke-width="1.8"/>
                <line x1="11" y1="12" x2="21" y2="12" stroke="#000" stroke-width="1.8"/>
                <path d="M9,18 Q16,26 23,18" fill="none" stroke="#000" stroke-width="1.5"/>
            </svg>
        `)}`
	}

	return `data:image/svg+xml,${encodeURIComponent(`
        <svg xmlns="http://www.w3.org/2000/svg" width="24" height="32" viewBox="0 0 24 32">
            <polygon points="12,0 24,28 12,22 0,28" fill="${color}" stroke="#000" stroke-width="1.5"/>
            <circle cx="12" cy="12" r="1.5" fill="#000"/>
            <line x1="12" y1="12" x2="12" y2="22" stroke="#000" stroke-width="1.5"/>
            <line x1="8" y1="14" x2="16" y2="14" stroke="#000" stroke-width="1.5"/>
            <path d="M7,17 Q12,24 17,17" fill="none" stroke="#000" stroke-width="1.3"/>
        </svg>
    `)}`
}

function buildPopupHtml(boat: any): string {
	const name = boat.name?.trim() || boat.callsign?.trim() || `MMSI: ${boat.mmsi}`
	const rows: [string, any][] = [
		['Type',        boat.type],
		['MMSI',        boat.mmsi],
		['Country',     boat.country],
		['Callsign',    boat.callsign || '-'],
		['IMO',         boat.imo || '-'],
		['Ship Type',   boat.ship_type ?? '-'],
		['Speed',       boat.speed != null ? `${boat.speed} kts` : '-'],
		['Heading',     boat.heading != null ? `${boat.heading}°` : '-'],
		['Course',      boat.course != null ? `${boat.course}°` : '-'],
		['Lat / Lon',   `${boat.lat?.toFixed(5)}, ${boat.lon?.toFixed(5)}`],
		['Distance',    `${boat.distance?.toFixed(2)} nmi`],
		['Bearing',     `${boat.bearing}°`],
		['Destination', boat.destination || '-'],
		['ETA',         boat.eta || '-'],
		['Draught',     boat.draught != null ? `${boat.draught}m` : '-'],
		['RSSI',        `${boat.rssi?.toFixed(1)} dB`],
		['Drift',       `${boat.drift?.toFixed(2)} ppm`],
		['Msg Types',   boat.msg_type?.join(', ') || '-'],
		['Channels',    boat.channels || '-'],
		['Sources',     boat.sources],
		['Receiver',    boat.receiver],
		['Count',       boat.count],
		['Last Signal', boat.last_signal != null ? `${boat.last_signal}s ago` : '-'],
		['In Range',    boat.in_range],
	]

	return `
        <div style="font-family:monospace;color:#ccc;min-width:280px">
            <div style="padding:12px 16px;border-bottom:1px solid rgba(200,200,220,0.2)">
                <h3 style="margin:0;color:#7eeee1;font-size:16px">🚢 ${name}</h3>
                <div style="font-size:11px;color:#888;margin-top:4px">${boat.type || 'Unknown'}</div>
            </div>
            <div style="padding:12px 16px;display:grid;grid-template-columns:1fr 1fr;gap:6px 16px">
                ${rows.map(([label, val]) => `
                    <div>
                        <div style="color:#888;font-size:10px;font-weight:bold">${label}</div>
                        <div style="color:#0f0;font-size:13px">${val ?? '-'}</div>
                    </div>
                `).join('')}
            </div>
        </div>
    `
}

export class AISLayer {
	private map:          Map
	private layer!:       VectorLayer<VectorSource>
	private popups:       Record<string, { el: HTMLDivElement, destroy: () => void }> = {}
	private data:         any[] = []
	private clickHandler: ((e: any) => void) | null = null
	private refreshTimer: any = null
	visible = false

	constructor(map: Map) { this.map = map }

	// ── Public ────────────────────────────────────────────────────────────────

	async show() {
		if (this.visible) return
		this.visible = true

		this.layer = new VectorLayer({ source: new VectorSource(), zIndex: 100 })
		this.map.addLayer(this.layer)

		await this._fetch()
		this._draw()
		this._attachClick()

		this.refreshTimer = adjustedInterval(async () => {
			await this._fetch()
			this._draw()
			this._refreshPopups()
		}, 5_000)
	}

	hide() {
		if (!this.visible) return
		this.visible = false

		if (this.refreshTimer) { clearInterval(this.refreshTimer); this.refreshTimer = null }
		if (this.clickHandler) { this.map.un('singleclick', this.clickHandler); this.clickHandler = null }

		for (const mmsi of Object.keys(this.popups)) this._closePopup(mmsi)
		this.map.removeLayer(this.layer)
	}

	// ── Private ───────────────────────────────────────────────────────────────

	private async _fetch() {
		this.data = await fetch(`${API}/ais`).then(r => r.json()) || []
	}

	private _draw() {
		const source = this.layer.getSource()!
		source.clear()

		for (const boat of this.data) {
			if (boat.lat == null || boat.lon == null) continue
			const coord = fromLonLat([boat.lon, boat.lat])
			const f = new Feature({ geometry: new Point(coord) })
			f.set('mmsi',     boat.mmsi)
			f.set('boatData', boat)
			f.setStyle(new Style({
				image: new Icon({
					src:      buildBoatIcon(boat),
					scale:    1,
					rotation: (boat.heading ?? boat.course ?? 0) * (Math.PI / 180),
					anchor:   [0.5, 0.5],
				}),
			}))
			source.addFeature(f)
		}
	}

	private _openPopup(boat: any) {
		const mmsi = String(boat.mmsi)
		if (this.popups[mmsi]) return

		const el = document.createElement('div')
		el.style.cssText = `
            position:absolute; z-index:9999; pointer-events:auto;
            background:rgba(0,0,0,0.88); border:1px solid rgba(200,200,220,0.3);
            border-radius:8px; box-shadow:0 4px 24px rgba(0,0,0,0.5); overflow:hidden;
        `

		const close         = document.createElement('button')
		close.innerHTML     = '✕'
		close.style.cssText = 'position:absolute;top:8px;right:8px;background:none;border:none;color:#888;font-size:14px;cursor:pointer;z-index:1'
		close.onclick       = () => this._closePopup(mmsi)

		el.innerHTML = buildPopupHtml(boat)
		el.appendChild(close)
		document.body.appendChild(el)
		this._positionPopup(el, boat)

		this.popups[mmsi] = { el, destroy: () => el.remove() }
	}

	private _positionPopup(el: HTMLDivElement, boat: any) {
		const pixel: any = this.map.getPixelFromCoordinate(fromLonLat([boat.lon, boat.lat]))
		if (!pixel) return
		const rect    = (this.map.getTargetElement() as HTMLElement).getBoundingClientRect()
		el.style.left = `${rect.left + pixel[0] + 16}px`
		el.style.top  = `${rect.top  + pixel[1] - 16}px`
	}

	private _closePopup(mmsi: string) {
		const popup = this.popups[mmsi]
		if (popup) { popup.destroy(); delete this.popups[mmsi] }
	}

	private _refreshPopups() {
		for (const mmsi of Object.keys(this.popups)) {
			const boat = this.data.find(b => String(b.mmsi) === mmsi)
			if (!boat) { this._closePopup(mmsi); continue }
			const { el } = <any>this.popups[mmsi]
			el.innerHTML  = buildPopupHtml(boat)
			const close   = document.createElement('button')
			close.innerHTML     = '✕'
			close.style.cssText = 'position:absolute;top:8px;right:8px;background:none;border:none;color:#888;font-size:14px;cursor:pointer;z-index:1'
			close.onclick       = () => this._closePopup(mmsi)
			el.appendChild(close)
			this._positionPopup(el, boat)
		}
	}

	private _attachClick() {
		this.clickHandler = (evt) => {
			const f = this.map.forEachFeatureAtPixel(evt.pixel, f => f.get('boatData') ? f : null)
			if (!f) return
			const boat = f.get('boatData')
			const mmsi = String(boat.mmsi)
			if (this.popups[mmsi]) { this._closePopup(mmsi); return }
			this._openPopup(boat)
		}
		this.map.on('singleclick', this.clickHandler)
	}
}
