/**
 * Daily Notification Plugin Test Console
 * Textual-inspired operator console for test execution
 */

// State management
const ConsoleState = {
    plan: null,
    runId: null,
    runState: {},
    currentPhase: null,
    currentTest: null,
    currentStep: null,
    evidence: {},
    feed: []
};

// Initialize console
async function initConsole() {
    try {
        // Generate run ID
        ConsoleState.runId = generateRunId();
        updateHeader();

        // Load test plan
        const planResponse = await fetch('plan.json');
        ConsoleState.plan = await planResponse.json();

        // Load saved run state
        loadRunState();

        // Render UI
        renderPhaseTree();
        renderEmptyState();

        // Setup event listeners
        setupEventListeners();

        // Setup Capacitor plugin listener (if available)
        setupCapacitorListener();

        // Add initial feed message
        addFeedLine('INFO', 'console', 'Console initialized', 'Console ready');

    } catch (error) {
        console.error('Failed to initialize console:', error);
        addFeedLine('ERROR', 'console', 'Initialization failed', error.message);
    }
}

// Generate run ID
function generateRunId() {
    const now = new Date();
    const dateStr = now.toISOString().slice(0, 10).replace(/-/g, '');
    const timeStr = now.toTimeString().slice(0, 8).replace(/:/g, '');
    const random = Math.random().toString(36).substring(2, 6);
    return `${dateStr}_${timeStr}_${random}`;
}

// Update header
function updateHeader() {
    const runIdEl = document.getElementById('run-id');
    if (runIdEl) {
        runIdEl.textContent = ConsoleState.runId;
    }

    // Try to get device info from Capacitor
    if (window.Capacitor && window.Capacitor.Plugins.Device) {
        window.Capacitor.Plugins.Device.getInfo().then(info => {
            const deviceIdEl = document.getElementById('device-id');
            if (deviceIdEl) {
                deviceIdEl.textContent = info.model || 'unknown';
            }
        }).catch(() => {
        });
    }
}

// Load run state from localStorage
function loadRunState() {
    const saved = localStorage.getItem(`runState_${ConsoleState.runId}`);
    if (saved) {
        try {
            ConsoleState.runState = JSON.parse(saved);
        } catch (e) {
            console.error('Failed to parse saved run state:', e);
        }
    }
}

// Save run state to localStorage
function saveRunState() {
    try {
        localStorage.setItem(`runState_${ConsoleState.runId}`, JSON.stringify(ConsoleState.runState));
    } catch (e) {
        console.error('Failed to save run state:', e);
    }
}

// Render phase tree
function renderPhaseTree() {
    const treeEl = document.getElementById('phase-tree');
    if (!treeEl || !ConsoleState.plan) return;

    treeEl.innerHTML = '';

    ConsoleState.plan.phases.forEach(phase => {
        const phaseEl = createPhaseElement(phase);
        treeEl.appendChild(phaseEl);
    });
}

// Create phase element
function createPhaseElement(phase) {
    const phaseDiv = document.createElement('div');
    phaseDiv.className = 'phase-item';

    const phaseState = getPhaseState(phase.id);
    const statusIcon = getStatusIcon(phaseState.status);
    const progress = getPhaseProgress(phase.id);

    const header = document.createElement('div');
    header.className = 'phase-header';
    header.innerHTML = `
        <span class="phase-status">${statusIcon}</span>
        <span class="phase-title">${phase.title}</span>
        <span class="phase-progress">${progress}</span>
    `;
    header.onclick = () => togglePhase(phase.id);

    phaseDiv.appendChild(header);

    // Test list (initially hidden, shown when phase expanded)
    const testList = document.createElement('div');
    testList.className = 'test-list';
    testList.style.display = 'none';
    testList.id = `test-list-${phase.id}`;

    phase.tests.forEach(test => {
        const testEl = createTestElement(phase.id, test);
        testList.appendChild(testEl);
    });

    phaseDiv.appendChild(testList);

    return phaseDiv;
}

