/**
 * Location Map Component
 * Displays a location on an OpenStreetMap map using Leaflet
 */

import { escapeHTML } from '../utils/helpers.js'

const NOMINATIM_URL = 'https://nominatim.openstreetmap.org/search'

class LocationMap extends HTMLElement {
    constructor() {
        super()
        this.map = null
        this.marker = null
        this.leafletLoaded = false
    }

    static get observedAttributes() {
        return ['lat', 'lng', 'name', 'postal-code', 'country']
    }

    async connectedCallback() {
        await this.loadLeaflet()
        this.render()
        await this.initMap()
    }

    disconnectedCallback() {
        if (this.map) {
            this.map.remove()
            this.map = null
        }
    }

    attributeChangedCallback() {
        if (this.map) {
            this.updateMap()
        }
    }

    async loadLeaflet() {
        if (this.leafletLoaded || window.L) {
            this.leafletLoaded = true
            return
        }

        // Load Leaflet CSS
        const css = document.createElement('link')
        css.rel = 'stylesheet'
        css.href = 'https://unpkg.com/leaflet@1.9.4/dist/leaflet.css'
        css.integrity = 'sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY='
        css.crossOrigin = ''
        document.head.appendChild(css)

        // Load Leaflet JS
        await new Promise((resolve, reject) => {
            const script = document.createElement('script')
            script.src = 'https://unpkg.com/leaflet@1.9.4/dist/leaflet.js'
            script.integrity = 'sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo='
            script.crossOrigin = ''
            script.onload = resolve
            script.onerror = reject
            document.head.appendChild(script)
        })

        this.leafletLoaded = true
    }

    render() {
        const name = this.getAttribute('name') || ''
        const postalCode = this.getAttribute('postal-code') || ''
        const country = this.getAttribute('country') || ''

        const locationText = [postalCode, name, country].filter(Boolean).join(', ')

        this.innerHTML = /* html */`
            <div class="location-map-container">
                <div class="location-map-header">
                    <span class="location-icon">📍</span>
                    <span class="location-text">${escapeHTML(locationText)}</span>
                </div>
                <div class="location-map" id="map"></div>
            </div>
        `
    }

    async initMap() {
        const lat = parseFloat(this.getAttribute('lat'))
        const lng = parseFloat(this.getAttribute('lng'))

        let coords = null

        if (!isNaN(lat) && !isNaN(lng)) {
            coords = [lat, lng]
        } else {
            // Geocode from name/postal-code/country
            coords = await this.geocodeLocation()
        }

        if (!coords) {
            this.querySelector('.location-map').innerHTML = '<p class="map-error">Standort konnte nicht geladen werden</p>'
            return
        }

        const mapContainer = this.querySelector('#map')
        if (!mapContainer || !window.L) return

        this.map = L.map(mapContainer, {
            scrollWheelZoom: false,
            dragging: !L.Browser.mobile,
            attributionControl: false
        }).setView(coords, 13)

        // Custom attribution (OSM required, no Leaflet branding)
        L.control.attribution({
            prefix: false
        }).addAttribution('© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>').addTo(this.map)

        L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
            attribution: ''
        }).addTo(this.map)

        this.marker = L.marker(coords).addTo(this.map)

        // Invalidate size after render (fixes grey tiles issue)
        setTimeout(() => {
            this.map?.invalidateSize()
        }, 100)
    }

    async geocodeLocation() {
        const name = this.getAttribute('name') || ''
        const postalCode = this.getAttribute('postal-code') || ''
        const country = this.getAttribute('country') || ''

        const query = [postalCode, name, country].filter(Boolean).join(' ')
        if (!query) return null

        try {
            const params = new URLSearchParams({
                q: query,
                format: 'json',
                limit: '1'
            })

            const response = await fetch(`${NOMINATIM_URL}?${params}`, {
                headers: { 'User-Agent': 'dgray.io/1.0' }
            })

            const results = await response.json()
            if (results.length > 0) {
                return [parseFloat(results[0].lat), parseFloat(results[0].lon)]
            }
        } catch (error) {
            console.error('Geocoding failed:', error)
        }

        return null
    }

    async updateMap() {
        if (!this.map) return

        const coords = await this.geocodeLocation()
        if (coords) {
            this.map.setView(coords, 13)
            if (this.marker) {
                this.marker.setLatLng(coords)
            }
        }
    }

}

customElements.define('location-map', LocationMap)

const style = document.createElement('style')
style.textContent = /* css */`
    location-map {
        display: block;
    }

    location-map .location-map-container {
        border: 1px solid var(--color-border);
        border-radius: var(--radius-md);
        overflow: hidden;
    }

    location-map .location-map-header {
        display: flex;
        align-items: center;
        gap: var(--space-sm);
        padding: var(--space-sm) var(--space-md);
        background: var(--color-bg-secondary);
        border-bottom: 1px solid var(--color-border);
    }

    location-map .location-icon {
        font-size: 1rem;
    }

    location-map .location-text {
        font-size: var(--font-size-sm);
        font-weight: var(--font-weight-medium);
    }

    location-map .location-map {
        height: 200px;
        background: var(--color-bg-tertiary);
    }

    location-map .map-error {
        display: flex;
        align-items: center;
        justify-content: center;
        height: 100%;
        color: var(--color-text-muted);
        font-size: var(--font-size-sm);
    }

    /* Fix Leaflet styles for dark mode */
    location-map .leaflet-container {
        background: var(--color-bg-tertiary);
    }

    location-map .leaflet-control-attribution {
        background: var(--color-bg);
        color: var(--color-text-muted);
        font-size: 10px;
    }

    location-map .leaflet-control-attribution a {
        color: var(--color-primary);
    }
`
document.head.appendChild(style)

export { LocationMap }
