/** @odoo-module **/

import { Component, useState, onWillStart, onMounted, onWillUnmount } from "@odoo/owl";
import { rpc } from "@web/core/network/rpc";
import { registry } from "@web/core/registry";
import { useService } from "@web/core/utils/hooks";

export class FusionClockFAB extends Component {
    static props = {};
    static template = "fusion_clock.ClockFAB";

    setup() {
        this.notification = useService("notification");

        this.state = useState({
            isCheckedIn: false,
            isDisplayed: false,
            expanded: false,
            checkInTime: null,
            locationName: "",
            timerDisplay: "00:00:00",
            todayHours: "0.0",
            weekHours: "0.0",
            loading: false,
            error: "",
            showReasonDialog: false,
            showClockoutConfirm: false,
            reasonText: "",
            reasonTime: "",
            reasonSubmitting: false,
        });

        this._timerInterval = null;

        onWillStart(async () => {
            await this._fetchStatus();
        });

        onMounted(() => {
            if (this.state.isCheckedIn) {
                this._startTimer();
            }
            // Poll every 15s to stay in sync with portal clock-outs
            this._pollInterval = setInterval(() => this._fetchStatus(), 15000);

            // Re-sync immediately when browser tab regains focus
            this._onFocus = () => this._fetchStatus();
            window.addEventListener("focus", this._onFocus);

            // Close panel when clicking outside
            this._onDocClick = (ev) => {
                if (!this.state.expanded) return;
                const el = ev.target.closest(".fclk-fab-wrapper");
                if (!el) this.state.expanded = false;
            };
            document.addEventListener("click", this._onDocClick, true);
        });

        onWillUnmount(() => {
            this._stopTimer();
            if (this._pollInterval) clearInterval(this._pollInterval);
            if (this._onDocClick) document.removeEventListener("click", this._onDocClick, true);
            if (this._onFocus) window.removeEventListener("focus", this._onFocus);
        });
    }

    togglePanel() {
        this.state.expanded = !this.state.expanded;
        this.state.error = "";
        // Always re-fetch when opening the panel
        if (this.state.expanded) {
            this._fetchStatus();
        }
    }

    async _fetchStatus() {
        try {
            const result = await rpc("/fusion_clock/get_status", {});
            if (result.error) return;

            this.state.isDisplayed = result.enable_clock !== false;
            this.state.locationName = result.location_name || "";
            this.state.todayHours = (result.today_hours || 0).toFixed(1);
            this.state.weekHours = (result.week_hours || 0).toFixed(1);

            if (result.is_checked_in && result.check_in) {
                const serverTime = new Date(result.check_in + "Z");
                const wasRunning = this.state.isCheckedIn;
                this.state.isCheckedIn = true;
                if (!wasRunning || Math.abs(serverTime - this.state.checkInTime) > 5000) {
                    this.state.checkInTime = serverTime;
                    this._startTimer();
                }
                try { localStorage.setItem("fclk_fab_check_in", serverTime.toISOString()); } catch {}
            } else if (!result.is_checked_in) {
                this.state.isCheckedIn = false;
                this.state.checkInTime = null;
                this._stopTimer();
                this.state.timerDisplay = "00:00:00";
                try { localStorage.removeItem("fclk_fab_check_in"); } catch {}
            }
        } catch {
            if (!this.state.isCheckedIn) {
                try {
                    const saved = localStorage.getItem("fclk_fab_check_in");
                    if (saved) {
                        const t = new Date(saved);
                        if (!isNaN(t.getTime()) && (Date.now() - t.getTime()) < 24 * 60 * 60 * 1000) {
                            this.state.isDisplayed = true;
                            this.state.isCheckedIn = true;
                            this.state.checkInTime = t;
                            this._startTimer();
                        }
                    }
                } catch {}
            }
        }
    }

    async onClockAction() {
        if (this.state.isCheckedIn) {
            this.state.showClockoutConfirm = true;
            return;
        }
        await this._executeClockAction();
    }

    async confirmClockOut() {
        this.state.showClockoutConfirm = false;
        await this._executeClockAction();
    }

    cancelClockOut() {
        this.state.showClockoutConfirm = false;
    }

