/**
 * MQTT Sources — CRUD, test, cards.
 */

import { mqttSourcesCache } from '../core/state.ts';
import { fetchWithAuth, escapeHtml } from '../core/api.ts';
import { t } from '../core/i18n.ts';
import { Modal } from '../core/modal.ts';
import { showToast, showConfirm } from '../core/ui.ts';
import { ICON_CLONE, ICON_EDIT, ICON_TEST } from '../core/icons.ts';
import * as P from '../core/icon-paths.ts';
import { wrapCard } from '../core/card-colors.ts';
import { TagInput, renderTagChips } from '../core/tag-input.ts';
import type { MQTTSource } from '../types.ts';

const ICON_MQTT = `<svg class="icon" viewBox="0 0 24 24">${P.radio}</svg>`;

// ── Modal ──

let _mqttTagsInput: TagInput | null = null;

class MQTTSourceModal extends Modal {
    constructor() { super('mqtt-source-modal'); }

    onForceClose() {
        if (_mqttTagsInput) { _mqttTagsInput.destroy(); _mqttTagsInput = null; }
    }

    snapshotValues() {
        return {
            name: (document.getElementById('mqtt-source-name') as HTMLInputElement).value,
            host: (document.getElementById('mqtt-source-host') as HTMLInputElement).value,
            port: (document.getElementById('mqtt-source-port') as HTMLInputElement).value,
            username: (document.getElementById('mqtt-source-username') as HTMLInputElement).value,
            password: (document.getElementById('mqtt-source-password') as HTMLInputElement).value,
            client_id: (document.getElementById('mqtt-source-client-id') as HTMLInputElement).value,
            base_topic: (document.getElementById('mqtt-source-base-topic') as HTMLInputElement).value,
            description: (document.getElementById('mqtt-source-description') as HTMLInputElement).value,
            tags: JSON.stringify(_mqttTagsInput ? _mqttTagsInput.getValue() : []),
        };
    }
}

const mqttSourceModal = new MQTTSourceModal();

// ── Show / Close ──

export async function showMQTTSourceModal(editData: MQTTSource | null = null): Promise<void> {
    const isEdit = !!editData;
    const titleKey = isEdit ? 'mqtt_source.edit' : 'mqtt_source.add';
    document.getElementById('mqtt-source-modal-title')!.innerHTML = `${ICON_MQTT} ${t(titleKey)}`;
    (document.getElementById('mqtt-source-id') as HTMLInputElement).value = editData?.id || '';
    (document.getElementById('mqtt-source-error') as HTMLElement).style.display = 'none';

    if (isEdit) {
        (document.getElementById('mqtt-source-name') as HTMLInputElement).value = editData.name || '';
        (document.getElementById('mqtt-source-host') as HTMLInputElement).value = editData.broker_host || '';
        (document.getElementById('mqtt-source-port') as HTMLInputElement).value = String(editData.broker_port ?? 1883);
        (document.getElementById('mqtt-source-username') as HTMLInputElement).value = editData.username || '';
        (document.getElementById('mqtt-source-password') as HTMLInputElement).value = '';  // never expose
        (document.getElementById('mqtt-source-client-id') as HTMLInputElement).value = editData.client_id || 'ledgrab';
        (document.getElementById('mqtt-source-base-topic') as HTMLInputElement).value = editData.base_topic || 'ledgrab';
        (document.getElementById('mqtt-source-description') as HTMLInputElement).value = editData.description || '';
    } else {
        (document.getElementById('mqtt-source-name') as HTMLInputElement).value = '';
        (document.getElementById('mqtt-source-host') as HTMLInputElement).value = '';
        (document.getElementById('mqtt-source-port') as HTMLInputElement).value = '1883';
        (document.getElementById('mqtt-source-username') as HTMLInputElement).value = '';
        (document.getElementById('mqtt-source-password') as HTMLInputElement).value = '';
        (document.getElementById('mqtt-source-client-id') as HTMLInputElement).value = 'ledgrab';
        (document.getElementById('mqtt-source-base-topic') as HTMLInputElement).value = 'ledgrab';
        (document.getElementById('mqtt-source-description') as HTMLInputElement).value = '';
    }

    // Tags
    if (_mqttTagsInput) { _mqttTagsInput.destroy(); _mqttTagsInput = null; }
    _mqttTagsInput = new TagInput(document.getElementById('mqtt-source-tags-container'), { placeholder: t('tags.placeholder') });
    _mqttTagsInput.setValue(isEdit ? (editData.tags || []) : []);

    // Show/hide test button based on edit mode
    const testBtn = document.getElementById('mqtt-source-test-btn');
    if (testBtn) testBtn.style.display = isEdit ? '' : 'none';

    // Password hint
    const pwHint = document.getElementById('mqtt-source-password-hint');
    if (pwHint) pwHint.style.display = isEdit ? '' : 'none';

    mqttSourceModal.open();
    mqttSourceModal.snapshot();
}

