{% extends "shared/frontend/base.html" %}

{% block title %}Telefoni - BMC Hub{% endblock %}

{% block content %}
<div class="container-fluid">
    <div class="d-flex align-items-center justify-content-between mb-4">
        <div>
            <h2 class="mb-1"><i class="bi bi-telephone me-2"></i>Telefoni</h2>
            <div class="text-muted small">Opkaldslog fra Yealink Action URL (Established/Terminated)</div>
        </div>
    </div>

    <div class="card border-0 shadow-sm mb-4">
        <div class="card-body">
            <div class="row g-3 align-items-end">
                <div class="col-md-3">
                    <label class="form-label">Bruger</label>
                    <select id="filterUser" class="form-select">
                        <option value="">Alle</option>
                    </select>
                </div>
                <div class="col-md-3">
                    <label class="form-label">Dato fra</label>
                    <input id="filterFrom" type="date" class="form-control" />
                </div>
                <div class="col-md-3">
                    <label class="form-label">Dato til</label>
                    <input id="filterTo" type="date" class="form-control" />
                </div>
                <div class="col-md-2">
                    <div class="form-check">
                        <input class="form-check-input" type="checkbox" id="filterWithoutCase" />
                        <label class="form-check-label" for="filterWithoutCase">Kun uden sag</label>
                    </div>
                </div>
                <div class="col-md-1">
                    <button id="btnRefresh" class="btn btn-primary w-100">
                        <i class="bi bi-arrow-clockwise"></i>
                    </button>
                </div>
            </div>
        </div>
    </div>

    <div class="card border-0 shadow-sm">
        <div class="card-body">
            <div class="table-responsive">
                <table class="table table-hover align-middle mb-0">
                    <thead>
                        <tr>
                            <th>Dato</th>
                            <th>Bruger</th>
                            <th>Retning</th>
                            <th>Nummer</th>
                            <th>Kontakt</th>
                            <th>Sag</th>
                            <th class="text-end">Varighed</th>
                        </tr>
                    </thead>
                    <tbody id="telefoniRows">
                        {% if initial_calls and initial_calls|length > 0 %}
                            {% for call in initial_calls %}
                            <tr
                                data-call-id="{{ call.id }}"
                                data-direction="{{ call.direction or '' }}"
                                data-display-number="{{ call.display_number or '' }}"
                                data-ekstern-nummer="{{ call.display_number or '' }}"
                                data-started-at="{{ call.started_at or '' }}"
                                data-ended-at="{{ call.ended_at or '' }}"
                                data-duration-sec="{{ call.duration_sec if call.duration_sec is not none else '' }}"
                                data-kontakt-id="{{ call.kontakt_id if call.kontakt_id is not none else '' }}"
                                data-contact-name="{{ call.contact_name or '' }}"
                                data-sag-id="{{ call.sag_id if call.sag_id is not none else '' }}"
                                data-sag-titel="{{ call.sag_titel or '' }}"
                                data-full-name="{{ call.full_name or '' }}"
                                data-username="{{ call.username or '' }}"
                            >
                                <td>{{ call.started_at or '-' }}</td>
                                <td>{{ call.full_name or call.username or '-' }}</td>
                                <td>{% if call.direction == 'outbound' %}Udgående{% else %}Indgående{% endif %}</td>
                                <td>
                                    {% if call.display_number %}
                                        <div class="d-flex gap-2 align-items-center flex-wrap">
                                            <span>{{ call.display_number }}</span>
                                            <button type="button" class="btn btn-sm btn-outline-success" onclick="callViaYealink('{{ call.display_number|replace("'", "\\'") }}')">Ring op</button>
                                        </div>
                                    {% else %}
                                        -
                                    {% endif %}
                                </td>
                                <td>
                                    {% if call.kontakt_id %}
                                        <div class="d-flex align-items-center gap-2 flex-wrap">
                                            <a href="/contacts/{{ call.kontakt_id }}">{{ (call.contact_name or ('Kontakt #' ~ call.kontakt_id))|trim }}</a>
                                            <button type="button" class="btn btn-sm btn-outline-secondary" onclick="openLinkContactModal({{ call.id }})" title="Skift kontakt / opret kontakt">
                                                <i class="bi bi-person-gear"></i>
                                            </button>
                                            <button type="button" class="btn btn-sm btn-outline-danger" onclick="unlinkContact({{ call.id }})" title="Fjern kontakt-link">
                                                <i class="bi bi-x-circle"></i>
                                            </button>
                                        </div>
                                    {% else %}
                                        <div class="d-flex gap-2">
                                            <button type="button" class="btn btn-sm btn-outline-secondary" onclick="openLinkContactModal({{ call.id }})" title="Tilknyt eller opret kontakt">
                                                <i class="bi bi-person-plus"></i>
                                            </button>
                                        </div>
                                    {% endif %}
                                </td>
                                <td>
                                    {% if call.sag_id %}
                                        <div class="d-flex gap-2 align-items-center flex-wrap">
                                            <a href="/sag/{{ call.sag_id }}/v3">{{ call.sag_titel or ('Sag #' ~ call.sag_id) }}</a>
                                            <button type="button" class="btn btn-sm btn-outline-secondary" onclick="linkExistingCase({{ call.id }})" title="Skift sag-link">
                                                <i class="bi bi-link-45deg"></i>
                                            </button>
                                            <button type="button" class="btn btn-sm btn-outline-danger" onclick="unlinkCase({{ call.id }})" title="Fjern sag-link">
                                                <i class="bi bi-x-circle"></i>
                                            </button>
                                        </div>
                                    {% else %}
                                        <div class="d-flex gap-2">
                                            <a class="btn btn-sm btn-outline-primary" href="/sag/new?telefoni_opkald_id={{ call.id }}{% if call.kontakt_id %}&contact_id={{ call.kontakt_id }}{% endif %}" title="Opret ny sag">
                                                <i class="bi bi-folder-plus"></i>
                                            </a>
                                            <button type="button" class="btn btn-sm btn-outline-secondary" onclick="linkExistingCase({{ call.id }})" title="Tilknyt eksisterende sag">
                                                <i class="bi bi-link-45deg"></i>
                                            </button>
                                        </div>
                                    {% endif %}
                                </td>
                                <td class="text-end">{{ call.duration_sec if call.duration_sec is not none else '-' }}</td>
                            </tr>
                            {% endfor %}
                        {% else %}
                            <tr><td colspan="7" class="text-muted small">Indlæser...</td></tr>
                        {% endif %}
                    </tbody>
                </table>
            </div>
        </div>
    </div>