// Create test element
function createTestElement(phaseId, test) {
    const testDiv = document.createElement('div');
    testDiv.className = 'test-item';
    testDiv.id = `test-${phaseId}-${test.id}`;

    const testState = getTestState(phaseId, test.id);
    const statusIcon = getStatusIcon(testState.status);

    testDiv.innerHTML = `
        <span class="test-status">${statusIcon}</span>
        <span class="test-title">${test.title}</span>
    `;

    testDiv.onclick = () => selectTest(phaseId, test.id);

    return testDiv;
}

// Get phase state
function getPhaseState(phaseId) {
    if (!ConsoleState.runState.phases) {
        ConsoleState.runState.phases = {};
    }
    if (!ConsoleState.runState.phases[phaseId]) {
        ConsoleState.runState.phases[phaseId] = { status: 'pending' };
    }
    return ConsoleState.runState.phases[phaseId];
}

// Get test state
function getTestState(phaseId, testId) {
    if (!ConsoleState.runState.phases) {
        ConsoleState.runState.phases = {};
    }
    if (!ConsoleState.runState.phases[phaseId]) {
        ConsoleState.runState.phases[phaseId] = { tests: {} };
    }
    if (!ConsoleState.runState.phases[phaseId].tests) {
        ConsoleState.runState.phases[phaseId].tests = {};
    }
    if (!ConsoleState.runState.phases[phaseId].tests[testId]) {
        ConsoleState.runState.phases[phaseId].tests[testId] = { status: 'pending', steps: {} };
    }
    return ConsoleState.runState.phases[phaseId].tests[testId];
}

// Get step state
function getStepState(phaseId, testId, stepId) {
    const testState = getTestState(phaseId, testId);
    if (!testState.steps) {
        testState.steps = {};
    }
    if (!testState.steps[stepId]) {
        testState.steps[stepId] = { status: 'pending' };
    }
    return testState.steps[stepId];
}

// Get status icon
function getStatusIcon(status) {
    const icons = {
        'pending': '·',
        'running': '→',
        'pass': '✓',
        'warn': '⚠',
        'fail': '✗',
        'skip': '⊘'
    };
    return icons[status] || '·';
}

// Get phase progress
function getPhaseProgress(phaseId) {
    const phase = ConsoleState.plan.phases.find(p => p.id === phaseId);
    if (!phase) return '(0/0)';

    let completed = 0;
    let total = phase.tests.length;

    phase.tests.forEach(test => {
        const testState = getTestState(phaseId, test.id);
        if (testState.status === 'pass' || testState.status === 'warn') {
            completed++;
        }
    });

    return `(${completed}/${total})`;
}

// Toggle phase expansion
function togglePhase(phaseId) {
    const testList = document.getElementById(`test-list-${phaseId}`);
    if (testList) {
        testList.style.display = testList.style.display === 'none' ? 'block' : 'none';
    }
}

// Select test
function selectTest(phaseId, testId) {
    ConsoleState.currentPhase = phaseId;
    ConsoleState.currentTest = testId;

    // Update active test highlight
    document.querySelectorAll('.test-item').forEach(el => {
        el.classList.remove('active');
    });
    const testEl = document.getElementById(`test-${phaseId}-${testId}`);
    if (testEl) {
        testEl.classList.add('active');
    }

    // Render test view
    renderTestView(phaseId, testId);
}

// Render test view
function renderTestView(phaseId, testId) {
    const phase = ConsoleState.plan.phases.find(p => p.id === phaseId);
    if (!phase) return;

    const test = phase.tests.find(t => t.id === testId);
    if (!test) return;

    // Hide empty state
    document.getElementById('empty-state').style.display = 'none';

    // Show test header
    const testHeader = document.getElementById('test-header');
    testHeader.style.display = 'block';
    document.getElementById('test-title').textContent = `${phase.title} / ${test.title}`;
    document.getElementById('test-purpose').textContent = test.purpose;

    // Render step checklist
    renderStepChecklist(phaseId, testId, test.steps);

    // Render current step (first step or active step)
    const activeStepId = getActiveStepId(phaseId, testId, test.steps);
    if (activeStepId) {
        renderCurrentStep(phaseId, testId, activeStepId, test.steps);
    }

    // Show sections
    document.getElementById('step-checklist-section').style.display = 'block';
    document.getElementById('current-step-section').style.display = 'block';
}