export async function closeMQTTSourceModal(): Promise<void> {
    await mqttSourceModal.close();
}

// ── Save ──

export async function saveMQTTSource(): Promise<void> {
    const id = (document.getElementById('mqtt-source-id') as HTMLInputElement).value;
    const name = (document.getElementById('mqtt-source-name') as HTMLInputElement).value.trim();
    const broker_host = (document.getElementById('mqtt-source-host') as HTMLInputElement).value.trim();
    const broker_port = parseInt((document.getElementById('mqtt-source-port') as HTMLInputElement).value, 10) || 1883;
    const username = (document.getElementById('mqtt-source-username') as HTMLInputElement).value.trim();
    const password = (document.getElementById('mqtt-source-password') as HTMLInputElement).value;
    const client_id = (document.getElementById('mqtt-source-client-id') as HTMLInputElement).value.trim() || 'ledgrab';
    const base_topic = (document.getElementById('mqtt-source-base-topic') as HTMLInputElement).value.trim() || 'ledgrab';
    const description = (document.getElementById('mqtt-source-description') as HTMLInputElement).value.trim() || null;

    if (!name) {
        mqttSourceModal.showError(t('mqtt_source.error.name_required'));
        return;
    }
    if (!id && !broker_host) {
        mqttSourceModal.showError(t('mqtt_source.error.host_required'));
        return;
    }

    const payload: Record<string, any> = {
        name, broker_port, username, client_id, base_topic, description,
        tags: _mqttTagsInput ? _mqttTagsInput.getValue() : [],
    };
    if (broker_host) payload.broker_host = broker_host;
    // Only send password if provided (edit mode may leave blank to keep)
    if (password) payload.password = password;

    try {
        const method = id ? 'PUT' : 'POST';
        const url = id ? `/mqtt/sources/${id}` : '/mqtt/sources';
        const resp = await fetchWithAuth(url, {
            method,
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify(payload),
        });
        if (!resp.ok) {
            const err = await resp.json().catch(() => ({}));
            throw new Error(err.detail || `HTTP ${resp.status}`);
        }
        showToast(t(id ? 'mqtt_source.updated' : 'mqtt_source.created'), 'success');
        mqttSourceModal.forceClose();
        mqttSourcesCache.invalidate();
    } catch (e: any) {
        if (e.isAuth) return;
        mqttSourceModal.showError(e.message);
    }
}

// ── Edit / Clone / Delete ──

export async function editMQTTSource(sourceId: string): Promise<void> {
    try {
        const resp = await fetchWithAuth(`/mqtt/sources/${sourceId}`);
        if (!resp.ok) throw new Error(t('mqtt_source.error.load'));
        const data = await resp.json();
        await showMQTTSourceModal(data);
    } catch (e: any) {
        if (e.isAuth) return;
        showToast(e.message, 'error');
    }
}

export async function cloneMQTTSource(sourceId: string): Promise<void> {
    try {
        const resp = await fetchWithAuth(`/mqtt/sources/${sourceId}`);
        if (!resp.ok) throw new Error(t('mqtt_source.error.load'));
        const data = await resp.json();
        delete data.id;
        data.name = data.name + ' (copy)';
        await showMQTTSourceModal(data);
    } catch (e: any) {
        if (e.isAuth) return;
        showToast(e.message, 'error');
    }
}

export async function deleteMQTTSource(sourceId: string): Promise<void> {
    const confirmed = await showConfirm(t('mqtt_source.delete.confirm'));
    if (!confirmed) return;
    try {
        const resp = await fetchWithAuth(`/mqtt/sources/${sourceId}`, { method: 'DELETE' });
        if (!resp.ok) {
            const err = await resp.json().catch(() => ({}));
            throw new Error(err.detail || `HTTP ${resp.status}`);
        }
        showToast(t('mqtt_source.deleted'), 'success');
        mqttSourcesCache.invalidate();
    } catch (e: any) {
        if (e.isAuth) return;
        showToast(e.message, 'error');
    }
}

// ── Test ──