</div>

<div class="modal fade" id="linkContactModal" tabindex="-1" aria-hidden="true">
    <div class="modal-dialog modal-lg modal-dialog-scrollable">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title">Knyt eller opret kontakt</h5>
                <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Luk"></button>
            </div>
            <div class="modal-body">
                <div id="linkContactContext" class="small text-muted mb-3">Opkald: -</div>

                <div class="mb-3">
                    <label for="linkContactSearch" class="form-label">Søg eksisterende kontakt</label>
                    <input id="linkContactSearch" type="text" class="form-control" placeholder="Søg navn, email, telefon..." autocomplete="off" />
                </div>
                <div id="linkContactSelected" class="alert alert-secondary py-2 mb-3">Ingen kontakt valgt</div>
                <div id="linkContactResults" class="list-group mb-3"></div>

                <hr>

                <h6 class="mb-3">Eller opret ny kontakt</h6>
                <div class="row g-3">
                    <div class="col-md-6">
                        <label for="newContactFirstName" class="form-label">Fornavn</label>
                        <input id="newContactFirstName" type="text" class="form-control" placeholder="Fornavn" />
                    </div>
                    <div class="col-md-6">
                        <label for="newContactLastName" class="form-label">Efternavn</label>
                        <input id="newContactLastName" type="text" class="form-control" placeholder="Efternavn" />
                    </div>
                    <div class="col-md-6">
                        <label for="newContactPhone" class="form-label">Telefon</label>
                        <input id="newContactPhone" type="text" class="form-control" placeholder="Telefonnummer" />
                    </div>
                    <div class="col-md-6">
                        <label for="newContactEmail" class="form-label">Email</label>
                        <input id="newContactEmail" type="email" class="form-control" placeholder="mail@firma.dk" />
                    </div>
                    <div class="col-md-12">
                        <label for="newContactTitle" class="form-label">Titel</label>
                        <input id="newContactTitle" type="text" class="form-control" placeholder="Fx IT-ansvarlig" />
                    </div>
                </div>

                <hr>

                <h6 class="mb-3">Eller brug firmaets hovednummer</h6>
                <div class="mb-3">
                    <label for="linkCompanySearch" class="form-label">Søg firma</label>
                    <input id="linkCompanySearch" type="text" class="form-control" placeholder="Søg firmanavn (min. 2 tegn)" autocomplete="off" />
                </div>
                <div id="linkCompanySelected" class="alert alert-secondary py-2 mb-3">Intet firma valgt</div>
                <div id="linkCompanyResults" class="list-group"></div>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-outline-secondary" data-bs-dismiss="modal">Luk</button>
                <button type="button" id="linkContactConfirm" class="btn btn-primary" disabled>Knyt kontakt</button>
                <button type="button" id="createContactConfirm" class="btn btn-success">Opret og knyt</button>
                <button type="button" id="createCompanyCaseConfirm" class="btn btn-warning">Opret sag på firma</button>
            </div>
        </div>
    </div>
</div>

<div class="modal fade" id="linkSagModal" tabindex="-1" aria-hidden="true">
    <div class="modal-dialog modal-lg modal-dialog-scrollable">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title">Link opkald til sag</h5>
                <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Luk"></button>
            </div>
            <div class="modal-body">
                <div id="linkSagContext" class="small text-muted mb-3">Opkald: -</div>
                <div class="mb-3">
                    <label for="linkSagSearch" class="form-label">Søg sag</label>
                    <input id="linkSagSearch" type="text" class="form-control" placeholder="Søg på titel, kunde eller ID" autocomplete="off" />
                </div>
                <div class="mb-3">
                    <label for="linkSagIdManual" class="form-label">Eller indtast sag-ID manuelt</label>
                    <input id="linkSagIdManual" type="number" min="1" step="1" class="form-control" placeholder="Fx 1234" />
                </div>
                <div id="linkSagSelected" class="alert alert-secondary py-2 mb-3">Ingen sag valgt</div>
                <div id="linkSagResults" class="list-group"></div>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-outline-secondary" data-bs-dismiss="modal">Annuller</button>
                <button type="button" id="linkSagConfirm" class="btn btn-primary" disabled>Link sag</button>
            </div>
        </div>
    </div>
</div>

<script>
function fmtDuration(sec, endedAt) {
    if (sec === null || sec === undefined) return endedAt ? '-' : 'I gang';
    const s = Number(sec);
    if (!Number.isFinite(s) || s < 0) return endedAt ? '-' : 'I gang';
    const mm = Math.floor(s / 60);
    const ss = s % 60;
    return `${mm}:${String(ss).padStart(2,'0')}`;
}

function escapeHtml(str) {
    return String(str ?? '')
        .replaceAll('&', '&amp;')
        .replaceAll('<', '&lt;')
        .replaceAll('>', '&gt;')
        .replaceAll('"', '&quot;')
        .replaceAll("'", '&#039;');
}

function normalizeDisplayNumber(value) {
    const raw = String(value || '').trim();
    if (!raw) return '';

    // Internal SIP identifiers should not be shown as external caller numbers.
    if (/^sip:/i.test(raw)) {
        const sipDigits = raw.replace(/\D+/g, '');
        if (sipDigits.length <= 6) return '';
    }

    const digits = raw.replace(/\D+/g, '');
    if (!digits) return raw;

    // E.164 max is 15 digits (excluding +). Longer values are malformed/concatenated.
    if (digits.length > 15) {
        if (digits.length >= 10 && digits.slice(0, 2) === '45') {
            return `+${digits.slice(0, 10)}`;
        }
        if (digits.length >= 8 && /[2-9]/.test(digits.charAt(0))) {
            return `+45${digits.slice(0, 8)}`;
        }
        if (digits.length >= 10 && digits.slice(-10).startsWith('45')) {
            return `+${digits.slice(-10)}`;
        }
        if (digits.length >= 8) {
            return `+45${digits.slice(-8)}`;
        }
    }

    if (raw.startsWith('+')) {
        return digits.length >= 9 ? `+${digits}` : raw;
    }

    if (digits.length === 8) return `+45${digits}`;
    if (digits.length === 10 && digits.startsWith('45')) return `+${digits}`;
    if (digits.length >= 9) return `+${digits}`;
    return raw;
}