// Render step checklist
function renderStepChecklist(phaseId, testId, steps) {
    const checklistEl = document.getElementById('step-checklist');
    if (!checklistEl) return;

    checklistEl.innerHTML = '';

    steps.forEach((step, index) => {
        const stepState = getStepState(phaseId, testId, step.id);
        const statusIcon = getStatusIcon(stepState.status);

        const stepEl = document.createElement('div');
        stepEl.className = 'step-item';
        if (step.id === ConsoleState.currentStep) {
            stepEl.classList.add('active');
        }

        stepEl.innerHTML = `
            <span class="step-checkbox">${statusIcon}</span>
            <span class="step-number">${index + 1}/${steps.length}</span>
            <span class="step-name">${step.title}</span>
            <span class="step-type-badge">${step.type}</span>
        `;

        stepEl.onclick = () => {
            ConsoleState.currentStep = step.id;
            renderCurrentStep(phaseId, testId, step.id, steps);
            renderStepChecklist(phaseId, testId, steps); // Re-render to update active
        };

        checklistEl.appendChild(stepEl);
    });
}

// Get active step ID
function getActiveStepId(phaseId, testId, steps) {
    // Find first step that's not pass
    for (const step of steps) {
        const stepState = getStepState(phaseId, testId, step.id);
        if (stepState.status !== 'pass') {
            return step.id;
        }
    }
    // If all passed, return last step
    return steps.length > 0 ? steps[steps.length - 1].id : null;
}

// Render current step
function renderCurrentStep(phaseId, testId, stepId, steps) {
    const step = steps.find(s => s.id === stepId);
    if (!step) return;

    ConsoleState.currentStep = stepId;

    // Update step header
    document.getElementById('step-title').textContent = step.title;
    document.getElementById('step-type').textContent = step.type + (step.blocking ? ' (blocking)' : '');

    // Update step content
    document.getElementById('step-purpose').textContent = step.purpose || '—';
    document.getElementById('step-instructions').innerHTML = formatList(step.instructions || []);
    document.getElementById('step-expected').innerHTML = formatList(step.expected || []);
    document.getElementById('step-artifacts').innerHTML = formatList(step.artifacts || []);

    // Update step actions
    const stepState = getStepState(phaseId, testId, stepId);
    updateStepActions(phaseId, testId, stepId, stepState);
}

// Format list as HTML
function formatList(items) {
    if (!items || items.length === 0) return '—';
    return '<ul>' + items.map(item => `<li>${item}</li>`).join('') + '</ul>';
}

// Update step actions
function updateStepActions(phaseId, testId, stepId, stepState) {
    const btnDone = document.getElementById('btn-step-done');
    const btnFail = document.getElementById('btn-step-fail');

    if (stepState.status === 'pass') {
        btnDone.disabled = true;
        btnDone.textContent = 'Done ✓';
    } else {
        btnDone.disabled = false;
        btnDone.textContent = 'Mark Done ✓';
    }

    if (stepState.status === 'fail') {
        btnFail.disabled = true;
        btnFail.textContent = 'Failed ✗';
    } else {
        btnFail.disabled = false;
        btnFail.textContent = 'Mark Fail ✗';
    }
}

// Setup event listeners
function setupEventListeners() {
    // Step action buttons
    document.getElementById('btn-step-done').onclick = () => {
        if (ConsoleState.currentPhase && ConsoleState.currentTest && ConsoleState.currentStep) {
            markStepDone(ConsoleState.currentPhase, ConsoleState.currentTest, ConsoleState.currentStep);
        }
    };

    document.getElementById('btn-step-fail').onclick = () => {
        if (ConsoleState.currentPhase && ConsoleState.currentTest && ConsoleState.currentStep) {
            markStepFail(ConsoleState.currentPhase, ConsoleState.currentTest, ConsoleState.currentStep);
        }
    };

    document.getElementById('btn-step-notes').onclick = () => {
        if (ConsoleState.currentPhase && ConsoleState.currentTest && ConsoleState.currentStep) {
            showStepNotes();
        }
    };

    // Evidence panel
    document.getElementById('btn-evidence-close').onclick = () => {
        document.getElementById('evidence-panel').style.display = 'none';
    };

    // Feed clear
    document.getElementById('btn-feed-clear').onclick = () => {
        ConsoleState.feed = [];
        renderLiveFeed();
    };
}

