<?php
declare(strict_types=1);
require __DIR__ . '/lib/Auth.php';
require __DIR__ . '/lib/Layout.php';
require __DIR__ . '/lib/Channels.php';

use PSLauncher\Admin\Auth;
use PSLauncher\Admin\Layout;
use PSLauncher\Admin\Channels;

Auth::requireLogin();
$config = require __DIR__ . '/../api/config.php';

$manifestDir = dirname(__DIR__) . '/manifest';
$message = null; $messageType = 'success';

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    Auth::checkCsrf();
    $action = $_POST['action'] ?? '';
    try {
        $registry = Channels::load($manifestDir);

        if ($action === 'create') {
            $rawName = (string)($_POST['name'] ?? '');
            $name    = Channels::normalizeName($rawName);
            $label   = trim((string)($_POST['label'] ?? '')) ?: $name;
            $desc    = trim((string)($_POST['description'] ?? '')) ?: null;

            if (!Channels::isValidName($name)) {
                throw new \RuntimeException("Nom invalide après normalisation : « {$rawName} » → « {$name} ». Saisis quelque chose comme « asterion-vr » ou « police ».");
            }
            if ($name === 'default') {
                throw new \RuntimeException("Le channel « default » est implicite, on ne peut pas en créer un autre.");
            }
            foreach ($registry['channels'] as $c) {
                if (($c['name'] ?? '') === $name) {
                    throw new \RuntimeException("Channel « {$name} » existe déjà.");
                }
            }

            $entry = ['name' => $name, 'label' => $label];
            if ($desc !== null) $entry['description'] = $desc;
            $registry['channels'][] = $entry;
            Channels::save($manifestDir, $registry);
            $message = "Channel « {$name} » créé.";
            if ($name !== $rawName) {
                $message .= " (Nom normalisé depuis « {$rawName} ».)";
            }
        }

        elseif ($action === 'edit') {
            $name  = trim((string)($_POST['name'] ?? ''));
            $label = trim((string)($_POST['label'] ?? '')) ?: $name;
            $desc  = trim((string)($_POST['description'] ?? '')) ?: null;
            $found = false;
            foreach ($registry['channels'] as &$c) {
                if (($c['name'] ?? '') === $name) {
                    $c['label'] = $label;
                    if ($desc === null) unset($c['description']);
                    else $c['description'] = $desc;
                    $found = true;
                    break;
                }
            }
            unset($c);
            if (!$found) throw new \RuntimeException("Channel « {$name} » introuvable.");
            Channels::save($manifestDir, $registry);
            $message = "Channel « {$name} » mis à jour.";
        }

        elseif ($action === 'delete') {
            $name = trim((string)($_POST['name'] ?? ''));
            if ($name === 'default') throw new \RuntimeException("Le channel « default » ne peut pas être supprimé.");

            // Sécurité : empêche la suppression si des versions ou licenses
            // référencent encore ce channel — sinon ces refs deviennent silencieusement
            // pendantes et l'admin oublie pourquoi tel client ne voit rien.
            $usage = checkChannelUsage($manifestDir, $name);
            if ($usage['versions'] > 0 || $usage['licenses'] > 0) {
                throw new \RuntimeException(
                    "Impossible de supprimer « {$name} » : "
                    . "{$usage['versions']} version(s) taggée(s) et {$usage['licenses']} license(s) attribuée(s) à ce channel. "
                    . "Détague d'abord les versions (page Versions) et change les licenses concernées (page Licenses)."
                );
            }

            $registry['channels'] = array_values(array_filter(
                $registry['channels'],
                fn($c) => ($c['name'] ?? '') !== $name
            ));
            Channels::save($manifestDir, $registry);
            $message = "Channel « {$name} » supprimé.";
        }
    } catch (\Throwable $e) {
        $message = $e->getMessage();
        $messageType = 'error';
    }
}

/**
 * Compte les versions et licenses qui pointent encore sur un channel.
 * Sert de garde-fou avant suppression.
 */
function checkChannelUsage(string $manifestDir, string $channelName): array
{
    $usage = ['versions' => 0, 'licenses' => 0];

    $manifestPath = $manifestDir . '/versions.json';
    if (is_file($manifestPath)) {
        $m = json_decode(file_get_contents($manifestPath), true);
        if (is_array($m) && isset($m['versions'])) {
            foreach ($m['versions'] as $v) {
                $channels = $v['channels'] ?? [];
                if (in_array($channelName, $channels, true)) $usage['versions']++;
            }
        }
    }

    try {
        $config = require __DIR__ . '/../api/config.php';
        $db     = \PSLauncher\Db::get($config);
        $stmt   = $db->prepare('SELECT COUNT(*) FROM licenses WHERE channel = ?');
        $stmt->execute([$channelName]);
        $usage['licenses'] = (int)$stmt->fetchColumn();
    } catch (\Throwable) { /* DB not reachable from this context, best effort */ }

    return $usage;
}