    async _executeClockAction() {
        this.state.loading = true;
        this.state.error = "";

        try {
            let lat = 0, lng = 0, acc = 0;
            if (navigator.geolocation) {
                try {
                    const pos = await new Promise((resolve, reject) => {
                        navigator.geolocation.getCurrentPosition(resolve, reject, {
                            enableHighAccuracy: true,
                            timeout: 15000,
                            maximumAge: 0,
                        });
                    });
                    lat = pos.coords.latitude;
                    lng = pos.coords.longitude;
                    acc = pos.coords.accuracy;
                } catch {
                    // Native GPS unavailable (common on desktops) -- try IP geolocation
                }
            }
            if (lat === 0 && lng === 0) {
                try {
                    const ipResp = await fetch("https://ipapi.co/json/");
                    if (ipResp.ok) {
                        const ipData = await ipResp.json();
                        if (ipData.latitude && ipData.longitude) {
                            lat = ipData.latitude;
                            lng = ipData.longitude;
                            acc = 5000;
                        }
                    }
                } catch {
                    // IP geolocation also unavailable
                }
            }

            const result = await rpc("/fusion_clock/clock_action", {
                latitude: lat,
                longitude: lng,
                accuracy: acc,
                source: "backend_fab",
            });

            if (result.requires_reason) {
                this.state.loading = false;
                this.state.showReasonDialog = true;
                this.state.reasonText = "";
                this.state.reasonTime = "";
                return;
            }

            if (result.error) {
                this.state.error = result.error;
                this.state.loading = false;
                return;
            }

            if (result.action === "clock_in") {
                this.state.isCheckedIn = true;
                this.state.checkInTime = new Date(result.check_in + "Z");
                this.state.locationName = result.location_name || "";
                this._startTimer();
                this.notification.add(result.message || "Clocked in!", { type: "success" });
            } else if (result.action === "clock_out") {
                this.state.isCheckedIn = false;
                this.state.checkInTime = null;
                this._stopTimer();
                this.state.timerDisplay = "00:00:00";
                this.notification.add(result.message || "Clocked out!", { type: "success" });
                await this._fetchStatus();
            }
        } catch (e) {
            this.state.error = e.message || "Clock action failed.";
        }

        this.state.loading = false;
    }

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

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

    cancelReason() {
        this.state.showReasonDialog = false;
        this.state.reasonText = "";
        this.state.reasonTime = "";
    }

    async submitReason() {
        if (!this.state.reasonText.trim()) {
            this.state.error = "Please provide a reason.";
            return;
        }
        this.state.reasonSubmitting = true;
        try {
            await rpc("/fusion_clock/submit_reason", {
                reason: this.state.reasonText.trim(),
                departure_time: this.state.reasonTime || "",
            });
            this.state.showReasonDialog = false;
            this.state.reasonText = "";
            this.state.reasonTime = "";
            this.state.reasonSubmitting = false;
            await this._executeClockAction();
        } catch (e) {
            this.state.error = "Failed to submit reason.";
            this.state.reasonSubmitting = false;
        }
    }

    get confirmCheckinDisplay() {
        if (!this.state.checkInTime) return "--";
        const d = this.state.checkInTime;
        let h = d.getHours();
        const m = d.getMinutes();
        const ampm = h >= 12 ? "PM" : "AM";
        h = h % 12 || 12;
        return h + ":" + (m < 10 ? "0" : "") + m + " " + ampm;
    }

    get confirmDurationDisplay() {
        if (!this.state.checkInTime) return "--";
        const diff = Math.max(0, Math.floor((new Date() - this.state.checkInTime) / 1000));
        const dh = Math.floor(diff / 3600);
        const dm = Math.floor((diff % 3600) / 60);
        return dh + "h " + dm + "m";
    }

    _startTimer() {
        this._stopTimer();
        this._updateTimer();
        this._timerInterval = setInterval(() => this._updateTimer(), 1000);
    }

    _stopTimer() {
        if (this._timerInterval) {
            clearInterval(this._timerInterval);
            this._timerInterval = null;
        }
    }

    _updateTimer() {
        if (!this.state.checkInTime) return;
        const now = new Date();
        let diff = Math.max(0, Math.floor((now - this.state.checkInTime) / 1000));
        const h = Math.floor(diff / 3600);
        const m = Math.floor((diff % 3600) / 60);
        const s = diff % 60;
        const pad = (n) => (n < 10 ? "0" + n : "" + n);
        this.state.timerDisplay = pad(h) + ":" + pad(m) + ":" + pad(s);
    }
}

registry.category("main_components").add("FusionClockFAB", {
    Component: FusionClockFAB,
});