// Mark step done
function markStepDone(phaseId, testId, stepId) {
    const stepState = getStepState(phaseId, testId, stepId);
    stepState.status = 'pass';
    stepState.completedAt = new Date().toISOString();

    saveRunState();
    updateTestStatus(phaseId, testId);
    renderTestView(phaseId, testId);

    addFeedLine('INFO', stepId, 'Step completed', `Step marked as done`);
}

// Mark step fail
function markStepFail(phaseId, testId, stepId) {
    const stepState = getStepState(phaseId, testId, stepId);
    stepState.status = 'fail';
    stepState.failedAt = new Date().toISOString();

    saveRunState();
    updateTestStatus(phaseId, testId);
    renderTestView(phaseId, testId);

    addFeedLine('ERROR', stepId, 'Step failed', `Step marked as failed`);
}

// Update test status based on steps
function updateTestStatus(phaseId, testId) {
    const phase = ConsoleState.plan.phases.find(p => p.id === phaseId);
    if (!phase) return;

    const test = phase.tests.find(t => t.id === testId);
    if (!test) return;

    const testState = getTestState(phaseId, testId);
    let hasFail = false;
    let hasWarn = false;
    let allPass = true;

    test.steps.forEach(step => {
        const stepState = getStepState(phaseId, testId, step.id);
        if (stepState.status === 'fail') {
            hasFail = true;
            allPass = false;
        } else if (stepState.status === 'warn') {
            hasWarn = true;
            allPass = false;
        } else if (stepState.status !== 'pass') {
            allPass = false;
        }
    });

    if (hasFail) {
        testState.status = 'fail';
    } else if (hasWarn) {
        testState.status = 'warn';
    } else if (allPass) {
        testState.status = 'pass';
    } else {
        testState.status = 'running';
    }

    saveRunState();
    renderPhaseTree(); // Update phase tree to reflect new status
}

// Show step notes
function showStepNotes() {
    const stepState = getStepState(ConsoleState.currentPhase, ConsoleState.currentTest, ConsoleState.currentStep);
    const notes = prompt('Add notes for this step:', stepState.notes || '');
    if (notes !== null) {
        stepState.notes = notes;
        saveRunState();
    }
}

// Render empty state
function renderEmptyState() {
    document.getElementById('empty-state').style.display = 'block';
    document.getElementById('test-header').style.display = 'none';
    document.getElementById('step-checklist-section').style.display = 'none';
    document.getElementById('current-step-section').style.display = 'none';
}

// Add feed line
function addFeedLine(level, source, category, message) {
    const timestamp = new Date().toLocaleTimeString();
    const line = {
        timestamp,
        level,
        source,
        category,
        message
    };

    ConsoleState.feed.push(line);

    // Keep feed to last 100 lines
    if (ConsoleState.feed.length > 100) {
        ConsoleState.feed.shift();
    }

    renderLiveFeed();
}

// Render live feed
function renderLiveFeed() {
    const feedEl = document.getElementById('live-feed');
    if (!feedEl) return;

    feedEl.innerHTML = ConsoleState.feed.map(line => {
        return `<div class="feed-line ${line.level}">
            <span class="feed-timestamp">${line.timestamp}</span>
            <span>${line.level}</span>
            <span>${line.source}</span>
            <span>${line.message}</span>
        </div>`;
    }).join('');

    // Auto-scroll to bottom
    feedEl.scrollTop = feedEl.scrollHeight;
}

// Setup Capacitor listener for test events
function setupCapacitorListener() {
    if (window.Capacitor && window.Capacitor.Plugins.TestEvents) {
        window.Capacitor.Plugins.TestEvents.addListener('testEvent', (event) => {
            handleTestEvent(event.payload);
        });
    } else {
        // Fallback: poll for events file (if scripts write to /sdcard/Download/dnp-events.jsonl)
        // This is a simple fallback - in production, use broadcast
        console.log('TestEvents plugin not available, using fallback polling');
    }
}

