/** @odoo-module **/
/**
 * Fusion Clock - Portal Floating Action Button (Odoo 19)
 *
 * A persistent clock-in/out FAB that appears on ALL portal pages.
 * Uses the Interaction class pattern required by Odoo 19 frontend.
 * Shares RPC endpoints with the backend FAB and full clock page.
 */

import { Interaction } from "@web/public/interaction";
import { registry } from "@web/core/registry";
import { rpc } from "@web/core/network/rpc";

export class FusionClockPortalFAB extends Interaction {
    static selector = "#fclk-portal-fab";

    setup() {
        // Hide on /my/clock page to avoid duplication with the full clock UI
        if (window.location.pathname === "/my/clock") {
            this.el.style.display = "none";
            return;
        }

        this.isCheckedIn = this.el.dataset.checkedIn === "true";
        this.checkInTime = null;
        this.expanded = false;
        this._timerInterval = null;
        this._pollInterval = null;

        if (this.el.dataset.checkInTime) {
            this.checkInTime = new Date(this.el.dataset.checkInTime + "Z");
        }

        // Cache DOM references
        this.fabBtn = this.el.querySelector(".fclk-pfab-btn");
        this.panel = this.el.querySelector(".fclk-pfab-panel");
        this.statusDot = this.el.querySelector(".fclk-pfab-status-dot");
        this.statusText = this.el.querySelector(".fclk-pfab-status-text");
        this.locationRow = this.el.querySelector(".fclk-pfab-location");
        this.locationText = this.el.querySelector(".fclk-pfab-location-text");
        this.timerEl = this.el.querySelector(".fclk-pfab-timer");
        this.badgeEl = this.el.querySelector(".fclk-pfab-badge");
        this.actionBtn = this.el.querySelector(".fclk-pfab-action");
        this.errorEl = this.el.querySelector(".fclk-pfab-error");
        this.errorText = this.el.querySelector(".fclk-pfab-error-text");
        this.todayEl = this.el.querySelector(".fclk-pfab-today");
        this.weekEl = this.el.querySelector(".fclk-pfab-week");

        // Bind events
        if (this.fabBtn) {
            this._onFabClick = () => this._togglePanel();
            this.fabBtn.addEventListener("click", this._onFabClick);
        }
        if (this.actionBtn) {
            this._onActionClick = (e) => {
                e.preventDefault();
                this._onClockAction();
            };
            this.actionBtn.addEventListener("click", this._onActionClick);
        }

        // Close panel on outside click
        this._onDocClick = (ev) => {
            if (!this.expanded) return;
            if (!ev.target.closest("#fclk-portal-fab")) {
                this._closePanel();
            }
        };
        document.addEventListener("click", this._onDocClick, true);

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

        // Visibility change sync
        this._onVisibility = () => {
            if (document.visibilityState === "visible") this._fetchStatus();
        };
        document.addEventListener("visibilitychange", this._onVisibility);

        // Initial state
        this._applyState();

        // Start timer if already checked in
        if (this.isCheckedIn && this.checkInTime) {
            this._startTimer();
        }

        // Poll every 30s to stay in sync
        this._pollInterval = setInterval(() => this._fetchStatus(), 30000);
    }