let telefoniCurrentUserId = null;
const telefoniCallMap = new Map();
const linkSagState = {
    callId: null,
    selectedSagId: null,
    selectedLabel: '',
    searchTimer: null,
    searchToken: 0,
    modal: null
};
const linkContactState = {
    callId: null,
    selectedContactId: null,
    selectedLabel: '',
    searchTimer: null,
    companySearchTimer: null,
    searchToken: 0,
    companySearchToken: 0,
    modal: null,
    number: '',
    mode: 'contact',
    selectedCompanyId: null,
    selectedCompanyLabel: ''
};

async function ensureCurrentUserId() {
    if (telefoniCurrentUserId !== null) return telefoniCurrentUserId;
    try {
        const res = await fetch('/api/v1/auth/me', { credentials: 'include' });
        if (!res.ok) return null;
        const me = await res.json();
        telefoniCurrentUserId = Number(me?.id) || null;
        return telefoniCurrentUserId;
    } catch (e) {
        return null;
    }
}

function getLinkSagModalInstance() {
    if (!linkSagState.modal) {
        const el = document.getElementById('linkSagModal');
        if (!el || !window.bootstrap) return null;
        linkSagState.modal = new bootstrap.Modal(el);
    }
    return linkSagState.modal;
}

function getLinkContactModalInstance() {
    if (!linkContactState.modal) {
        const el = document.getElementById('linkContactModal');
        if (!el || !window.bootstrap) return null;
        linkContactState.modal = new bootstrap.Modal(el);
    }
    return linkContactState.modal;
}

function setLinkContactSelected(contactId, label) {
    const selected = document.getElementById('linkContactSelected');
    const confirmBtn = document.getElementById('linkContactConfirm');
    const numericContactId = Number(contactId);
    if (!Number.isInteger(numericContactId) || numericContactId <= 0) {
        linkContactState.selectedContactId = null;
        linkContactState.selectedLabel = '';
        if (selected) {
            selected.className = 'alert alert-secondary py-2 mb-3';
            selected.textContent = 'Ingen kontakt valgt';
        }
        if (confirmBtn) confirmBtn.disabled = true;
        return;
    }

    linkContactState.selectedContactId = numericContactId;
    linkContactState.selectedLabel = String(label || `Kontakt #${numericContactId}`);
    if (selected) {
        selected.className = 'alert alert-success py-2 mb-3';
        selected.textContent = `Valgt: ${linkContactState.selectedLabel} (ID: ${numericContactId})`;
    }
    if (confirmBtn) confirmBtn.disabled = false;
}

function setLinkCompanySelected(companyId, label) {
    const selected = document.getElementById('linkCompanySelected');
    const numericCompanyId = Number(companyId);
    if (!Number.isInteger(numericCompanyId) || numericCompanyId <= 0) {
        linkContactState.selectedCompanyId = null;
        linkContactState.selectedCompanyLabel = '';
        if (selected) {
            selected.className = 'alert alert-secondary py-2 mb-3';
            selected.textContent = 'Intet firma valgt';
        }
        return;
    }

    linkContactState.selectedCompanyId = numericCompanyId;
    linkContactState.selectedCompanyLabel = String(label || `Firma #${numericCompanyId}`);
    if (selected) {
        selected.className = 'alert alert-success py-2 mb-3';
        selected.textContent = `Valgt: ${linkContactState.selectedCompanyLabel} (ID: ${numericCompanyId})`;
    }
}

function renderLinkContactResults(results) {
    const container = document.getElementById('linkContactResults');
    if (!container) return;

    if (!results || results.length === 0) {
        container.innerHTML = '<div class="alert alert-light border mb-0">Ingen kontakter fundet</div>';
        return;
    }

    container.innerHTML = (results || []).map((item) => {
        const cid = Number(item.id);
        const name = `${item.first_name || ''} ${item.last_name || ''}`.trim() || `Kontakt #${cid}`;
        const email = String(item.email || '-');
        const phone = String(item.mobile || item.phone || '-');
        return `
            <button type="button" class="list-group-item list-group-item-action" data-contact-id="${cid}" data-contact-label="${escapeHtml(name)}">
                <div class="fw-semibold">${escapeHtml(name)}</div>
                <div class="small text-muted">${escapeHtml(email)} · ${escapeHtml(phone)}</div>
            </button>
        `;
    }).join('');

    container.querySelectorAll('[data-contact-id]').forEach((btn) => {
        btn.addEventListener('click', () => {
            const cid = Number(btn.getAttribute('data-contact-id'));
            const label = btn.getAttribute('data-contact-label') || `Kontakt #${cid}`;
            setLinkContactSelected(cid, label);
        });
    });
}

async function searchContacts(query) {
    const token = ++linkContactState.searchToken;
    const container = document.getElementById('linkContactResults');
    if (container) {
        container.innerHTML = '<div class="alert alert-light border mb-0"><span class="spinner-border spinner-border-sm me-2"></span>Søger...</div>';
    }

    try {
        const qs = new URLSearchParams({ search: query || '', limit: '30', offset: '0' });
        const res = await fetch(`/api/v1/contacts?${qs.toString()}`, { credentials: 'include' });
        if (token !== linkContactState.searchToken) return;
        if (!res.ok) {
            if (container) container.innerHTML = '<div class="alert alert-danger mb-0">Kunne ikke søge kontakter</div>';
            return;
        }
        const data = await res.json();
        const results = Array.isArray(data?.contacts) ? data.contacts : [];
        renderLinkContactResults(results);
    } catch (e) {
        if (token !== linkContactState.searchToken) return;
        if (container) container.innerHTML = '<div class="alert alert-danger mb-0">Fejl under søgning</div>';
    }
}

async function patchCallContact(callId, contactId) {
    const res = await fetch(`/api/v1/telefoni/calls/${callId}`, {
        method: 'PATCH',
        headers: { 'Content-Type': 'application/json' },
        credentials: 'include',
        body: JSON.stringify({ kontakt_id: contactId })
    });
    if (!res.ok) {
        const t = await res.text();
        throw new Error(t || `HTTP ${res.status}`);
    }
}