require_once __DIR__ . '/../api/lib/Db.php';

$registry = Channels::load($manifestDir);

Layout::header('Channels', 'channels');
?>
<h1>Channels de distribution</h1>

<?php Layout::flash($message, $messageType); ?>

<div class="card">
    <h2>Comment ça marche</h2>
    <ul class="muted">
        <li><strong>default</strong> = channel public implicite. Toutes les versions taggées « default » (ou sans tag) sont visibles par tous les clients, peu importe leur license.</li>
        <li>Les autres channels (<strong>asterion-vr</strong>, <strong>police</strong>, …) sont des canaux privés. Une version taggée uniquement sur un channel privé n'est vue QUE par les licenses attribuées à ce channel.</li>
        <li>Une version peut être taggée sur plusieurs channels en même temps (multi-channel). Une license n'est attribuée qu'à un seul channel à la fois.</li>
        <li>Sémantique additive : un client sur le channel « police » voit les versions « default » + les versions « police ». Pour rendre une version invisible au public, ne la tague PAS « default ».</li>
    </ul>
</div>

<div class="card">
    <h2>Créer un channel</h2>
    <form method="post">
        <?= Layout::csrfField() ?>
        <input type="hidden" name="action" value="create">
        <div class="row">
            <div class="col field">
                <label>Nom (identifiant ASCII)</label>
                <input type="text" name="name" required maxlength="80" placeholder="asterion-vr"
                       title="Sera normalisé en lowercase + tirets côté serveur (« ASTERION VR » → « asterion-vr »).">
            </div>
            <div class="col field">
                <label>Label (affiché dans les UI)</label>
                <input type="text" name="label" maxlength="120" placeholder="ASTERION VR (interne)">
            </div>
        </div>
        <div class="field">
            <label>Description (optionnel)</label>
            <input type="text" name="description" maxlength="255" placeholder="Builds internes pour l'équipe ASTERION">
        </div>
        <button class="btn btn-success" type="submit">Créer</button>
    </form>
</div>

<div class="card">
    <h2>Channels existants</h2>
    <table>
        <thead>
            <tr>
                <th>Nom</th>
                <th>Label</th>
                <th>Description</th>
                <th style="text-align:right">Actions</th>
            </tr>
        </thead>
        <tbody>
        <?php foreach ($registry['channels'] as $c):
            $isDefault = ($c['name'] ?? '') === 'default';
        ?>
            <tr>
                <td>
                    <code><?= htmlspecialchars($c['name'] ?? '') ?></code>
                    <?php if ($isDefault): ?>
                        <span class="badge badge-success" style="margin-left: 6px;" title="Channel implicite, immutable">implicite</span>
                    <?php endif; ?>
                </td>
                <td><?= htmlspecialchars($c['label'] ?? $c['name'] ?? '') ?></td>
                <td class="muted"><?= htmlspecialchars($c['description'] ?? '') ?></td>
                <td style="text-align:right; white-space: nowrap;">
                    <details style="display: inline-block; margin: 0 4px;">
                        <summary class="btn btn-secondary">Éditer</summary>
                        <form method="post" style="margin-top: 8px; min-width: 320px;">
                            <?= Layout::csrfField() ?>
                            <input type="hidden" name="action" value="edit">
                            <input type="hidden" name="name" value="<?= htmlspecialchars($c['name'] ?? '') ?>">
                            <div class="field">
                                <label>Label</label>
                                <input type="text" name="label" value="<?= htmlspecialchars($c['label'] ?? '') ?>" required>
                            </div>
                            <div class="field">
                                <label>Description</label>
                                <input type="text" name="description" value="<?= htmlspecialchars($c['description'] ?? '') ?>">
                            </div>
                            <button class="btn btn-primary" type="submit">Enregistrer</button>
                        </form>
                    </details>
                    <?php if (!$isDefault): ?>
                        <form method="post" style="display:inline" onsubmit="return confirm('Supprimer le channel <?= htmlspecialchars($c['name']) ?> ?\nLes versions et licenses qui le référencent doivent être détaguées d\'abord.')">
                            <?= Layout::csrfField() ?>
                            <input type="hidden" name="action" value="delete">
                            <input type="hidden" name="name" value="<?= htmlspecialchars($c['name'] ?? '') ?>">
                            <button class="btn btn-danger" type="submit">Supprimer</button>
                        </form>
                    <?php endif; ?>
                </td>
            </tr>
        <?php endforeach; ?>
        </tbody>
    </table>
</div>

<?php Layout::footer();