    destroy() {
        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);
        if (this._onVisibility) document.removeEventListener("visibilitychange", this._onVisibility);
        if (this.fabBtn && this._onFabClick) this.fabBtn.removeEventListener("click", this._onFabClick);
        if (this.actionBtn && this._onActionClick) this.actionBtn.removeEventListener("click", this._onActionClick);
    }

    // =========================================================================
    // Panel Toggle
    // =========================================================================

    _togglePanel() {
        if (this.expanded) {
            this._closePanel();
        } else {
            this._openPanel();
        }
    }

    _openPanel() {
        this.expanded = true;
        if (this.panel) {
            this.panel.style.display = "block";
            this.panel.classList.add("fclk-pfab-panel--open");
        }
        this._clearError();
        this._fetchStatus();
    }

    _closePanel() {
        this.expanded = false;
        if (this.panel) {
            this.panel.classList.remove("fclk-pfab-panel--open");
            setTimeout(() => {
                if (!this.expanded && this.panel) this.panel.style.display = "none";
            }, 200);
        }
    }

    // =========================================================================
    // State Management
    // =========================================================================

    _applyState() {
        // FAB button state
        if (this.fabBtn) {
            this.fabBtn.classList.toggle("fclk-pfab-btn--active", this.isCheckedIn);
        }
        this.el.classList.toggle("fclk-pfab--active", this.isCheckedIn);

        // Status dot and text
        if (this.statusDot) {
            this.statusDot.classList.toggle("fclk-pfab-status-dot--active", this.isCheckedIn);
        }
        if (this.statusText) {
            this.statusText.textContent = this.isCheckedIn ? "Clocked In" : "Not Clocked In";
        }

        // Location
        const locName = this.el.dataset.locationName || "";
        if (this.locationRow) {
            this.locationRow.style.display = (this.isCheckedIn && locName) ? "flex" : "none";
        }
        if (this.locationText) {
            this.locationText.textContent = locName;
        }

        // Action button
        if (this.actionBtn) {
            if (this.isCheckedIn) {
                this.actionBtn.classList.remove("fclk-pfab-action--in");
                this.actionBtn.classList.add("fclk-pfab-action--out");
                this.actionBtn.innerHTML = '<i class="fa fa-stop-circle-o"/> Clock Out';
            } else {
                this.actionBtn.classList.remove("fclk-pfab-action--out");
                this.actionBtn.classList.add("fclk-pfab-action--in");
                this.actionBtn.innerHTML = '<i class="fa fa-play-circle-o"/> Clock In';
            }
        }

        // Badge
        if (this.badgeEl) {
            this.badgeEl.style.display = this.isCheckedIn ? "block" : "none";
        }

        // Timer reset when not checked in
        if (!this.isCheckedIn && this.timerEl) {
            this.timerEl.textContent = "00:00:00";
        }
    }

    // =========================================================================
    // Fetch Status from Server
    // =========================================================================

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

            const wasCheckedIn = this.isCheckedIn;
            this.isCheckedIn = result.is_checked_in;

            if (result.is_checked_in && result.check_in) {
                this.checkInTime = new Date(result.check_in + "Z");
                this.el.dataset.locationName = result.location_name || "";
                if (!wasCheckedIn) this._startTimer();
            } else {
                this.checkInTime = null;
                this._stopTimer();
            }

            if (this.todayEl) {
                this.todayEl.textContent = (result.today_hours || 0).toFixed(1) + "h";
            }
            if (this.weekEl) {
                this.weekEl.textContent = (result.week_hours || 0).toFixed(1) + "h";
            }

            this._applyState();
        } catch (e) {
            // Silent fail - will retry on next poll
        }
    }

    // =========================================================================
    // Clock Action
    // =========================================================================

    async _onClockAction() {
        if (this.isCheckedIn) {
            this._showClockOutConfirm();
            return;
        }
        await this._executeClockAction();
    }

    _showClockOutConfirm() {
        let modal = document.getElementById("fclk-pfab-clockout-modal");
        if (!modal) {
            modal = document.createElement("div");
            modal.id = "fclk-pfab-clockout-modal";
            modal.className = "fclk-wizard-overlay";
            modal.innerHTML = `
                <div class="fclk-wizard-backdrop" data-pfab-dismiss="fclk-pfab-clockout-modal"></div>
                <div class="fclk-wizard-dialog fclk-wizard-dialog--compact">
                    <div class="fclk-wizard-header fclk-wizard-header--danger">
                        <div class="fclk-wizard-header-icon">
                            <svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="4" y="4" width="16" height="16" rx="2"/></svg>
                        </div>
                        <h3 class="fclk-wizard-title">Clock Out?</h3>
                        <p class="fclk-wizard-subtitle">Are you sure you want to end your current shift?</p>
                    </div>
                    <div class="fclk-wizard-body">
                        <div class="fclk-clockout-summary">
                            <div class="fclk-clockout-summary-row">
                                <span class="fclk-clockout-summary-label">Clocked in at</span>
                                <span class="fclk-clockout-summary-value" id="fclk-pfab-confirm-time">--</span>
                            </div>
                            <div class="fclk-clockout-summary-row">
                                <span class="fclk-clockout-summary-label">Duration</span>
                                <span class="fclk-clockout-summary-value" id="fclk-pfab-confirm-dur">--</span>
                            </div>
                        </div>
                    </div>
                    <div class="fclk-wizard-footer">
                        <button class="fclk-wizard-btn fclk-wizard-btn--secondary" data-pfab-dismiss="fclk-pfab-clockout-modal">Cancel</button>
                        <button class="fclk-wizard-btn fclk-wizard-btn--danger" id="fclk-pfab-confirm-clockout-btn">
                            <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="4" y="4" width="16" height="16" rx="2"/></svg>
                            Confirm Clock Out
                        </button>
                    </div>
                </div>`;
            document.body.appendChild(modal);

            modal.querySelectorAll("[data-pfab-dismiss]").forEach((btn) => {
                btn.addEventListener("click", () => { modal.style.display = "none"; });
            });
            document.getElementById("fclk-pfab-confirm-clockout-btn").addEventListener("click", () => {
                modal.style.display = "none";
                this._executeClockAction();
            });
        }

        if (this.checkInTime) {
            const h = this.checkInTime.getHours();
            const m = this.checkInTime.getMinutes();
            const ampm = h >= 12 ? "PM" : "AM";
            const hour12 = h % 12 || 12;
            const timeEl = document.getElementById("fclk-pfab-confirm-time");
            if (timeEl) timeEl.textContent = hour12 + ":" + (m < 10 ? "0" : "") + m + " " + ampm;

            const diff = Math.max(0, Math.floor((new Date() - this.checkInTime) / 1000));
            const dh = Math.floor(diff / 3600);
            const dm = Math.floor((diff % 3600) / 60);
            const durEl = document.getElementById("fclk-pfab-confirm-dur");
            if (durEl) durEl.textContent = dh + "h " + dm + "m";
        }

        modal.style.display = "flex";
    }

    _showReasonDialog() {
        let modal = document.getElementById("fclk-pfab-reason-modal");
        if (!modal) {
            modal = document.createElement("div");
            modal.id = "fclk-pfab-reason-modal";
            modal.className = "fclk-wizard-overlay";
            modal.innerHTML = `
                <div class="fclk-wizard-backdrop" data-pfab-dismiss="fclk-pfab-reason-modal"></div>
                <div class="fclk-wizard-dialog">
                    <div class="fclk-wizard-header fclk-wizard-header--warning">
                        <div class="fclk-wizard-header-icon">
                            <svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
                                <path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/>
                                <line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/>
                            </svg>
                        </div>
                        <h3 class="fclk-wizard-title">Missed Clock-Out</h3>
                        <p class="fclk-wizard-subtitle">You didn't clock out on your last shift. Please provide details before continuing.</p>
                    </div>
                    <div class="fclk-wizard-body">
                        <div class="fclk-wizard-field">
                            <label class="fclk-wizard-label">
                                <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>
                                Reason <span class="fclk-wizard-required">*</span>
                            </label>
                            <textarea id="fclk-pfab-reason-text" class="fclk-wizard-input fclk-wizard-textarea" rows="3"
                                      placeholder="Please explain why you didn't clock out..."></textarea>
                        </div>
                        <div class="fclk-wizard-field">
                            <label class="fclk-wizard-label">
                                <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg>
                                Departure Time
                            </label>
                            <input type="datetime-local" id="fclk-pfab-reason-time" class="fclk-wizard-input"/>
                            <span class="fclk-wizard-hint">When did you actually leave? (optional)</span>
                        </div>
                    </div>
                    <div class="fclk-wizard-footer">
                        <button class="fclk-wizard-btn fclk-wizard-btn--secondary" data-pfab-dismiss="fclk-pfab-reason-modal">Cancel</button>
                        <button class="fclk-wizard-btn fclk-wizard-btn--primary" id="fclk-pfab-reason-submit-btn">
                            <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="20 6 9 17 4 12"/></svg>
                            Submit Reason
                        </button>
                    </div>
                </div>`;
            document.body.appendChild(modal);

            modal.querySelectorAll("[data-pfab-dismiss]").forEach((btn) => {
                btn.addEventListener("click", () => { modal.style.display = "none"; });
            });
            document.getElementById("fclk-pfab-reason-submit-btn").addEventListener("click", async () => {
                const reasonEl = document.getElementById("fclk-pfab-reason-text");
                const timeEl = document.getElementById("fclk-pfab-reason-time");
                const reason = reasonEl ? reasonEl.value.trim() : "";
                if (!reason) {
                    this._showError("Please provide a reason.");
                    return;
                }
                const submitBtn = document.getElementById("fclk-pfab-reason-submit-btn");
                if (submitBtn) submitBtn.disabled = true;
                try {
                    await rpc("/fusion_clock/submit_reason", {
                        reason: reason,
                        departure_time: timeEl ? timeEl.value : "",
                    });
                    modal.style.display = "none";
                    if (reasonEl) reasonEl.value = "";
                    if (timeEl) timeEl.value = "";
                    if (submitBtn) submitBtn.disabled = false;
                    await this._executeClockAction();
                } catch (e) {
                    this._showError("Failed to submit reason.");
                    if (submitBtn) submitBtn.disabled = false;
                }
            });
        }

        const reasonEl = document.getElementById("fclk-pfab-reason-text");
        const timeEl = document.getElementById("fclk-pfab-reason-time");
        if (reasonEl) reasonEl.value = "";
        if (timeEl) timeEl.value = "";
        modal.style.display = "flex";
    }

    async _executeClockAction() {
        if (this.actionBtn) this.actionBtn.disabled = true;
        this._clearError();

        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: "portal_fab",
            });

            if (result.requires_reason) {
                if (this.actionBtn) this.actionBtn.disabled = false;
                this._showReasonDialog();
                return;
            }

            if (result.error) {
                this._showError(result.error);
                if (this.actionBtn) this.actionBtn.disabled = false;
                return;
            }

            if (result.action === "clock_in") {
                this.isCheckedIn = true;
                this.checkInTime = new Date(result.check_in + "Z");
                this.el.dataset.locationName = result.location_name || "";
                this._startTimer();
            } else if (result.action === "clock_out") {
                this.isCheckedIn = false;
                this.checkInTime = null;
                this._stopTimer();
                await this._fetchStatus();
            }

            this._applyState();
        } catch (e) {
            this._showError("Network error. Please try again.");
        }

        if (this.actionBtn) this.actionBtn.disabled = false;
    }

    // =========================================================================
    // Timer
    // =========================================================================

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

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

    _updateTimer() {
        if (!this.checkInTime) return;
        const now = new Date();
        let diff = Math.max(0, Math.floor((now - this.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);
        const display = pad(h) + ":" + pad(m) + ":" + pad(s);

        if (this.timerEl) this.timerEl.textContent = display;
        if (this.badgeEl) this.badgeEl.textContent = display;
    }

    // =========================================================================
    // Error Display
    // =========================================================================

    _showError(msg) {
        if (this.errorEl) this.errorEl.style.display = "flex";
        if (this.errorText) this.errorText.textContent = msg;
    }

    _clearError() {
        if (this.errorEl) this.errorEl.style.display = "none";
        if (this.errorText) this.errorText.textContent = "";
    }
}

registry.category("public.interactions").add("fusion_clock.portal_fab", FusionClockPortalFAB);