function renderCompanyResults(results) {
    const container = document.getElementById('linkCompanyResults');
    if (!container) return;

    if (!results || results.length === 0) {
        container.innerHTML = '<div class="alert alert-light border mb-0">Ingen firmaer fundet</div>';
        return;
    }

    container.innerHTML = (results || []).map((item) => {
        const cid = Number(item.id);
        const name = String(item.name || `Firma #${cid}`);
        const cvr = String(item.cvr_nummer || item.cvr_number || '-');
        return `
            <button type="button" class="list-group-item list-group-item-action" data-company-id="${cid}" data-company-label="${escapeHtml(name)}">
                <div class="fw-semibold">${escapeHtml(name)}</div>
                <div class="small text-muted">CVR: ${escapeHtml(cvr)}</div>
            </button>
        `;
    }).join('');

    container.querySelectorAll('[data-company-id]').forEach((btn) => {
        btn.addEventListener('click', () => {
            const cid = Number(btn.getAttribute('data-company-id'));
            const label = btn.getAttribute('data-company-label') || `Firma #${cid}`;
            setLinkCompanySelected(cid, label);
        });
    });
}

async function searchCompanies(query) {
    const token = ++linkContactState.companySearchToken;
    const container = document.getElementById('linkCompanyResults');
    if (container) {
        container.innerHTML = '<div class="alert alert-light border mb-0"><span class="spinner-border spinner-border-sm me-2"></span>Søger...</div>';
    }

    try {
        const res = await fetch(`/api/v1/search/customers?q=${encodeURIComponent(query || '')}`, { credentials: 'include' });
        if (token !== linkContactState.companySearchToken) return;
        if (!res.ok) {
            if (container) container.innerHTML = '<div class="alert alert-danger mb-0">Kunne ikke søge firmaer</div>';
            return;
        }
        const data = await res.json();
        renderCompanyResults(Array.isArray(data) ? data : []);
    } catch (e) {
        if (token !== linkContactState.companySearchToken) return;
        if (container) container.innerHTML = '<div class="alert alert-danger mb-0">Fejl under søgning</div>';
    }
}

function initLinkContactModalEvents() {
    const searchInput = document.getElementById('linkContactSearch');
    const companySearchInput = document.getElementById('linkCompanySearch');
    const confirmBtn = document.getElementById('linkContactConfirm');
    const createBtn = document.getElementById('createContactConfirm');
    const createCompanyCaseBtn = document.getElementById('createCompanyCaseConfirm');
    const modalEl = document.getElementById('linkContactModal');
    if (!searchInput || !companySearchInput || !confirmBtn || !createBtn || !createCompanyCaseBtn) return;

    searchInput.addEventListener('input', () => {
        if (linkContactState.searchTimer) clearTimeout(linkContactState.searchTimer);
        const q = String(searchInput.value || '').trim();
        linkContactState.searchTimer = setTimeout(() => {
            if (!q) {
                renderLinkContactResults([]);
                return;
            }
            searchContacts(q);
        }, 250);
    });

    companySearchInput.addEventListener('input', () => {
        if (linkContactState.companySearchTimer) clearTimeout(linkContactState.companySearchTimer);
        const q = String(companySearchInput.value || '').trim();
        linkContactState.companySearchTimer = setTimeout(() => {
            if (q.length < 2) {
                renderCompanyResults([]);
                return;
            }
            searchCompanies(q);
        }, 250);
    });

    confirmBtn.addEventListener('click', async () => {
        if (!linkContactState.callId || !linkContactState.selectedContactId) return;
        confirmBtn.disabled = true;
        try {
            await patchCallContact(linkContactState.callId, linkContactState.selectedContactId);
            const modal = getLinkContactModalInstance();
            if (modal) modal.hide();
            await loadCalls();
        } catch (error) {
            alert('Kunne ikke knytte kontakt: ' + (error?.message || 'ukendt fejl'));
        } finally {
            confirmBtn.disabled = false;
        }
    });

    createBtn.addEventListener('click', async () => {
        const firstName = String(document.getElementById('newContactFirstName')?.value || '').trim();
        const lastName = String(document.getElementById('newContactLastName')?.value || '').trim();
        const email = String(document.getElementById('newContactEmail')?.value || '').trim();
        const title = String(document.getElementById('newContactTitle')?.value || '').trim();
        const phoneInput = String(document.getElementById('newContactPhone')?.value || '').trim() || linkContactState.number;

        if (!firstName) {
            alert('Fornavn er påkrævet for at oprette kontakt');
            return;
        }
        if (!linkContactState.callId) {
            alert('Opkald mangler');
            return;
        }

        createBtn.disabled = true;
        createBtn.textContent = 'Opretter...';
        try {
            const res = await fetch('/api/v1/contacts', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                credentials: 'include',
                body: JSON.stringify({
                    first_name: firstName,
                    last_name: lastName,
                    email: email || null,
                    phone: phoneInput || null,
                    title: title || null,
                })
            });

            if (!res.ok) {
                const t = await res.text();
                throw new Error(t || `HTTP ${res.status}`);
            }

            const created = await res.json();
            const contactId = Number(created?.id || 0);
            if (!Number.isInteger(contactId) || contactId <= 0) {
                throw new Error('Kontakt blev oprettet men ID mangler');
            }

            await patchCallContact(linkContactState.callId, contactId);
            const modal = getLinkContactModalInstance();
            if (modal) modal.hide();
            await loadCalls();
        } catch (error) {
            alert('Kunne ikke oprette kontakt: ' + (error?.message || 'ukendt fejl'));
        } finally {
            createBtn.disabled = false;
            createBtn.textContent = 'Opret og knyt';
        }
    });

    createCompanyCaseBtn.addEventListener('click', async () => {
        if (!linkContactState.callId) {
            alert('Opkald mangler');
            return;
        }
        if (!linkContactState.selectedCompanyId) {
            alert('Vælg et firma først');
            return;
        }

        const numberForTitle = linkContactState.number || 'ukendt nummer';
        const qs = new URLSearchParams();
        qs.set('customer_id', String(linkContactState.selectedCompanyId));
        qs.set('telefoni_opkald_id', String(linkContactState.callId));
        qs.set('title', `Telefonsamtale – ${numberForTitle}`);
        qs.set('description', `Opkald fra firmaets hovednummer: ${numberForTitle}`);
        window.location.href = `/sag/new?${qs.toString()}`;
    });

    if (modalEl) {
        modalEl.addEventListener('hidden.bs.modal', () => {
            if (linkContactState.searchTimer) clearTimeout(linkContactState.searchTimer);
            if (linkContactState.companySearchTimer) clearTimeout(linkContactState.companySearchTimer);
            linkContactState.searchTimer = null;
            linkContactState.companySearchTimer = null;
            linkContactState.searchToken++;
            linkContactState.companySearchToken++;
            linkContactState.callId = null;
            linkContactState.number = '';
            linkContactState.mode = 'contact';
            setLinkContactSelected(null, '');
            setLinkCompanySelected(null, '');
            searchInput.value = '';
            companySearchInput.value = '';
            document.getElementById('newContactFirstName').value = '';
            document.getElementById('newContactLastName').value = '';
            document.getElementById('newContactPhone').value = '';
            document.getElementById('newContactEmail').value = '';
            document.getElementById('newContactTitle').value = '';
            const results = document.getElementById('linkContactResults');
            const companyResults = document.getElementById('linkCompanyResults');
            const ctx = document.getElementById('linkContactContext');
            if (results) results.innerHTML = '';
            if (companyResults) companyResults.innerHTML = '';
            if (ctx) ctx.textContent = 'Opkald: -';
        });
    }
}

