/**
 * FormationsUIManager - Handles DOM updates and formation card rendering
 */
class FormationsUIManager {
    constructor() {
        this.targetEl = null;
        this.instructionsEl = null;
        this.nameControlsEl = null;
        this.nameInputEl = null;
        this.instructionTextEl = null;
        this.pointsStatusEl = null;
        this.onDeleteFormation = null;
        this.onEditFormation = null;
    }

    /**
     * Initializes the UI elements.
     * @param {string} targetId - ID of the formations list container
     */
    initUI(targetId) {
        this.targetEl = document.getElementById(targetId);
        if (!this.targetEl) {
            console.warn(`Formations container "${targetId}" not found.`);
        }

        this.instructionsEl = document.getElementById('formation_drawing_instructions');
        this.nameControlsEl = document.getElementById('formation_name_controls');
        this.nameInputEl = document.getElementById('formation_name_input');
        this.instructionTextEl = document.getElementById('formation_instruction_text');
        this.pointsStatusEl = document.getElementById('formation_points_status');
    }

    /**
     * Register callback for delete formation.
     * @param {Function} callback - Function to call when delete is clicked
     */
    registerDeleteCallback(callback) {
        this.onDeleteFormation = callback;
    }

    /**
     * Register callback for edit formation.
     * @param {Function} callback - Function to call when edit is clicked
     */
    registerEditCallback(callback) {
        this.onEditFormation = callback;
    }

    /**
     * Show drawing instructions for a formation type.
     * @param {string} type - Formation type
     * @param {number} pointsNeeded - Number of points needed
     */
    showDrawingInstructions(type, pointsNeeded) {
        // Hide name controls if visible
        if (this.nameControlsEl) {
            this.nameControlsEl.style.display = 'none';
        }

        // Show instructions
        if (this.instructionsEl) {
            this.instructionsEl.style.display = 'block';
        }

        // Set instruction text based on type
        const instructions = {
            'support_resistance': 'Click on chart to place a line. Drag anchors to adjust.',
            'channel': 'Click to place first line, then click to place parallel line.'
        };
        if (this.instructionTextEl) {
            this.instructionTextEl.textContent = instructions[type] || 'Click on chart to place points';
        }

        // Update points status (for single-click types, show descriptive text)
        if (type === 'support_resistance') {
            if (this.pointsStatusEl) {
                this.pointsStatusEl.textContent = 'Click anywhere on the chart';
                this.pointsStatusEl.style.color = '#667eea';
            }
        } else if (type === 'channel') {
            if (this.pointsStatusEl) {
                this.pointsStatusEl.textContent = 'Step 1: Click to place primary line';
                this.pointsStatusEl.style.color = '#667eea';
            }
        } else {
            this.updatePointsStatus(0, pointsNeeded);
        }
    }

    /**
     * Update the points status display.
     * @param {number} current - Current points placed
     * @param {number} needed - Points needed
     */
    updatePointsStatus(current, needed) {
        if (this.pointsStatusEl) {
            this.pointsStatusEl.textContent = `Points: ${current} / ${needed}`;
            // Change color when complete
            this.pointsStatusEl.style.color = current >= needed ? '#28a745' : '#667eea';
        }
    }

    /**
     * Show name input after points are placed.
     */
    showNameInput() {
        // Hide instructions
        if (this.instructionsEl) {
            this.instructionsEl.style.display = 'none';
        }

        // Show name controls
        if (this.nameControlsEl) {
            this.nameControlsEl.style.display = 'block';
        }

        // Focus and clear input
        if (this.nameInputEl) {
            this.nameInputEl.value = '';
            this.nameInputEl.focus();
        }
    }

    /**
     * Hide all drawing-related UI.
     */
    hideAllDrawingUI() {
        if (this.instructionsEl) {
            this.instructionsEl.style.display = 'none';
        }
        if (this.nameControlsEl) {
            this.nameControlsEl.style.display = 'none';
        }
    }

    /**
     * Legacy method - kept for compatibility
     */
    showDrawingControls() {
        // Now handled by showDrawingInstructions and showNameInput
    }

    /**
     * Legacy method - kept for compatibility
     */
    hideDrawingControls() {
        this.hideAllDrawingUI();
    }

    /**
     * Get the formation name from input.
     * @returns {string} Formation name
     */
    getFormationName() {
        return this.nameInputEl ? this.nameInputEl.value.trim() : '';
    }

    /**
     * Render all formations as cards.
     * @param {Array} formations - List of formation objects
     */
    renderFormations(formations) {
        if (!this.targetEl) {
            console.warn("Formations container not initialized");
            return;
        }

        this.targetEl.innerHTML = '';

        if (!formations || formations.length === 0) {
            this.targetEl.innerHTML = '<p style="color: #888; font-size: 12px; padding: 10px;">No formations yet. Click a button above to draw one.</p>';
            return;
        }

        formations.forEach(formation => {
            const card = this._createFormationCard(formation);
            this.targetEl.appendChild(card);
        });
    }

