// Fusion Chatter Enhance
// Copyright 2024-2026 Nexa Systems Inc.
// License OPL-1
//
// Resizable & collapsible chatter panel with per-user position preference.
//
// ARCHITECTURE:
//   1. On script load: read localStorage, inject <style> for anti-flash.
//   2. On DOMContentLoaded: read odoo.__session_info__ (server-injected),
//      sync to localStorage, then apply the definitive layout.
//   3. MutationObserver re-applies layout on SPA navigations.
//   4. No RPC calls needed -- preferences come from session_info.

(function () {
    'use strict';

    var STORAGE_KEY_WIDTH    = 'fce_chatter_width';
    var STORAGE_KEY_HIDDEN   = 'fce_chatter_hidden';
    var STORAGE_KEY_POSITION = 'fce_chatter_position';
    var MIN_CHATTER_PCT  = 15;
    var MAX_CHATTER_PCT  = 50;
    var DEFAULT_CHATTER_PCT = 20;
    var STYLE_TAG_ID = 'fce-width-override';

    var TOOLTIPS = {
        '.o-mail-Chatter-sendMessage': 'Send Message',
        '.o-mail-Chatter-logNote': 'Log Note',
        'button[data-hotkey="shift+w"]': 'WhatsApp',
        '.o-mail-Chatter-activity': 'Schedule Activity',
        '.fusion-notes-mic-btn': 'Record Voice Note',
        '.o-mail-Chatter-messageAuthorizer': 'Message Authorizer',
    };

    var _enhanceTimer = null;
    var _sessionSynced = false;

    // =========================================================================
    // EARLY <style> INJECTION  (runs before DOM is ready)
    // =========================================================================

    var SEL_RENDERER = '.o_action_manager .o_form_view .o_form_renderer';
    var SEL_SHEET    = SEL_RENDERER + ':not(.fce-chatter-bottom) > .o_form_sheet_bg';
    var SEL_CHATTER  = SEL_RENDERER + ':not(.fce-chatter-bottom) > .o-mail-ChatterContainer, ' +
                       SEL_RENDERER + ':not(.fce-chatter-bottom) > .o-mail-Form-chatter, ' +
                       SEL_RENDERER + ':not(.fce-chatter-bottom) > .o-aside';

    function buildWidthCss(chatterPct) {
        var formPct = 100 - chatterPct;
        return '@media (min-width:992px){' +
            SEL_SHEET + '{flex:0 0 ' + formPct + '% !important;width:' + formPct + '% !important;max-width:' + formPct + '% !important;}' +
            SEL_CHATTER + '{flex:0 0 ' + chatterPct + '% !important;width:' + chatterPct + '% !important;}' +
        '}';
    }

    function injectOrUpdateStyleTag(css) {
        var tag = document.getElementById(STYLE_TAG_ID);
        if (!tag) {
            tag = document.createElement('style');
            tag.id = STYLE_TAG_ID;
            tag.setAttribute('type', 'text/css');
            (document.head || document.documentElement).appendChild(tag);
        }
        tag.textContent = css;
    }

    // =========================================================================
    // SESSION INFO READER
    // =========================================================================

    function getSessionInfo() {
        try {
            var o = window.odoo;
            if (!o) return null;
            return o.__session_info__ || o.session_info || null;
        } catch (_) {}
        return null;
    }

    function syncFromSessionInfo() {
        if (_sessionSynced) return;
        var si = getSessionInfo();
        if (!si || !si.uid) return;
        _sessionSynced = true;
        if (si.chatter_position) {
            localStorage.setItem(STORAGE_KEY_POSITION, si.chatter_position);
        }
        if (typeof si.chatter_hidden === 'boolean') {
            localStorage.setItem(STORAGE_KEY_HIDDEN, si.chatter_hidden ? '1' : '0');
        }
    }

    function applyEarlyStyles() {
        syncFromSessionInfo();
        var pos = localStorage.getItem(STORAGE_KEY_POSITION) || 'side';
        if (pos === 'bottom') {
            injectOrUpdateStyleTag('');
            return;
        }
        if (localStorage.getItem(STORAGE_KEY_HIDDEN) === '1') {
            injectOrUpdateStyleTag(buildWidthCss(0));
            return;
        }
        var raw = localStorage.getItem(STORAGE_KEY_WIDTH);
        var pct = raw ? parseFloat(raw) : NaN;
        if (isNaN(pct) || pct < MIN_CHATTER_PCT || pct > MAX_CHATTER_PCT) pct = DEFAULT_CHATTER_PCT;
        injectOrUpdateStyleTag(buildWidthCss(pct));
    }

    applyEarlyStyles();

    // =========================================================================
    // WRITE HELPERS (save to backend)
    // =========================================================================

    function getSessionUid() {
        var si = getSessionInfo();
        return si && si.uid ? si.uid : null;
    }

    function rpcCall(model, method, args, kwargs, callback) {
        try {
            var xhr = new XMLHttpRequest();
            xhr.open('POST', '/web/dataset/call_kw/' + model + '/' + method, true);
            xhr.setRequestHeader('Content-Type', 'application/json');
            xhr.onreadystatechange = function () {
                if (xhr.readyState !== 4) return;
                if (xhr.status !== 200) { if (callback) callback(null); return; }
                try {
                    var resp = JSON.parse(xhr.responseText);
                    if (resp && resp.error) { if (callback) callback(null); return; }
                    if (callback) callback(resp && resp.result);
                } catch (_) {
                    if (callback) callback(null);
                }
            };
            xhr.send(JSON.stringify({
                jsonrpc: '2.0',
                method: 'call',
                params: { model: model, method: method, args: args, kwargs: kwargs || {} },
            }));
        } catch (_) {
            if (callback) callback(null);
        }
    }

    function saveHiddenPref(hidden) {
        localStorage.setItem(STORAGE_KEY_HIDDEN, hidden ? '1' : '0');
        var uid = getSessionUid();
        if (!uid) return;
        rpcCall('res.users', 'write', [[uid], { chatter_hidden: hidden }], {}, null);
    }

    // =========================================================================
    // STORAGE HELPERS
    // =========================================================================

    function getStoredWidth() {
        var v = localStorage.getItem(STORAGE_KEY_WIDTH);
        var n = v ? parseFloat(v) : NaN;
        if (isNaN(n) || n < MIN_CHATTER_PCT || n > MAX_CHATTER_PCT) return DEFAULT_CHATTER_PCT;
        return n;
    }

    function getStoredPosition() {
        return localStorage.getItem(STORAGE_KEY_POSITION) || 'side';
    }

    function isHidden() {
        return localStorage.getItem(STORAGE_KEY_HIDDEN) === '1';
    }

    // =========================================================================
    // DOM FINDERS
    // =========================================================================

    function findFormRenderer() {
        return document.querySelector('.o_action_manager .o_form_view .o_form_renderer');
    }

    function findChatterEl(renderer) {
        if (!renderer) return null;
        return renderer.querySelector('.o-mail-ChatterContainer') ||
               renderer.querySelector('.o-mail-Form-chatter') ||
               renderer.querySelector('.o-aside');
    }

    function findSheetBg(renderer) {
        if (!renderer) return null;
        return renderer.querySelector('.o_form_sheet_bg');
    }

    // =========================================================================
    // WIDTH APPLICATION
    // =========================================================================

    function applyWidths(renderer, chatterPct) {
        injectOrUpdateStyleTag(buildWidthCss(chatterPct));
        var sheet = findSheetBg(renderer);
        var chatter = findChatterEl(renderer);
        if (!sheet || !chatter) return;
        var formPct = 100 - chatterPct;
        sheet.style.flex = '0 0 ' + formPct + '%';
        sheet.style.width = formPct + '%';
        sheet.style.maxWidth = formPct + '%';
        sheet.style.minWidth = '0';
        chatter.style.flex = '0 0 ' + chatterPct + '%';
        chatter.style.width = chatterPct + '%';
    }

    function clearInlineWidths(renderer) {
        var sheet = findSheetBg(renderer);
        var chatter = findChatterEl(renderer);
        if (sheet) sheet.removeAttribute('style');
        if (chatter) chatter.removeAttribute('style');
    }

    // =========================================================================
    // RESIZE HANDLE
    // =========================================================================

    function injectResizeHandle(renderer) {
        if (renderer.querySelector('.fce-resize-handle')) return;
        var chatter = findChatterEl(renderer);
        if (!chatter) return;

        var handle = document.createElement('div');
        handle.className = 'fce-resize-handle';
        chatter.parentNode.insertBefore(handle, chatter);

        var startX = 0;
        var startWidth = 0;

        function onMouseDown(e) {
            e.preventDefault();
            startX = e.clientX;
            startWidth = chatter.getBoundingClientRect().width;
            handle.classList.add('fce-dragging');
            document.addEventListener('mousemove', onMouseMove);
            document.addEventListener('mouseup', onMouseUp);
            document.body.style.cursor = 'col-resize';
            document.body.style.userSelect = 'none';
        }

        function onMouseMove(e) {
            var delta = startX - e.clientX;
            var rendererWidth = renderer.getBoundingClientRect().width;
            var newWidth = startWidth + delta;
            var pct = (newWidth / rendererWidth) * 100;
            pct = Math.max(MIN_CHATTER_PCT, Math.min(MAX_CHATTER_PCT, pct));
            applyWidths(renderer, pct);
        }

        function onMouseUp() {
            handle.classList.remove('fce-dragging');
            document.removeEventListener('mousemove', onMouseMove);
            document.removeEventListener('mouseup', onMouseUp);
            document.body.style.cursor = '';
            document.body.style.userSelect = '';

            var rendererWidth = renderer.getBoundingClientRect().width;
            var chatterWidth = chatter.getBoundingClientRect().width;
            var pct = Math.round((chatterWidth / rendererWidth) * 100);
            localStorage.setItem(STORAGE_KEY_WIDTH, String(pct));
            injectOrUpdateStyleTag(buildWidthCss(pct));
        }

        handle.addEventListener('mousedown', onMouseDown);
    }

    // =========================================================================
    // TOGGLE / EXPAND BUTTONS
    // =========================================================================

    function injectToggleBtn(renderer) {
        if (renderer.querySelector('.fce-toggle-btn') || renderer.querySelector('.fce-expand-btn')) return;
        var chatter = findChatterEl(renderer);
        if (!chatter) return;

        var btn = document.createElement('button');
        btn.className = 'fce-toggle-btn';
        btn.type = 'button';
        btn.innerHTML = '<i class="fa fa-chevron-right"></i>';
        btn.title = 'Hide chatter';
        chatter.style.position = 'relative';
        chatter.appendChild(btn);

        btn.addEventListener('click', function () {
            saveHiddenPref(true);
            renderer.classList.add('fce-chatter-hidden');
            injectOrUpdateStyleTag(buildWidthCss(0));
            btn.remove();
            injectExpandBtn(renderer);
        });
    }

    function injectExpandBtn(renderer) {
        if (renderer.querySelector('.fce-expand-btn')) return;

        var btn = document.createElement('button');
        btn.className = 'fce-expand-btn';
        btn.type = 'button';
        btn.innerHTML = '<i class="fa fa-chevron-left"></i>';
        btn.title = 'Show chatter';
        renderer.appendChild(btn);

        btn.addEventListener('click', function () {
            saveHiddenPref(false);
            renderer.classList.remove('fce-chatter-hidden');
            btn.remove();
            var savedPct = getStoredWidth();
            applyWidths(renderer, savedPct);
            injectResizeHandle(renderer);
            injectToggleBtn(renderer);
        });
    }

    // =========================================================================
    // TOOLTIPS
    // =========================================================================

    function applyTooltips() {
        var keys = Object.keys(TOOLTIPS);
        for (var i = 0; i < keys.length; i++) {
            var selector = keys[i];
            var title = TOOLTIPS[selector];
            var els = document.querySelectorAll(selector);
            for (var j = 0; j < els.length; j++) {
                if (!els[j].getAttribute('title')) els[j].setAttribute('title', title);
            }
        }
    }

    // =========================================================================
    // LAYOUT APPLICATION
    // =========================================================================

    function applyLayout(renderer) {
        var pos = getStoredPosition();
        var hidden = isHidden();

        if (pos === 'bottom') {
            renderer.classList.add('fce-chatter-bottom');
            renderer.classList.remove('fce-chatter-hidden');
            injectOrUpdateStyleTag('');
            removeEl(renderer, '.fce-resize-handle');
            removeEl(renderer, '.fce-toggle-btn');
            removeEl(renderer, '.fce-expand-btn');
            renderer.style.display = 'block';
            var sheet = findSheetBg(renderer);
            var chatter = findChatterEl(renderer);
            if (sheet) {
                sheet.style.flex = 'none';
                sheet.style.width = '100%';
                sheet.style.maxWidth = '100%';
                sheet.style.minWidth = '100%';
            }
            if (chatter) {
                chatter.style.flex = 'none';
                chatter.style.width = '100%';
                chatter.style.maxWidth = '100%';
                chatter.style.minWidth = '100%';
            }
            return;
        }

        renderer.classList.remove('fce-chatter-bottom');
        renderer.style.display = '';

        if (hidden) {
            renderer.classList.add('fce-chatter-hidden');
            injectOrUpdateStyleTag(buildWidthCss(0));
            removeEl(renderer, '.fce-resize-handle');
            removeEl(renderer, '.fce-toggle-btn');
            injectExpandBtn(renderer);
            return;
        }

        renderer.classList.remove('fce-chatter-hidden');
        removeEl(renderer, '.fce-expand-btn');
        var savedPct = getStoredWidth();
        applyWidths(renderer, savedPct);
        injectResizeHandle(renderer);
        injectToggleBtn(renderer);
        applyTooltips();
    }

    function removeEl(renderer, selector) {
        var el = renderer.querySelector(selector);
        if (el) el.remove();
    }

    // =========================================================================
    // MAIN ORCHESTRATOR
    // =========================================================================

    function enhance() {
        var renderer = findFormRenderer();
        if (!renderer) return;
        var chatter = findChatterEl(renderer);
        if (!chatter) return;
        if (window.innerWidth < 992) return;

        syncFromSessionInfo();
        applyLayout(renderer);
    }

    function debouncedEnhance() {
        if (_enhanceTimer) clearTimeout(_enhanceTimer);
        _enhanceTimer = setTimeout(enhance, 150);
    }

    var observer = new MutationObserver(debouncedEnhance);

    function boot() {
        syncFromSessionInfo();
        applyEarlyStyles();
        observer.observe(document.body, { childList: true, subtree: true });
        enhance();
    }

    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', boot);
    } else {
        boot();
    }
})();