function openLinkContactModal(callId, mode = 'contact') {
    const numericCallId = Number(callId);
    const call = telefoniCallMap.get(numericCallId);
    linkContactState.callId = numericCallId;
    linkContactState.number = String(call?.display_number || call?.ekstern_nummer || '').trim();
    linkContactState.mode = mode;

    const ctx = document.getElementById('linkContactContext');
    const searchInput = document.getElementById('linkContactSearch');
    const companySearchInput = document.getElementById('linkCompanySearch');
    const phoneInput = document.getElementById('newContactPhone');
    const firstNameInput = document.getElementById('newContactFirstName');
    const label = call
        ? `${call.direction === 'outbound' ? 'Udgående' : 'Indgående'} · ${linkContactState.number || '-'} · ${call.started_at ? new Date(call.started_at).toLocaleString('da-DK') : '-'}`
        : `Opkald #${numericCallId}`;

    if (ctx) ctx.textContent = `Opkald: ${label}`;
    if (searchInput) searchInput.value = linkContactState.number;
    if (companySearchInput) companySearchInput.value = '';
    if (phoneInput) phoneInput.value = linkContactState.number;
    if (firstNameInput && !firstNameInput.value) {
        firstNameInput.value = 'Ukendt';
    }
    setLinkContactSelected(null, '');
    setLinkCompanySelected(null, '');
    renderLinkContactResults([]);
    renderCompanyResults([]);

    const modal = getLinkContactModalInstance();
    if (modal) modal.show();

    setTimeout(() => {
        if (mode === 'company') {
            companySearchInput?.focus();
        } else {
            searchInput?.focus();
        }
        if (linkContactState.number) {
            searchContacts(linkContactState.number);
        }
    }, 200);
}

async function unlinkContact(callId) {
    if (!confirm('Fjern link til kontakt for dette opkald?')) return;
    try {
        await patchCallContact(callId, null);
        await loadCalls();
    } catch (error) {
        alert('Kunne ikke fjerne kontakt-link: ' + (error?.message || 'ukendt fejl'));
    }
}

function setLinkSagSelected(sagId, label) {
    const selected = document.getElementById('linkSagSelected');
    const confirmBtn = document.getElementById('linkSagConfirm');
    const numericSagId = Number(sagId);
    if (!Number.isInteger(numericSagId) || numericSagId <= 0) {
        linkSagState.selectedSagId = null;
        linkSagState.selectedLabel = '';
        if (selected) {
            selected.className = 'alert alert-secondary py-2 mb-3';
            selected.textContent = 'Ingen sag valgt';
        }
        if (confirmBtn) confirmBtn.disabled = true;
        return;
    }

    linkSagState.selectedSagId = numericSagId;
    linkSagState.selectedLabel = String(label || `Sag #${numericSagId}`);
    if (selected) {
        selected.className = 'alert alert-success py-2 mb-3';
        selected.textContent = `Valgt: ${linkSagState.selectedLabel} (ID: ${numericSagId})`;
    }
    if (confirmBtn) confirmBtn.disabled = false;
}

function renderLinkSagResults(results) {
    const container = document.getElementById('linkSagResults');
    if (!container) return;

    if (!results || results.length === 0) {
        container.innerHTML = '<div class="alert alert-light border mb-0">Ingen sager fundet</div>';
        return;
    }

    container.innerHTML = (results || []).map(item => {
        const sid = Number(item.id);
        const title = String(item.titel || item.title || `Sag #${sid}`);
        const customer = String(item.customer_name || 'Ukendt kunde');
        const status = String(item.status || '-');
        const label = `${title} — ${customer}`;
        return `
            <div class="list-group-item d-flex justify-content-between align-items-start gap-3">
                <div>
                    <div class="fw-semibold">${escapeHtml(title)}</div>
                    <div class="small text-muted">${escapeHtml(customer)} · ${escapeHtml(status)} · ID: ${sid}</div>
                </div>
                <button type="button" class="btn btn-sm btn-outline-primary" onclick="setLinkSagSelected(${sid}, '${escapeHtml(label)}')">Vælg</button>
            </div>
        `;
    }).join('');
}

function buildInitialSagQuery(call) {
    if (!call) return '';

    const number = String(call.display_number || call.ekstern_nummer || '').trim();
    const contact = String(call.contact_name || '').trim();
    const company = String(call.contact_company || '').trim();

    if (contact && company) return `${contact} ${company}`;
    if (contact) return contact;
    if (company) return company;
    if (number) return number;
    return '';
}