    /**
     * Create a formation card element.
     * @param {Object} formation - Formation data
     * @returns {HTMLElement} Card element
     */
    _createFormationCard(formation) {
        const card = document.createElement('div');
        card.className = 'formation-item';
        card.dataset.tblKey = formation.tbl_key;
        card.dataset.type = formation.formation_type;

        // Format type for display
        const typeDisplay = this._formatType(formation.formation_type);

        card.innerHTML = `
            <div class="formation-icon">
                <span class="formation-name">${this._escapeHtml(formation.name)}</span>
                <span class="formation-type">${typeDisplay}</span>
            </div>
            <button class="edit-button" title="Edit">&#9998;</button>
            <button class="delete-button" title="Delete">&times;</button>
            <div class="formation-hover">
                <strong>${this._escapeHtml(formation.name)}</strong>
                <div class="formation-details">
                    <span>Type: ${typeDisplay}</span>
                    <span><span class="formation-color-dot" style="background: ${formation.color}"></span>Color</span>
                    <span>Scope: ${formation.exchange}/${formation.market}/${formation.timeframe}</span>
                </div>
            </div>
        `;

        // Add click handlers
        const deleteBtn = card.querySelector('.delete-button');
        deleteBtn.addEventListener('click', (e) => {
            e.stopPropagation();
            if (this.onDeleteFormation) {
                this.onDeleteFormation(formation.tbl_key, formation.name);
            }
        });

        const editBtn = card.querySelector('.edit-button');
        editBtn.addEventListener('click', (e) => {
            e.stopPropagation();
            if (this.onEditFormation) {
                this.onEditFormation(formation.tbl_key);
            }
        });

        // Card click to select
        card.addEventListener('click', () => {
            this._selectCard(card);
            if (this.onEditFormation) {
                this.onEditFormation(formation.tbl_key);
            }
        });

        return card;
    }

    /**
     * Select a card visually.
     * @param {HTMLElement} card - Card to select
     */
    _selectCard(card) {
        // Deselect all
        this.targetEl.querySelectorAll('.formation-item').forEach(c => {
            c.classList.remove('selected');
        });
        // Select this one
        card.classList.add('selected');
    }

    /**
     * Format formation type for display.
     * @param {string} type - Formation type
     * @returns {string} Formatted type
     */
    _formatType(type) {
        const typeMap = {
            'support_resistance': 'Line',
            'channel': 'Channel',
            'triangle': 'Triangle',
            'head_shoulders': 'H&S',
            'double_bottom': 'Double Bottom',
            'double_top': 'Double Top'
        };
        return typeMap[type] || type;
    }

    /**
     * Escape HTML to prevent XSS.
     * @param {string} str - String to escape
     * @returns {string} Escaped string
     */
    _escapeHtml(str) {
        const div = document.createElement('div');
        div.textContent = str;
        return div.innerHTML;
    }
}


/**
 * FormationsDataManager - Manages in-memory formations data
 */
class FormationsDataManager {
    constructor() {
        this.formations = [];
    }

    /**
     * Set all formations.
     * @param {Array} formations - List of formations
     */
    setFormations(formations) {
        this.formations = Array.isArray(formations) ? formations : [];
    }

    /**
     * Get all formations.
     * @returns {Array} List of formations
     */
    getAllFormations() {
        return this.formations;
    }

    /**
     * Add a new formation.
     * @param {Object} formation - Formation to add
     */
    addFormation(formation) {
        if (formation) {
            this.formations.push(formation);
        }
    }

    /**
     * Update an existing formation.
     * @param {Object} updatedFormation - Updated formation data
     */
    updateFormation(updatedFormation) {
        const index = this.formations.findIndex(f => f.tbl_key === updatedFormation.tbl_key);
        if (index !== -1) {
            this.formations[index] = { ...this.formations[index], ...updatedFormation };
        }
    }

    /**
     * Remove a formation by tbl_key.
     * @param {string} tblKey - Formation tbl_key to remove
     */
    removeFormation(tblKey) {
        this.formations = this.formations.filter(f => f.tbl_key !== tblKey);
    }

    /**
     * Get a formation by tbl_key.
     * @param {string} tblKey - Formation tbl_key
     * @returns {Object|null} Formation or null
     */
    getFormation(tblKey) {
        return this.formations.find(f => f.tbl_key === tblKey) || null;
    }
}


/**
 * Formations - Main coordinator class for formations feature
 */