export async function testMQTTSource(): Promise<void> {
    const id = (document.getElementById('mqtt-source-id') as HTMLInputElement).value;
    if (!id) return;

    const testBtn = document.getElementById('mqtt-source-test-btn');
    if (testBtn) testBtn.classList.add('loading');

    try {
        const resp = await fetchWithAuth(`/mqtt/sources/${id}/test`, { method: 'POST' });
        if (!resp.ok) throw new Error(`HTTP ${resp.status}`);
        const data = await resp.json();
        if (data.success) {
            showToast(t('mqtt_source.test.success'), 'success');
        } else {
            showToast(`${t('mqtt_source.test.failed')}: ${data.error}`, 'error');
        }
    } catch (e: any) {
        if (e.isAuth) return;
        showToast(e.message, 'error');
    } finally {
        if (testBtn) testBtn.classList.remove('loading');
    }
}

async function _testMQTTSourceFromCard(sourceId: string): Promise<void> {
    try {
        const resp = await fetchWithAuth(`/mqtt/sources/${sourceId}/test`, { method: 'POST' });
        if (!resp.ok) throw new Error(`HTTP ${resp.status}`);
        const data = await resp.json();
        if (data.success) {
            showToast(t('mqtt_source.test.success'), 'success');
        } else {
            showToast(`${t('mqtt_source.test.failed')}: ${data.error}`, 'error');
        }
    } catch (e: any) {
        if (e.isAuth) return;
        showToast(e.message, 'error');
    }
}

// ── Card rendering ──

export function createMQTTSourceCard(source: MQTTSource) {
    let healthClass: string, healthTitle: string;
    if (source.connected) {
        healthClass = 'health-online';
        healthTitle = t('mqtt_source.connected');
    } else {
        healthClass = 'health-offline';
        healthTitle = t('mqtt_source.disconnected');
    }
    const statusDot = `<span class="health-dot ${healthClass}" title="${escapeHtml(healthTitle)}" role="status"></span>`;

    return wrapCard({
        type: 'template-card',
        dataAttr: 'data-id',
        id: source.id,
        removeOnclick: `deleteMQTTSource('${source.id}')`,
        removeTitle: t('common.delete'),
        content: `
            <div class="template-card-header">
                <div class="template-name">${ICON_MQTT} ${statusDot} ${escapeHtml(source.name)}</div>
            </div>
            <div class="stream-card-props">
                <span class="stream-card-prop">
                    <svg class="icon" viewBox="0 0 24 24">${P.wifi}</svg> ${escapeHtml(source.broker_host)}:${source.broker_port}
                </span>
                <span class="stream-card-prop">
                    <svg class="icon" viewBox="0 0 24 24">${P.hash}</svg> ${escapeHtml(source.base_topic)}
                </span>
            </div>
            ${renderTagChips(source.tags)}
            ${source.description ? `<div class="template-config" style="opacity:0.7;">${escapeHtml(source.description)}</div>` : ''}`,
        actions: `
                <button class="btn btn-icon btn-secondary" data-action="test" title="${t('mqtt_source.test')}">${ICON_TEST}</button>
                <button class="btn btn-icon btn-secondary" data-action="clone" title="${t('common.clone')}">${ICON_CLONE}</button>
                <button class="btn btn-icon btn-secondary" data-action="edit" title="${t('common.edit')}">${ICON_EDIT}</button>`,
    });
}

// ── Event delegation ──

const _mqttSourceActions: Record<string, (id: string) => void> = {
    test: (id) => _testMQTTSourceFromCard(id),
    clone: cloneMQTTSource,
    edit: editMQTTSource,
};

export function initMQTTSourceDelegation(container: HTMLElement): void {
    container.addEventListener('click', (e: MouseEvent) => {
        const btn = (e.target as HTMLElement).closest<HTMLElement>('[data-action]');
        if (!btn) return;

        const section = btn.closest<HTMLElement>('[data-card-section="mqtt-sources"]');
        if (!section) return;
        const card = btn.closest<HTMLElement>('[data-id]');
        if (!card) return;

        const action = btn.dataset.action;
        const id = card.getAttribute('data-id');
        if (!action || !id) return;

        const handler = _mqttSourceActions[action];
        if (handler) {
            e.stopPropagation();
            handler(id);
        }
    });
}

// ── Expose to global scope for HTML template onclick handlers ──

window.showMQTTSourceModal = showMQTTSourceModal;
window.closeMQTTSourceModal = closeMQTTSourceModal;
window.saveMQTTSource = saveMQTTSource;
window.editMQTTSource = editMQTTSource;
window.cloneMQTTSource = cloneMQTTSource;
window.deleteMQTTSource = deleteMQTTSource;
window.testMQTTSource = testMQTTSource;
