/** @odoo-module **/

import { Component, onMounted, onWillUnmount, useRef, useState } from "@odoo/owl";
import { registry } from "@web/core/registry";
import { standardFieldProps } from "@web/views/fields/standard_field_props";
import { rpc } from "@web/core/network/rpc";

/**
 * Google Places Autocomplete widget for the address field.
 * Automatically geocodes the selected place and updates lat/lng on the record.
 */
export class FusionClockPlacesAutocomplete extends Component {
    static template = "fusion_clock.PlacesAutocomplete";
    static props = { ...standardFieldProps };

    setup() {
        this.inputRef = useRef("addressInput");
        this.autocomplete = null;
        this._apiReady = false;

        this.state = useState({
            value: this.props.record.data[this.props.name] || "",
        });

        onMounted(() => this._init());
        onWillUnmount(() => this._cleanup());
    }

    get isReadonly() {
        return this.props.readonly;
    }

    async _getApiKey() {
        try {
            return await rpc("/web/dataset/call_kw", {
                model: "ir.config_parameter",
                method: "get_param",
                args: ["fusion_clock.google_maps_api_key", ""],
                kwargs: {},
            }) || "";
        } catch (e) {
            return "";
        }
    }

    async _waitForGoogleMaps() {
        if (window.google && window.google.maps && window.google.maps.places) {
            return true;
        }
        return new Promise((resolve) => {
            let attempts = 0;
            const check = setInterval(() => {
                attempts++;
                if (window.google && window.google.maps && window.google.maps.places) {
                    clearInterval(check);
                    resolve(true);
                }
                if (attempts > 50) {
                    clearInterval(check);
                    resolve(false);
                }
            }, 100);
        });
    }

    async _loadGoogleMaps(apiKey) {
        if (window.google && window.google.maps) return;

        if (document.querySelector('script[src*="maps.googleapis.com"]')) {
            await this._waitForGoogleMaps();
            return;
        }

        return new Promise((resolve, reject) => {
            const script = document.createElement("script");
            script.src = `https://maps.googleapis.com/maps/api/js?key=${apiKey}&libraries=places&callback=__fclkPlacesInit`;
            script.async = true;
            script.defer = true;
            window.__fclkPlacesInit = () => {
                delete window.__fclkPlacesInit;
                resolve();
            };
            script.onerror = () => reject(new Error("Failed to load Google Maps"));
            document.head.appendChild(script);
        });
    }

    async _init() {
        if (this.isReadonly) return;

        const apiKey = await this._getApiKey();
        if (!apiKey) return;

        try {
            await this._loadGoogleMaps(apiKey);
        } catch (e) {
            return;
        }

        await this._waitForGoogleMaps();

        if (!this.inputRef.el || !window.google || !window.google.maps.places) return;

        this.autocomplete = new google.maps.places.Autocomplete(this.inputRef.el, {
            types: ["geocode", "establishment"],
            fields: ["formatted_address", "geometry", "name"],
        });

        this.autocomplete.addListener("place_changed", () => {
            const place = this.autocomplete.getPlace();
            if (!place || !place.geometry) return;

            const lat = place.geometry.location.lat();
            const lng = place.geometry.location.lng();
            const address = place.formatted_address || place.name || "";

            this.state.value = address;
            this.props.record.update({
                [this.props.name]: address,
                latitude: Math.round(lat * 10000000) / 10000000,
                longitude: Math.round(lng * 10000000) / 10000000,
            });
        });
    }

    onInput(ev) {
        this.state.value = ev.target.value;
    }

    onChange(ev) {
        this.props.record.update({ [this.props.name]: ev.target.value });
    }

    _cleanup() {
        if (this.autocomplete) {
            google.maps.event.clearInstanceListeners(this.autocomplete);
            this.autocomplete = null;
        }

        const containers = document.querySelectorAll(".pac-container");
        containers.forEach((c) => c.remove());
    }
}

FusionClockPlacesAutocomplete.template = "fusion_clock.PlacesAutocomplete";

registry.category("fields").add("fclk_places_autocomplete", {
    component: FusionClockPlacesAutocomplete,
    supportedTypes: ["char"],
});