class Formations {
    constructor(ui) {
        this.ui = ui;
        this.comms = ui?.data?.comms;
        this.data = ui?.data;

        this.dataManager = new FormationsDataManager();
        this.uiManager = new FormationsUIManager();
        this.overlay = null;

        // Current drawing state
        this.drawingMode = null;
        this.currentScope = null;

        // Set up callbacks
        this.uiManager.registerDeleteCallback(this.deleteFormation.bind(this));
        this.uiManager.registerEditCallback(this.selectFormation.bind(this));

        this._initialized = false;
    }

    /**
     * Initialize the formations system.
     * @param {string} targetId - ID of formations list container
     */
    initialize(targetId) {
        try {
            this.uiManager.initUI(targetId);

            if (!this.comms) {
                console.error("Communications instance not available for Formations");
                return;
            }

            // Register socket handlers
            this.registerSocketHandlers();

            // Get current scope from chart data
            // Note: bt_data uses 'exchange_name' not 'exchange', and 'timeframe' not 'interval'
            this.currentScope = {
                exchange: this.data?.exchange || window.bt_data?.exchange_name || 'binance',
                market: this.data?.trading_pair || window.bt_data?.trading_pair || 'BTC/USDT',
                timeframe: this.data?.interval || window.bt_data?.timeframe || '1h'
            };

            // Fetch formations for current scope
            this.fetchFormations();

            this._initialized = true;
            console.log("Formations initialized for scope:", this.currentScope);

        } catch (error) {
            console.error("Error initializing Formations:", error);
        }
    }

    /**
     * Initialize the SVG overlay for drawing.
     * @param {string} chartContainerId - ID of chart container
     * @param {Object} chart - Lightweight Charts instance
     * @param {Object} candleSeries - Candlestick series for coordinate conversion
     */
    initOverlay(chartContainerId, chart, candleSeries) {
        if (typeof FormationOverlay !== 'undefined') {
            this.overlay = new FormationOverlay(chartContainerId, chart, candleSeries);
            this.overlay.setOnSaveCallback(this.saveFormation.bind(this));
            console.log("Formation overlay initialized");
        } else {
            console.warn("FormationOverlay class not loaded");
        }
    }

    /**
     * Register socket handlers for formations.
     */
    registerSocketHandlers() {
        this.comms.on('formations', this.handleFormationsResponse.bind(this));
        this.comms.on('formation_created', this.handleFormationCreated.bind(this));
        this.comms.on('formation_updated', this.handleFormationUpdated.bind(this));
        this.comms.on('formation_deleted', this.handleFormationDeleted.bind(this));
        this.comms.on('formation_error', this.handleFormationError.bind(this));
    }

    /**
     * Fetch formations for current scope.
     */
    fetchFormations() {
        if (!this.comms || !this.currentScope) return;

        this.comms.sendToApp('request_formations', this.currentScope);
    }

    // ================ Socket Handlers ================

    /**
     * Handle formations list response.
     * @param {Object} data - Response with formations array
     */
    handleFormationsResponse(data) {
        console.log("Received formations:", data);
        const formations = data.formations || [];
        this.dataManager.setFormations(formations);
        this.uiManager.renderFormations(formations);

        // Render on overlay if available
        if (this.overlay) {
            this.overlay.clearAllFormations();
            formations.forEach(f => this.overlay.renderFormation(f));
        }
    }

    /**
     * Handle formation created event.
     * @param {Object} data - Response with formation data
     */
    handleFormationCreated(data) {
        console.log("Formation created:", data);
        if (data.success && data.formation) {
            this.dataManager.addFormation(data.formation);
            this.uiManager.renderFormations(this.dataManager.getAllFormations());

            if (this.overlay) {
                this.overlay.renderFormation(data.formation);
            }

            this.uiManager.hideAllDrawingUI();
            this.drawingMode = null;
        } else {
            alert(`Failed to create formation: ${data.message}`);
        }
    }

    /**
     * Handle formation updated event.
     * @param {Object} data - Response with updated formation data
     */
    handleFormationUpdated(data) {
        console.log("Formation updated:", data);
        if (data.success && data.formation) {
            this.dataManager.updateFormation(data.formation);
            this.uiManager.renderFormations(this.dataManager.getAllFormations());

            if (this.overlay) {
                this.overlay.updateFormation(data.formation);
            }
        } else {
            alert(`Failed to update formation: ${data.message}`);
        }
    }

    /**
     * Handle formation deleted event.
     * @param {Object} data - Response with tbl_key of deleted formation
     */
    handleFormationDeleted(data) {
        console.log("Formation deleted:", data);
        if (data.success && data.tbl_key) {
            this.dataManager.removeFormation(data.tbl_key);
            this.uiManager.renderFormations(this.dataManager.getAllFormations());

            if (this.overlay) {
                this.overlay.removeFormation(data.tbl_key);
            }
        }
    }

    /**
     * Handle formation error.
     * @param {Object} data - Error data
     */
    handleFormationError(data) {
        console.error("Formation error:", data.message);
        alert(`Formation error: ${data.message}`);
    }