async function searchSager(query) {
    const token = ++linkSagState.searchToken;
    const container = document.getElementById('linkSagResults');
    if (container) {
        container.innerHTML = '<div class="alert alert-light border mb-0"><span class="spinner-border spinner-border-sm me-2"></span>Søger...</div>';
    }

    try {
        const res = await fetch(`/api/v1/search/sag?q=${encodeURIComponent(query || '')}`, { credentials: 'include' });
        if (token !== linkSagState.searchToken) return;
        if (!res.ok) {
            if (container) container.innerHTML = '<div class="alert alert-danger mb-0">Kunne ikke søge sager</div>';
            return;
        }
        const data = await res.json();
        const results = Array.isArray(data) ? data : (data?.items || data?.results || []);
        renderLinkSagResults(results);
    } catch (e) {
        if (token !== linkSagState.searchToken) return;
        if (container) container.innerHTML = '<div class="alert alert-danger mb-0">Fejl under søgning</div>';
    }
}

function initLinkSagModalEvents() {
    const searchInput = document.getElementById('linkSagSearch');
    const manualInput = document.getElementById('linkSagIdManual');
    const confirmBtn = document.getElementById('linkSagConfirm');
    const modalEl = document.getElementById('linkSagModal');
    if (!searchInput || !manualInput || !confirmBtn) return;

    searchInput.addEventListener('input', () => {
        if (linkSagState.searchTimer) clearTimeout(linkSagState.searchTimer);
        const q = String(searchInput.value || '').trim();
        linkSagState.searchTimer = setTimeout(() => {
            if (!q) {
                renderLinkSagResults([]);
                return;
            }
            searchSager(q);
        }, 250);
    });

    searchInput.addEventListener('keydown', (event) => {
        if (event.key !== 'Enter') return;
        event.preventDefault();

        const firstSelectBtn = document.querySelector('#linkSagResults .btn-outline-primary');
        if (firstSelectBtn) {
            firstSelectBtn.click();
            return;
        }

        const manualVal = Number(manualInput.value);
        if (Number.isInteger(manualVal) && manualVal > 0) {
            setLinkSagSelected(manualVal, `Sag #${manualVal} (manuel)`);
        }
    });

    manualInput.addEventListener('input', () => {
        const val = Number(manualInput.value);
        if (Number.isInteger(val) && val > 0) {
            setLinkSagSelected(val, `Sag #${val} (manuel)`);
        } else {
            setLinkSagSelected(null, '');
        }
    });

    confirmBtn.addEventListener('click', async () => {
        if (!linkSagState.callId || !linkSagState.selectedSagId) return;
        try {
            const res = await fetch(`/api/v1/telefoni/calls/${linkSagState.callId}`, {
                method: 'PATCH',
                headers: { 'Content-Type': 'application/json' },
                credentials: 'include',
                body: JSON.stringify({ sag_id: linkSagState.selectedSagId })
            });
            if (!res.ok) {
                const t = await res.text();
                alert('Kunne ikke linke sag: ' + t);
                return;
            }
            const modal = getLinkSagModalInstance();
            if (modal) modal.hide();
            await loadCalls();
        } catch (e) {
            alert('Kunne ikke linke sag');
        }
    });

    if (modalEl) {
        modalEl.addEventListener('hidden.bs.modal', () => {
            if (linkSagState.searchTimer) clearTimeout(linkSagState.searchTimer);
            linkSagState.searchTimer = null;
            linkSagState.searchToken++;
            linkSagState.callId = null;
            setLinkSagSelected(null, '');
            searchInput.value = '';
            manualInput.value = '';
            const results = document.getElementById('linkSagResults');
            const ctx = document.getElementById('linkSagContext');
            if (results) results.innerHTML = '';
            if (ctx) ctx.textContent = 'Opkald: -';
        });
    }
}

async function callViaYealink(number) {
    const clean = String(number || '').trim();
    if (!clean || clean === '-') {
        alert('Intet gyldigt nummer at ringe til');
        return;
    }

    const userId = await ensureCurrentUserId();
    try {
        const res = await fetch('/api/v1/telefoni/click-to-call', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            credentials: 'include',
            body: JSON.stringify({ number: clean, user_id: userId })
        });

        if (!res.ok) {
            const t = await res.text();
            alert('Ring ud fejlede: ' + t);
            return;
        }

        alert('Ringer ud via Yealink...');
    } catch (e) {
        alert('Kunne ikke starte opkald');
    }
}

async function loadUsers() {
    const sel = document.getElementById('filterUser');
    try {
        const res = await fetch('/api/v1/telefoni/users', { credentials: 'include' });
        if (!res.ok) return;
        const users = await res.json();
        (users || []).forEach(u => {
            const opt = document.createElement('option');
            opt.value = u.user_id;
            opt.textContent = `${u.full_name || u.username || ('#' + u.user_id)}${u.telefoni_extension ? ' (' + u.telefoni_extension + ')' : ''}`;
            sel.appendChild(opt);
        });
        sel.value = '';
    } catch (e) {
        console.error('Failed loading telefoni users', e);
    }
}

function hasExistingCallRows(tbody) {
    return Boolean(tbody && tbody.querySelector('tr[data-call-id]'));
}

function hydrateCallMapFromSsrRows() {
    const rows = document.querySelectorAll('#telefoniRows tr[data-call-id]');
    if (!rows.length) return;

    rows.forEach((row) => {
        const callId = Number(row.dataset.callId);
        if (!Number.isInteger(callId) || callId <= 0) return;

        const toIntOrNull = (value) => {
            const n = Number(value);
            return Number.isInteger(n) && n > 0 ? n : null;
        };

        const durationRaw = String(row.dataset.durationSec || '').trim();
        const durationSec = durationRaw === '' ? null : Number(durationRaw);

        telefoniCallMap.set(callId, {
            id: callId,
            direction: String(row.dataset.direction || '').trim() || null,
            display_number: normalizeDisplayNumber(String(row.dataset.displayNumber || '').trim()) || null,
            ekstern_nummer: normalizeDisplayNumber(String(row.dataset.eksternNummer || '').trim()) || null,
            started_at: String(row.dataset.startedAt || '').trim() || null,
            ended_at: String(row.dataset.endedAt || '').trim() || null,
            duration_sec: Number.isFinite(durationSec) ? durationSec : null,
            kontakt_id: toIntOrNull(row.dataset.kontaktId),
            contact_name: String(row.dataset.contactName || '').trim() || null,
            sag_id: toIntOrNull(row.dataset.sagId),
            sag_titel: String(row.dataset.sagTitel || '').trim() || null,
            full_name: String(row.dataset.fullName || '').trim() || null,
            username: String(row.dataset.username || '').trim() || null,
        });
    });
}

