<?php
declare(strict_types=1);

session_start();
require_once __DIR__ . '/session-guard.php';
header('Content-Type: application/json; charset=utf-8');
date_default_timezone_set('Europe/Paris');

require_active_client_session(false);

function respond_json(int $statusCode, array $payload): void
{
    http_response_code($statusCode);
    echo json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
    exit;
}

function load_private_config(): array
{
    $configFile = dirname(__DIR__) . '/privatedata/client-config.php';

    if (!is_file($configFile)) {
        respond_json(500, [
            'ok' => false,
            'message' => 'Configuration privÃ©e introuvable'
        ]);
    }

    $config = require $configFile;

    if (!is_array($config) || empty($config['access_end'])) {
        respond_json(500, [
            'ok' => false,
            'message' => 'Configuration privÃ©e invalide'
        ]);
    }

    return $config;
}

function normalize_list($value): array
{
    if (!is_array($value)) {
        return [];
    }

    $seen = [];
    $out = [];

    foreach ($value as $item) {
        $item = trim((string) $item);
        if ($item === '') {
            continue;
        }

        if (!isset($seen[$item])) {
            $seen[$item] = true;
            $out[] = $item;
        }
    }

    return $out;
}

function normalize_word_key(string $word): string
{
    $word = trim(preg_replace('/\s+/u', ' ', $word) ?? $word);

    if (function_exists('mb_strtolower')) {
        return mb_strtolower($word, 'UTF-8');
    }

    return strtolower($word);
}

function take_words_from_theme(array &$diffPools, int $target, array &$usedKeys): array
{
    $picked = [];

    if ($target <= 0 || empty($diffPools)) {
        return $picked;
    }

    $diffKeys = array_keys($diffPools);

    while (count($picked) < $target) {
        $addedThisRound = false;

        foreach ($diffKeys as $diff) {
            if (count($picked) >= $target) {
                break;
            }

            while (!empty($diffPools[$diff])) {
                $item = array_shift($diffPools[$diff]);
                $globalKey = normalize_word_key((string) ($item['w'] ?? ''));

                if ($globalKey === '' || isset($usedKeys[$globalKey])) {
                    continue;
                }

                $picked[] = $item;
                $usedKeys[$globalKey] = true;
                $addedThisRound = true;
                break;
            }
        }

        if (!$addedThisRound) {
            break;
        }
    }

    return $picked;
}

$raw = file_get_contents('php://input');
$data = json_decode($raw ?: '', true);

if (!is_array($data)) {
    respond_json(400, [
        'ok' => false,
        'message' => 'RequÃªte invalide'
    ]);
}

$config = load_private_config();

if (date('Y-m-d') > (string) $config['access_end']) {
    respond_json(403, [
        'ok' => false,
        'message' => 'AccÃ¨s premium expirÃ©'
    ]);
}

$requested = (int) ($data['wordCount'] ?? 40);
$maxWords = max(10, (int) ($config['max_words'] ?? 80));
$requested = max(10, min($requested, $maxWords));

$themes = normalize_list($data['themes'] ?? []);
$diffs = array_values(array_intersect(
    ['facile', 'moyen', 'difficile'],
    normalize_list($data['difficulties'] ?? [])
));

if (!$themes || !$diffs) {
    respond_json(400, [
        'ok' => false,
        'message' => 'SÃ©lection incomplÃ¨te'
    ]);
}

$mode = (string) ($data['mode'] ?? 'premium');

if ($mode === 'kids') {
    $themesFile = dirname(__DIR__) . '/privatedata/themes-kids.json';
} elseif ($mode === 'family') {
    $themesFile = dirname(__DIR__) . '/privatedata/themes-family.json';
} else {
    $themesFile = dirname(__DIR__) . '/privatedata/themes-premium.json';
}

if (!is_file($themesFile)) {
    respond_json(500, [
        'ok' => false,
        'message' => $mode === 'kids'
            ? 'Base de mots enfants introuvable'
            : 'Base de mots introuvable'
    ]);
}

$allData = json_decode((string) file_get_contents($themesFile), true);

if (!is_array($allData)) {
    respond_json(500, [
        'ok' => false,
        'message' => $mode === 'kids'
            ? 'Base de mots enfants invalide'
            : 'Base de mots invalide'
    ]);
}

$themePools = [];

foreach ($themes as $theme) {
    if (!isset($allData[$theme]) || !is_array($allData[$theme])) {
        continue;
    }

    $themePools[$theme] = [];

    foreach ($diffs as $diff) {
        if (!isset($allData[$theme][$diff]) || !is_array($allData[$theme][$diff])) {
            continue;
        }

        $unique = [];
        $seen = [];

        foreach ($allData[$theme][$diff] as $word) {
            $word = trim((string) $word);
            if ($word === '') {
                continue;
            }

            $wordKey = normalize_word_key($word);
            if (isset($seen[$wordKey])) {
                continue;
            }

            $seen[$wordKey] = true;
            $unique[] = [
                'w' => $word,
                'theme' => $theme,
                'diff' => $diff,
                'difficulty' => $diff
            ];
        }

        if ($unique) {
            shuffle($unique);
            $themePools[$theme][$diff] = $unique;
        }
    }

    if (empty($themePools[$theme])) {
        unset($themePools[$theme]);
    }
}

if (empty($themePools)) {
    respond_json(400, [
        'ok' => false,
        'message' => 'Aucun mot disponible pour la sÃ©lection demandÃ©e'
    ]);
}

$themeKeys = array_keys($themePools);
$themeCount = count($themeKeys);
$basePerTheme = intdiv($requested, $themeCount);
$remainderThemes = $requested % $themeCount;
$deck = [];
$usedKeys = [];

foreach ($themeKeys as $index => $theme) {
    $target = $basePerTheme + ($index < $remainderThemes ? 1 : 0);
    $picked = take_words_from_theme($themePools[$theme], $target, $usedKeys);

    foreach ($picked as $item) {
        $deck[] = $item;
    }
}

if (count($deck) < $requested) {
    $remainingPool = [];

    foreach ($themePools as $diffPools) {
        foreach ($diffPools as $items) {
            foreach ($items as $item) {
                $globalKey = normalize_word_key((string) ($item['w'] ?? ''));
                if ($globalKey !== '' && !isset($usedKeys[$globalKey])) {
                    $remainingPool[] = $item;
                }
            }
        }
    }

    shuffle($remainingPool);

    foreach ($remainingPool as $item) {
        $globalKey = normalize_word_key((string) ($item['w'] ?? ''));
        if ($globalKey === '' || isset($usedKeys[$globalKey])) {
            continue;
        }

        $deck[] = $item;
        $usedKeys[$globalKey] = true;

        if (count($deck) >= $requested) {
            break;
        }
    }
}

if (empty($deck)) {
    respond_json(400, [
        'ok' => false,
        'message' => 'Aucun mot disponible'
    ]);
}

shuffle($deck);

respond_json(200, [
    'ok' => true,
    'deck' => array_values($deck),
    'wordCountServed' => count($deck)
]);
