<?php

require_once __DIR__ . '/../lib/init.php';
Auth::requireLogin();

// ── Données PHP ────────────────────────────────────────────────────────────────

$apiResult = LeaseService::getLeases();

// Map subnets par kea_subnet_id
$subnets   = Subnet::getAll();
$subnetMap = [];
foreach ($subnets as $s) {
    $subnetMap[(int)$s['kea_subnet_id']] = $s;
}

// Map réservations : "machex:subnet_id" → [host_id, group_name]
$resRows = Database::get()->query(
    'SELECT h.host_id, HEX(h.dhcp_identifier) AS mac_hex, h.dhcp4_subnet_id,
            m.group_name
     FROM hosts h
     LEFT JOIN app_reservation_meta m ON m.host_id = h.host_id
     WHERE h.dhcp_identifier_type = ' . Reservation::HW_ADDR_TYPE
)->fetchAll();
$resMap = [];
foreach ($resRows as $r) {
    $key = strtolower($r['mac_hex']) . ':' . $r['dhcp4_subnet_id'];
    $resMap[$key] = ['host_id' => (int)$r['host_id'], 'group_name' => $r['group_name'] ?? ''];
}

// Construction du tableau enrichi pour le JS
$leasesData = [];
if ($apiResult['success']) {
    foreach ($apiResult['leases'] as $lease) {
        $mac      = $lease['hw-address'] ?? '';
        $ip       = $lease['ip-address'] ?? '';
        $subnetId = (int)($lease['subnet-id'] ?? 0);
        $cltt     = (int)($lease['cltt']      ?? 0);
        $validLft = (int)($lease['valid-lft'] ?? 0);
        $macHex   = strtolower(str_replace(':', '', $mac));
        $resKey   = $macHex . ':' . $subnetId;
        $sub      = $subnetMap[$subnetId] ?? null;
        $res      = $resMap[$resKey] ?? null;

        $leasesData[] = [
            'ip'           => $ip,
            'ip_int'       => sprintf('%u', ip2long($ip) ?: 0),
            'mac'          => $mac,
            'hostname'     => $lease['hostname'] ?? '',
            'subnet_id'    => $subnetId,
            'subnet_name'  => $sub ? $sub['name'] : ('Subnet #' . $subnetId),
            'subnet_app_id'=> $sub ? (int)$sub['id'] : null,
            'state'        => (int)($lease['state'] ?? 0),
            'expiry'       => $cltt + $validLft,
            'host_id'      => $res ? $res['host_id'] : null,
            'group_name'   => $res ? $res['group_name'] : '',
        ];
    }
}

// Options subnets pour le filtre (uniquement ceux présents dans les leases)
$subnetOptions = [];
foreach ($leasesData as $l) {
    $sid = $l['subnet_id'];
    if (!isset($subnetOptions[$sid])) {
        $subnetOptions[$sid] = $l['subnet_name'];
    }
}
asort($subnetOptions);

$page_title = 'Leases DHCP';
require_once APP_ROOT . '/lib/layout_header.php';
?>

<?php if (!$apiResult['success']): ?>
<div class="alert alert-warning d-flex align-items-start gap-2">
    <i class="bi bi-exclamation-triangle-fill fs-5 mt-1"></i>
    <div>
        <strong>Impossible de récupérer les leases.</strong><br>
        <?= h($apiResult['message']) ?><br>
        <small class="text-muted">
            Vérifiez l'URL et les credentials du Kea Control Agent dans
            <a href="settings.php">Paramètres</a>.
        </small>
    </div>
</div>
<?php else: ?>