function cacheInitialSsrRows(tbody) {
    if (!tbody) return;
    if (tbody.dataset.initialRowsCached === '1') return;
    tbody.dataset.initialRowsHtml = tbody.innerHTML;
    tbody.dataset.initialRowsCached = '1';
}

function restoreInitialSsrRows(tbody) {
    if (!tbody) return false;
    const initialHtml = String(tbody.dataset.initialRowsHtml || '').trim();
    if (!initialHtml) return false;
    if (!initialHtml.includes('data-call-id')) return false;

    tbody.innerHTML = initialHtml;
    tbody.classList.remove('d-none');
    tbody.style.display = '';
    tbody.style.visibility = '';
    tbody.style.opacity = '';
    return true;
}

function hasActiveCallFilters() {
    const userId = document.getElementById('filterUser')?.value;
    const from = document.getElementById('filterFrom')?.value;
    const to = document.getElementById('filterTo')?.value;
    const withoutCase = document.getElementById('filterWithoutCase')?.checked;
    return Boolean(userId || from || to || withoutCase);
}

async function loadCalls(options = {}) {
    const preserveOnEmpty = Boolean(options.preserveOnEmpty);
    const skipLoadingState = Boolean(options.skipLoadingState);
    const tbody = document.getElementById('telefoniRows');
    cacheInitialSsrRows(tbody);
    const hadRowsBeforeLoad = hasExistingCallRows(tbody);
    const noActiveFilters = !hasActiveCallFilters();

    if (!skipLoadingState) {
        tbody.innerHTML = '<tr><td colspan="7" class="text-muted small"><span class="spinner-border spinner-border-sm me-2"></span>Indlæser...</td></tr>';
    }

    const userId = document.getElementById('filterUser').value;
    const from = document.getElementById('filterFrom').value;
    const to = document.getElementById('filterTo').value;
    const withoutCase = document.getElementById('filterWithoutCase').checked;

    const qs = new URLSearchParams();
    if (userId) qs.set('user_id', userId);
    if (from) qs.set('date_from', from);
    if (to) qs.set('date_to', to);
    if (withoutCase) qs.set('without_case', '1');

    try {
        const res = await fetch('/api/v1/telefoni/calls?' + qs.toString(), { credentials: 'include' });
        if (!res.ok) {
            const t = await res.text();
            if (preserveOnEmpty && hadRowsBeforeLoad && noActiveFilters) {
                console.warn('Telefoni: bevarer SSR-rækker efter tom/fejlende auto-refresh');
                return;
            }
            if (preserveOnEmpty && noActiveFilters && restoreInitialSsrRows(tbody)) {
                console.warn('Telefoni: gendannede SSR-rækker efter API-fejl under auto-refresh');
                return;
            }
            tbody.innerHTML = `<tr><td colspan="7" class="text-danger small">Fejl: ${escapeHtml(t)}</td></tr>`;
            return;
        }
        const rows = await res.json();
        telefoniCallMap.clear();
        (rows || []).forEach(r => {
            const fixedDisplay = normalizeDisplayNumber(r.display_number || r.ekstern_nummer || '');
            const fixedExternal = normalizeDisplayNumber(r.ekstern_nummer || r.display_number || '');
            r.display_number = fixedDisplay || null;
            r.ekstern_nummer = fixedExternal || null;
            telefoniCallMap.set(Number(r.id), r);
        });
        if (!rows || rows.length === 0) {
            if (preserveOnEmpty && hadRowsBeforeLoad && noActiveFilters) {
                console.warn('Telefoni: API returnerede 0 rækker, bevarer eksisterende SSR-visning');
                return;
            }
            if (preserveOnEmpty && noActiveFilters && restoreInitialSsrRows(tbody)) {
                console.warn('Telefoni: gendannede SSR-rækker efter tom API-respons');
                return;
            }
            tbody.innerHTML = '<tr><td colspan="7" class="text-muted small">Ingen opkald fundet</td></tr>';
            return;
        }

        tbody.innerHTML = rows.map(r => {
            const callId = Number(r.id);
            const canMutateCall = Number.isInteger(callId) && callId > 0;
            const started = r.started_at ? new Date(r.started_at) : null;
            const dateTxt = started ? started.toLocaleString('da-DK') : '-';
            const userTxt = escapeHtml(r.full_name || r.username || '-');
            const dirTxt = r.direction === 'outbound' ? 'Udgående' : 'Indgående';
            const numberRaw = normalizeDisplayNumber(r.display_number || r.ekstern_nummer || '');
            const numTxt = numberRaw
                ? `<div class="d-flex gap-2 align-items-center flex-wrap">
                        <span>${escapeHtml(numberRaw)}</span>
                        <button type="button" class="btn btn-sm btn-outline-success" onclick="callViaYealink('${escapeHtml(numberRaw)}')">Ring op</button>
                   </div>`
                : '-';

            const contactHtml = r.kontakt_id
                ? `<div class="d-flex align-items-center gap-2 flex-wrap">
                        <a href="/contacts/${r.kontakt_id}">${escapeHtml(r.contact_name || ('Kontakt #' + r.kontakt_id))}</a>
                        ${canMutateCall
                            ? `<button type="button" class="btn btn-sm btn-outline-secondary" onclick="openLinkContactModal(${callId})" title="Skift kontakt / opret kontakt"><i class="bi bi-person-gear"></i></button>
                               <button type="button" class="btn btn-sm btn-outline-danger" onclick="unlinkContact(${callId})" title="Fjern kontakt-link"><i class="bi bi-x-circle"></i></button>`
                            : '<span class="badge bg-light text-muted border">Historik</span>'}
                   </div>
                   ${r.contact_company ? `<div class="text-muted small">${escapeHtml(r.contact_company)}</div>` : ''}`
                : (canMutateCall
                    ? `<button type="button" class="btn btn-sm btn-outline-secondary" onclick="openLinkContactModal(${callId})" title="Tilknyt eller opret kontakt">
                        <i class="bi bi-person-plus"></i>
                       </button>`
                    : '<span class="text-muted small">Historisk opkald</span>');

            const numberForTitle = normalizeDisplayNumber(r.display_number || r.ekstern_nummer || '');
            const createQs = new URLSearchParams();
            if (r.kontakt_id) createQs.set('contact_id', String(r.kontakt_id));
            if (canMutateCall) createQs.set('telefoni_opkald_id', String(callId));
            createQs.set('title', `Telefonsamtale – ${numberForTitle || 'ukendt nummer'}`);

                const sagHtml = r.sag_id
                ? `<div class="d-flex gap-2 align-items-center flex-wrap">
                    <a href="/sag/${r.sag_id}/v3">${escapeHtml(r.sag_titel || ('Sag #' + r.sag_id))}</a>
                    ${canMutateCall
                                ? `<button type="button" class="btn btn-sm btn-outline-secondary" onclick="linkExistingCase(${callId})" title="Skift sag-link"><i class="bi bi-link-45deg"></i></button>
                                    <button type="button" class="btn btn-sm btn-outline-danger" onclick="unlinkCase(${callId})" title="Fjern sag-link"><i class="bi bi-x-circle"></i></button>`
                        : '<span class="badge bg-light text-muted border">Historik</span>'}
                   </div>`
                : (canMutateCall
                    ? `<div class="d-flex gap-2">
                                <a class="btn btn-sm btn-outline-primary" href="/sag/new?${createQs.toString()}" title="Opret ny sag"><i class="bi bi-folder-plus"></i></a>
                                <button type="button" class="btn btn-sm btn-outline-secondary" onclick="linkExistingCase(${callId})" title="Tilknyt eksisterende sag"><i class="bi bi-link-45deg"></i></button>
                       </div>`
                    : '<span class="text-muted small">Ingen sag</span>');

            return `
                <tr data-call-id="${callId}">
                    <td>${escapeHtml(dateTxt)}</td>
                    <td>${userTxt}</td>
                    <td>${escapeHtml(dirTxt)}</td>
                    <td>${numTxt}</td>
                    <td>${contactHtml}</td>
                    <td>${sagHtml}</td>
                    <td class="text-end">${escapeHtml(fmtDuration(r.duration_sec, r.ended_at))}</td>
                </tr>
            `;
        }).join('');
    } catch (e) {
        console.error('Failed loading calls', e);
        if (preserveOnEmpty && hadRowsBeforeLoad && noActiveFilters) {
            console.warn('Telefoni: bevarer SSR-rækker efter exception i auto-refresh');
            return;
        }
        if (preserveOnEmpty && noActiveFilters && restoreInitialSsrRows(tbody)) {
            console.warn('Telefoni: gendannede SSR-rækker efter exception i auto-refresh');
            return;
        }
        tbody.innerHTML = '<tr><td colspan="7" class="text-danger small">Kunne ikke hente opkald</td></tr>';
    }
}