    // ================ Drawing Methods ================

    /**
     * Get points needed for a formation type.
     * @param {string} type - Formation type
     * @returns {number}
     */
    _getPointsNeeded(type) {
        const pointsMap = {
            'support_resistance': 1,  // Single click creates line with 3 anchors
            'channel': 2  // Two clicks: primary line + parallel line placement
        };
        return pointsMap[type] || 2;
    }

    /**
     * Start drawing a new formation.
     * @param {string} type - Formation type ('support_resistance', 'channel')
     */
    startDrawing(type) {
        console.log("Starting drawing mode:", type);
        this.drawingMode = type;

        const pointsNeeded = this._getPointsNeeded(type);

        // Show drawing instructions (not name input yet)
        this.uiManager.showDrawingInstructions(type, pointsNeeded);

        // Tell overlay to start drawing, with callbacks
        if (this.overlay) {
            this.overlay.setOnPointsChangedCallback(this._onPointsChanged.bind(this));
            this.overlay.setOnDraftReadyCallback(this._onDraftReady.bind(this));
            this.overlay.startDrawing(type);
        }
    }

    /**
     * Called when points are added/changed during drawing.
     * @param {number} currentPoints - Current number of points
     * @param {number} pointsNeeded - Points needed for completion
     */
    _onPointsChanged(currentPoints, pointsNeeded) {
        // For single-click formations, use _onDraftReady instead
        if (this.drawingMode === 'support_resistance') {
            return;
        }

        // For channel, update status based on step
        if (this.drawingMode === 'channel') {
            if (this.uiManager.pointsStatusEl) {
                if (currentPoints === 1) {
                    this.uiManager.pointsStatusEl.textContent = 'Step 2: Move mouse and click to place parallel line';
                    this.uiManager.pointsStatusEl.style.color = '#667eea';
                }
            }
            return;
        }

        // Update the UI status for other multi-point drawings
        this.uiManager.updatePointsStatus(currentPoints, pointsNeeded);

        // If we have enough points, show the name input
        if (currentPoints >= pointsNeeded) {
            this.uiManager.showNameInput();
        }
    }

    /**
     * Called when a draft formation is ready (line/channel placed, can be named).
     */
    _onDraftReady() {
        // Update status based on formation type
        if (this.uiManager.pointsStatusEl) {
            if (this.drawingMode === 'channel') {
                this.uiManager.pointsStatusEl.textContent = 'Channel placed! Drag anchors to adjust.';
            } else {
                this.uiManager.pointsStatusEl.textContent = 'Line placed! Drag anchors to adjust.';
            }
            this.uiManager.pointsStatusEl.style.color = '#28a745';
        }

        // Show name input
        this.uiManager.showNameInput();
    }

    /**
     * Complete the current drawing.
     */
    completeDrawing() {
        const name = this.uiManager.getFormationName();
        if (!name) {
            alert("Please enter a formation name");
            return;
        }

        if (this.overlay) {
            this.overlay.completeDrawing(name);
        }
    }

    /**
     * Cancel the current drawing.
     */
    cancelDrawing() {
        this.drawingMode = null;
        this.uiManager.hideAllDrawingUI();

        if (this.overlay) {
            this.overlay.cancelDrawing();
        }
    }

    /**
     * Save a formation (callback from overlay).
     * @param {Object} formationData - Formation data to save
     */
    saveFormation(formationData) {
        if (!this.comms) return;

        const payload = {
            ...formationData,
            ...this.currentScope
        };

        this.comms.sendToApp('new_formation', payload);
    }

    /**
     * Select a formation for editing.
     * @param {string} tblKey - Formation tbl_key
     */
    selectFormation(tblKey) {
        console.log("Selecting formation:", tblKey);
        if (this.overlay) {
            this.overlay.selectFormation(tblKey);
        }
    }

    /**
     * Delete a formation.
     * @param {string} tblKey - Formation tbl_key
     * @param {string} name - Formation name (for confirmation)
     */
    deleteFormation(tblKey, name) {
        if (!confirm(`Delete formation "${name}"?`)) {
            return;
        }

        if (this.comms) {
            if (!this.comms.connectionOpen) {
                alert('Server connection is offline. Delete will be sent after reconnect.');
            }
            this.comms.sendToApp('delete_formation', { tbl_key: tblKey });
        }
    }

    /**
     * Update a formation's lines (called from overlay after drag).
     * @param {string} tblKey - Formation tbl_key
     * @param {Object} linesData - Updated lines data
     */
    updateFormationLines(tblKey, linesData) {
        if (!this.comms) return;

        this.comms.sendToApp('edit_formation', {
            tbl_key: tblKey,
            lines_json: JSON.stringify(linesData)
        });
    }
}