<!-- ── Stats ─────────────────────────────────────────────────────────────── -->
<div class="row g-3 mb-4">
    <div class="col-6 col-md-3">
        <div class="card text-center py-3">
            <div class="display-6 fw-bold text-primary" id="stat-total">0</div>
            <div class="text-muted small">Total affiché</div>
        </div>
    </div>
    <div class="col-6 col-md-3">
        <div class="card text-center py-3">
            <div class="display-6 fw-bold text-success" id="stat-active">0</div>
            <div class="text-muted small">Actifs</div>
        </div>
    </div>
    <div class="col-6 col-md-3">
        <div class="card text-center py-3">
            <div class="display-6 fw-bold text-warning" id="stat-declined">0</div>
            <div class="text-muted small">Refusés</div>
        </div>
    </div>
    <div class="col-6 col-md-3">
        <div class="card text-center py-3">
            <div class="display-6 fw-bold text-secondary" id="stat-expired">0</div>
            <div class="text-muted small">Expirés</div>
        </div>
    </div>
</div>

<!-- ── Filtres ────────────────────────────────────────────────────────────── -->
<div class="card mb-3">
    <div class="card-body py-2">
        <div class="row g-2 align-items-center">
            <div class="col-md-auto">
                <div class="btn-group btn-group-sm" role="group" aria-label="Affichage interne d'un subnet">
                    <button type="button" class="btn btn-outline-secondary" id="mode-grouped"
                            title="Sous-grouper les leases par groupe de réservation dans chaque subnet">
                        <i class="bi bi-collection me-1"></i>Groupés
                    </button>
                    <button type="button" class="btn btn-outline-secondary" id="mode-flat"
                            title="Lister les leases à plat dans chaque subnet">
                        <i class="bi bi-list-ul me-1"></i>Plat
                    </button>
                </div>
            </div>
            <div class="col-md-3">
                <div class="input-group input-group-sm">
                    <span class="input-group-text"><i class="bi bi-search"></i></span>
                    <input type="text" id="f-search" class="form-control"
                           placeholder="Rechercher IP, MAC, hostname…">
                    <button class="btn btn-outline-secondary" id="f-clear" type="button" title="Effacer">
                        <i class="bi bi-x"></i>
                    </button>
                </div>
            </div>
            <div class="col-md-2">
                <select id="f-subnet" class="form-select form-select-sm">
                    <option value="">Tous les subnets</option>
                    <?php foreach ($subnetOptions as $sid => $sname): ?>
                        <option value="<?= (int)$sid ?>"><?= h($sname) ?></option>
                    <?php endforeach; ?>
                </select>
            </div>
            <div class="col-md-2">
                <select id="f-state" class="form-select form-select-sm">
                    <option value="">Tous les états</option>
                    <option value="0">Actif</option>
                    <option value="1">Refusé</option>
                    <option value="2">Expiré</option>
                </select>
            </div>
            <div class="col-md-auto ms-md-auto d-flex gap-2">
                <button class="btn btn-sm btn-outline-secondary" id="btn-reset" type="button">
                    <i class="bi bi-funnel"></i> Réinitialiser
                </button>
                <a href="leases.php" class="btn btn-sm btn-outline-primary">
                    <i class="bi bi-arrow-clockwise"></i> Actualiser
                </a>
            </div>
        </div>
    </div>
</div>

<!-- ── Tableau ────────────────────────────────────────────────────────────── -->
<div class="card">
    <div class="card-body p-0">
        <div class="table-responsive">
            <table class="table table-hover table-sm mb-0" id="lease-table">
                <thead class="table-light">
                    <tr>
                        <th class="ps-3" data-col="ip_int"     style="cursor:pointer;white-space:nowrap">
                            IP <span class="sort-icon text-muted"></span>
                        </th>
                        <th data-col="mac"         style="cursor:pointer;white-space:nowrap">
                            MAC <span class="sort-icon text-muted"></span>
                        </th>
                        <th data-col="hostname"    style="cursor:pointer;white-space:nowrap">
                            Hostname <span class="sort-icon text-muted"></span>
                        </th>
                        <th data-col="subnet_name" style="cursor:pointer;white-space:nowrap">
                            Subnet <span class="sort-icon text-muted"></span>
                        </th>
                        <th data-col="state"       style="cursor:pointer;white-space:nowrap">
                            État <span class="sort-icon text-muted"></span>
                        </th>
                        <th data-col="expiry"      style="cursor:pointer;white-space:nowrap">
                            Expiration <span class="sort-icon text-muted"></span>
                        </th>
                        <th style="width:46px"></th>
                    </tr>
                </thead>
                <tbody id="lease-tbody">
                    <tr><td colspan="7" class="text-center text-muted py-5">
                        <div class="spinner-border spinner-border-sm me-2"></div>Chargement…
                    </td></tr>
                </tbody>
            </table>
        </div>
    </div>
    <div class="card-footer text-muted small py-2 px-3" id="lease-footer"></div>