// Handle test event from scripts
function handleTestEvent(eventData) {
    try {
        const event = typeof eventData === 'string' ? JSON.parse(eventData) : eventData;

        // Update step/test status based on event
        if (event.phaseId && event.testId && event.stepId) {
            const stepState = getStepState(event.phaseId, event.testId, event.stepId);

            if (event.type === 'step_start') {
                stepState.status = 'running';
                stepState.startedAt = event.ts;
            } else if (event.type === 'step_pass') {
                stepState.status = 'pass';
                stepState.completedAt = event.ts;
            } else if (event.type === 'step_warn') {
                stepState.status = 'warn';
                stepState.completedAt = event.ts;
            } else if (event.type === 'step_fail') {
                stepState.status = 'fail';
                stepState.failedAt = event.ts;
            }

            updateTestStatus(event.phaseId, event.testId);

            // Re-render if this is the current test
            if (ConsoleState.currentPhase === event.phaseId && ConsoleState.currentTest === event.testId) {
                const phase = ConsoleState.plan.phases.find(p => p.id === event.phaseId);
                if (phase) {
                    const test = phase.tests.find(t => t.id === event.testId);
                    if (test) {
                        renderTestView(event.phaseId, event.testId);
                    }
                }
            }
        }

        // Add to feed
        addFeedLine(event.level || 'INFO', event.stepId || event.testId || 'system', event.type || 'event', event.message || JSON.stringify(event));

        // Handle artifacts
        if (event.type === 'artifact' && event.artifact) {
            addEvidence(event.phaseId, event.testId, event.artifact);
        }

        saveRunState();

    } catch (error) {
        console.error('Failed to handle test event:', error);
        addFeedLine('ERROR', 'system', 'event_handler', `Failed to process event: ${error.message}`);
    }
}

// Add evidence
function addEvidence(phaseId, testId, artifact) {
    if (!ConsoleState.evidence[phaseId]) {
        ConsoleState.evidence[phaseId] = {};
    }
    if (!ConsoleState.evidence[phaseId][testId]) {
        ConsoleState.evidence[phaseId][testId] = [];
    }

    ConsoleState.evidence[phaseId][testId].push(artifact);
    renderEvidence(phaseId, testId);
}

// Render evidence
function renderEvidence(phaseId, testId) {
    if (ConsoleState.currentPhase !== phaseId || ConsoleState.currentTest !== testId) {
        return; // Not viewing this test
    }

    const evidenceList = document.getElementById('evidence-list');
    if (!evidenceList) return;

    const artifacts = ConsoleState.evidence[phaseId]?.[testId] || [];
    evidenceList.innerHTML = '';

    if (artifacts.length === 0) {
        evidenceList.innerHTML = '<div style="color: #858585; padding: 20px; text-align: center;">No evidence captured yet</div>';
        return;
    }

    artifacts.forEach(artifact => {
        const item = document.createElement('div');
        item.className = 'evidence-item';

        const icon = getArtifactIcon(artifact.kind);
        const name = artifact.name || artifact.path || 'Unknown';

        item.innerHTML = `
            <span class="evidence-icon">${icon}</span>
            <span class="evidence-name">${name}</span>
            <a href="#" class="evidence-action" onclick="viewEvidence('${artifact.path || ''}')">view</a>
        `;

        evidenceList.appendChild(item);
    });

    // Show evidence panel
    document.getElementById('evidence-panel').style.display = 'block';
}

// Get artifact icon
function getArtifactIcon(kind) {
    const icons = {
        'alarms': '📋',
        'logs': '📄',
        'screen': '📷',
        'notes': '📝'
    };
    return icons[kind] || '📎';
}

// View evidence (placeholder)
function viewEvidence(path) {
    addFeedLine('INFO', 'evidence', 'view', `Viewing evidence: ${path}`);
    // In a real implementation, this would open the file or show it in a modal
    alert(`Evidence file: ${path}\n\nIn production, this would open the file viewer.`);
}

// Initialize on load
document.addEventListener('DOMContentLoaded', initConsole);