async function linkExistingCase(callId) {
    linkSagState.callId = Number(callId);
    const call = telefoniCallMap.get(Number(callId));

    const ctx = document.getElementById('linkSagContext');
    const searchInput = document.getElementById('linkSagSearch');
    const manualInput = document.getElementById('linkSagIdManual');
    const results = document.getElementById('linkSagResults');
    const label = call
        ? `${call.direction === 'outbound' ? 'Udgående' : 'Indgående'} · ${call.display_number || call.ekstern_nummer || '-'} · ${call.started_at ? new Date(call.started_at).toLocaleString('da-DK') : '-'}`
        : `Opkald #${callId}`;

    if (ctx) ctx.textContent = `Opkald: ${label}`;
    const initialQuery = buildInitialSagQuery(call);
    if (searchInput) searchInput.value = initialQuery;
    if (manualInput) manualInput.value = '';
    if (results) {
        results.innerHTML = initialQuery
            ? '<div class="alert alert-light border mb-0"><span class="spinner-border spinner-border-sm me-2"></span>Søger relevante sager...</div>'
            : '<div class="alert alert-light border mb-0">Søg efter en sag eller indtast ID manuelt</div>';
    }
    setLinkSagSelected(null, '');

    const modal = getLinkSagModalInstance();
    if (modal) modal.show();
    setTimeout(() => {
        searchInput?.focus();
        if (initialQuery) {
            searchSager(initialQuery);
        }
    }, 200);
}

async function unlinkCase(callId) {
    if (!confirm('Fjern link til sag for dette opkald?')) return;
    try {
        const res = await fetch(`/api/v1/telefoni/calls/${callId}`, {
            method: 'PATCH',
            headers: { 'Content-Type': 'application/json' },
            credentials: 'include',
            body: JSON.stringify({ sag_id: null })
        });
        if (!res.ok) {
            const t = await res.text();
            alert('Kunne ikke fjerne link: ' + t);
            return;
        }
        await loadCalls();
    } catch (e) {
        alert('Kunne ikke fjerne link');
    }
}

document.addEventListener('DOMContentLoaded', async () => {
    const telefoniRows = document.getElementById('telefoniRows');
    cacheInitialSsrRows(telefoniRows);
    hydrateCallMapFromSsrRows();
    initLinkContactModalEvents();
    initLinkSagModalEvents();
    const userFilter = document.getElementById('filterUser');
    const fromFilter = document.getElementById('filterFrom');
    const toFilter = document.getElementById('filterTo');
    const withoutCaseFilter = document.getElementById('filterWithoutCase');

    if (userFilter) userFilter.value = '';
    if (fromFilter) fromFilter.value = '';
    if (toFilter) toFilter.value = '';
    if (withoutCaseFilter) withoutCaseFilter.checked = false;

    await loadUsers();
    document.getElementById('btnRefresh').addEventListener('click', loadCalls);
    document.getElementById('filterUser').addEventListener('change', loadCalls);
    document.getElementById('filterFrom').addEventListener('change', loadCalls);
    document.getElementById('filterTo').addEventListener('change', loadCalls);
    document.getElementById('filterWithoutCase').addEventListener('change', loadCalls);

    // Keep SSR rows on first paint when they exist; avoid replacing visible data
    // with an empty state due to transient API/auth/cache issues in production.
    if (hasExistingCallRows(telefoniRows)) {
        console.warn('Telefoni: springer initial auto-refresh over, SSR-rækker vises');
        return;
    }

    await loadCalls({ preserveOnEmpty: true, skipLoadingState: true });
});
</script>
{% endblock %}