</div>

<?php endif; ?>

<script>
(function () {
'use strict';

const ALL_LEASES = <?= json_encode($leasesData, JSON_HEX_TAG | JSON_HEX_AMP) ?>;

const MODE_KEY = 'leases_view_mode';
let mode    = localStorage.getItem(MODE_KEY) === 'flat' ? 'flat' : 'grouped';
let sortCol = 'ip_int';
let sortDir = 'asc';

// ── Formatage ────────────────────────────────────────────────────────────────

function formatRemaining(expiry) {
    const now = Math.floor(Date.now() / 1000);
    const rem = expiry - now;
    if (rem <= 0) return '<span class="text-muted fst-italic small">expiré</span>';
    if (rem < 3600) {
        const m = Math.floor(rem / 60);
        return '<span class="text-danger fw-semibold">' + m + 'min</span>';
    }
    if (rem < 86400) {
        const h = Math.floor(rem / 3600);
        const m = Math.floor((rem % 3600) / 60);
        return '<span class="text-warning fw-semibold">' + h + 'h' + (m > 0 ? ' ' + m + 'm' : '') + '</span>';
    }
    const d = Math.floor(rem / 86400);
    const h = Math.floor((rem % 86400) / 3600);
    return d + 'j' + (h > 0 ? ' ' + h + 'h' : '');
}

function formatDate(ts) {
    if (!ts) return '—';
    return new Date(ts * 1000).toLocaleString('fr-FR', {dateStyle: 'short', timeStyle: 'short'});
}

function stateLabel(state) {
    const map = {0: ['Actif','success'], 1: ['Refusé','warning'], 2: ['Expiré','secondary']};
    const p   = map[state] || ['Inconnu','dark'];
    return '<span class="badge bg-' + p[1] + '">' + p[0] + '</span>';
}

function rowClass(lease) {
    if (lease.state === 1) return ' class="table-warning"';
    if (lease.state === 2) return ' class="table-secondary"';
    const now = Math.floor(Date.now() / 1000);
    if (lease.expiry - now < 3600) return ' class="table-danger"';
    return '';
}

// ── Filtrage / tri ───────────────────────────────────────────────────────────

function applyFilters() {
    const search = document.getElementById('f-search').value.toLowerCase().trim();
    const subnet = document.getElementById('f-subnet').value;
    const state  = document.getElementById('f-state').value;

    return ALL_LEASES.filter(function (l) {
        if (search) {
            const hay = l.ip + ' ' + l.mac + ' ' + l.hostname.toLowerCase();
            if (hay.indexOf(search) === -1) return false;
        }
        if (subnet !== '' && String(l.subnet_id) !== subnet) return false;
        if (state  !== '' && String(l.state)     !== state)  return false;
        return true;
    });
}

function sortLeases(leases) {
    return leases.slice().sort(function (a, b) {
        var va = a[sortCol], vb = b[sortCol];
        if (va === null) va = -1;
        if (vb === null) vb = -1;
        if (typeof va === 'string') { va = va.toLowerCase(); vb = vb.toLowerCase(); }
        var cmp = va < vb ? -1 : va > vb ? 1 : 0;
        return sortDir === 'asc' ? cmp : -cmp;
    });
}

// ── Rendu ────────────────────────────────────────────────────────────────────

function render() {
    var filtered = applyFilters();
    var sorted   = sortLeases(filtered);

    // Stats
    document.getElementById('stat-total').textContent    = filtered.length;
    document.getElementById('stat-active').textContent   = filtered.filter(function(l){ return l.state === 0; }).length;
    document.getElementById('stat-declined').textContent = filtered.filter(function(l){ return l.state === 1; }).length;
    document.getElementById('stat-expired').textContent  = filtered.filter(function(l){ return l.state === 2; }).length;

    // État des boutons de mode
    document.getElementById('mode-grouped').classList.toggle('active', mode === 'grouped');
    document.getElementById('mode-flat').classList.toggle('active', mode === 'flat');

    // Indicateurs de tri
    document.querySelectorAll('th[data-col]').forEach(function (th) {
        var icon = th.dataset.col === sortCol
            ? (sortDir === 'asc' ? '↑' : '↓')
            : '⇅';
        th.querySelector('.sort-icon').textContent = icon;
        th.querySelector('.sort-icon').className   =
            'sort-icon ' + (th.dataset.col === sortCol ? 'text-primary' : 'text-muted');
    });

    // Corps du tableau
    var tbody = document.getElementById('lease-tbody');
    if (sorted.length === 0) {
        tbody.innerHTML = '<tr><td colspan="7" class="text-center text-muted py-5">Aucun lease correspondant</td></tr>';
        document.getElementById('lease-footer').textContent = '';
        return;
    }

    // Toujours groupé par subnet ; le mode ne change QUE l'intérieur d'un subnet
    // (grouped = sous-groupes par group_name ; flat = liste simple).
    tbody.innerHTML = renderBySubnet(sorted);

    document.getElementById('lease-footer').textContent =
        sorted.length + ' lease(s) affiché(s) sur ' + ALL_LEASES.length + ' total';
}

// HTML d'une ligne de lease
function rowHtml(l) {
    var resBtn = '';
    if (l.host_id !== null) {
        resBtn = '<a href="reservation_edit.php?id=' + l.host_id + '" '
               + 'class="btn btn-sm btn-outline-primary py-0 px-1" '
               + 'title="Voir la réservation"><i class="bi bi-bookmark-check"></i></a>';
    } else if (l.subnet_app_id !== null) {
        resBtn = '<a href="reservation_add.php?subnet_id=' + l.subnet_app_id
               + '&mac='      + encodeURIComponent(l.mac)
               + '&ip='       + encodeURIComponent(l.ip)
               + '&hostname=' + encodeURIComponent(l.hostname) + '" '
               + 'class="btn btn-sm btn-outline-secondary py-0 px-1" '
               + 'title="Créer une réservation"><i class="bi bi-bookmark-plus"></i></a>';
    }

    return '<tr' + rowClass(l) + '>'
        + '<td class="ps-3 font-monospace small">' + l.ip + '</td>'
        + '<td class="font-monospace small">' + l.mac + '</td>'
        + '<td>' + (l.hostname || '<span class="text-muted">—</span>') + '</td>'
        + '<td><small>' + l.subnet_name + '</small></td>'
        + '<td>' + stateLabel(l.state) + '</td>'
        + '<td class="small">'
        +     formatRemaining(l.expiry)
        +     '<br><span class="text-muted" style="font-size:.75em">'
        +     formatDate(l.expiry) + '</span>'
        + '</td>'
        + '<td class="pe-2">' + resBtn + '</td>'
        + '</tr>';
}

// Rendu TOUJOURS groupé par subnet. À l'intérieur d'un subnet :
//   mode 'grouped' → sous-groupes par group_name ; mode 'flat' → liste simple.
// Le tri courant (sortLeases) est déjà appliqué en amont → conservé au niveau le plus fin.
function renderBySubnet(sorted) {
    var subnets = {};  // subnet_id → { name, list }
    var order   = [];
    sorted.forEach(function (l) {
        if (!subnets[l.subnet_id]) {
            subnets[l.subnet_id] = { name: l.subnet_name, list: [] };
            order.push(l.subnet_id);
        }
        subnets[l.subnet_id].list.push(l);
    });
    order.sort(function (a, b) {
        return subnets[a].name.toLowerCase().localeCompare(subnets[b].name.toLowerCase());
    });

    return order.map(function (sid) {
        var s = subnets[sid];
        return subnetHeaderRow(s.name, s.list.length) + innerRows(s.list);
    }).join('');
}

// Contenu interne d'un subnet selon le mode.
function innerRows(list) {
    if (mode !== 'grouped') {
        return list.map(rowHtml).join('');
    }
    // Sous-groupes par group_name ; '(sans groupe)' en dernier.
    var groups = {};
    var order  = [];
    list.forEach(function (l) {
        var key = (l.group_name && l.group_name.trim() !== '') ? l.group_name : ' ';
        if (!groups[key]) { groups[key] = []; order.push(key); }
        groups[key].push(l);
    });
    order.sort(function (a, b) {
        if (a === ' ') return 1;
        if (b === ' ') return -1;
        return a.toLowerCase().localeCompare(b.toLowerCase());
    });
    return order.map(function (key) {
        return groupHeaderRow(key, groups[key].length) + groups[key].map(rowHtml).join('');
    }).join('');
}

// Ligne d'en-tête de subnet (niveau 1)
function subnetHeaderRow(name, count) {
    return '<tr class="lease-group-row"><td colspan="7">'
        + '<div class="group-header">'
        +     '<span class="group-name">' + escapeHtml(name) + '</span>'
        +     '<span class="group-count">' + count + '</span>'
        + '</div></td></tr>';
}

// Ligne de sous-en-tête de groupe de réservation (niveau 2, indenté)
function groupHeaderRow(key, count) {
    var none = key === ' ';
    return '<tr class="lease-group-row lease-subgroup-row"><td colspan="7">'
        + '<div class="group-header group-subheader' + (none ? ' group-header-none' : '') + '">'
        +     '<span class="group-name">' + (none ? '(sans groupe)' : escapeHtml(key)) + '</span>'
        +     '<span class="group-count">' + count + '</span>'
        + '</div></td></tr>';
}

function escapeHtml(s) {
    return String(s).replace(/[&<>"]/g, function (c) {
        return {'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;'}[c];
    });
}

// ── Événements ───────────────────────────────────────────────────────────────

document.querySelectorAll('th[data-col]').forEach(function (th) {
    th.addEventListener('click', function () {
        var col = this.dataset.col;
        if (sortCol === col) {
            sortDir = sortDir === 'asc' ? 'desc' : 'asc';
        } else {
            sortCol = col;
            sortDir = 'asc';
        }
        render();
    });
});

document.getElementById('mode-grouped').addEventListener('click', function () {
    mode = 'grouped'; localStorage.setItem(MODE_KEY, mode); render();
});
document.getElementById('mode-flat').addEventListener('click', function () {
    mode = 'flat'; localStorage.setItem(MODE_KEY, mode); render();
});

document.getElementById('f-search').addEventListener('input', render);
document.getElementById('f-subnet').addEventListener('change', render);
document.getElementById('f-state').addEventListener('change', render);

document.getElementById('f-clear').addEventListener('click', function () {
    document.getElementById('f-search').value = '';
    render();
});

document.getElementById('btn-reset').addEventListener('click', function () {
    document.getElementById('f-search').value = '';
    document.getElementById('f-subnet').value = '';
    document.getElementById('f-state').value  = '';
    render();
});

// Actualisation automatique du temps restant toutes les 30s
setInterval(render, 30000);

// Rendu initial
render();

}());
</script>

<?php require_once APP_ROOT . '/lib/layout_footer.php'; ?>
