<?php
declare(strict_types=1);
session_start();
date_default_timezone_set('UTC');

const SURVEY_ROOT = __DIR__;
const FORMS_ROOT = SURVEY_ROOT . '/forms';
const DEFAULT_ADMIN_PASSWORD = 'ChangeMe-MyKollectOr-2026';

function admin_password(): string {
    return getenv('SURVEY_ADMIN_PASSWORD') ?: DEFAULT_ADMIN_PASSWORD;
}

function h(mixed $value): string {
    return htmlspecialchars((string)$value, ENT_QUOTES, 'UTF-8');
}

function slugify(string $value): string {
    $value = trim($value);
    $value = iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $value) ?: $value;
    $value = strtolower($value);
    $value = preg_replace('/[^a-z0-9]+/', '-', $value) ?? '';
    $value = trim($value, '-');
    return $value ?: 'sondage';
}

function ensure_forms_root(): void {
    if (!is_dir(FORMS_ROOT)) {
        mkdir(FORMS_ROOT, 0775, true);
    }
}

function form_dir(string $slug): string {
    return FORMS_ROOT . '/' . slugify($slug);
}

function form_file(string $slug): string {
    return form_dir($slug) . '/questions.json';
}

function responses_file(string $slug): string {
    return form_dir($slug) . '/responses.csv';
}

function meta_defaults(string $slug = ''): array {
    return [
        'slug' => $slug,
        'name' => $slug ?: 'Nouveau sondage',
        'description' => '',
        'maxResponses' => '',
        'endDate' => '',
        'background' => '',
        'shareText' => 'Je viens de répondre à ce sondage. Donne ton avis toi aussi.',
    ];
}

function normalize_form_payload(array $raw, string $fallbackSlug = ''): array {
    $meta = array_merge(meta_defaults($fallbackSlug), $raw['meta'] ?? []);
    $meta['slug'] = slugify($meta['slug'] ?: $fallbackSlug ?: ($meta['name'] ?? 'sondage'));
    $meta['name'] = trim((string)($meta['name'] ?? $meta['slug']));
    $meta['description'] = trim((string)($meta['description'] ?? ''));
    $meta['maxResponses'] = trim((string)($meta['maxResponses'] ?? ''));
    $meta['endDate'] = trim((string)($meta['endDate'] ?? ''));
    $meta['background'] = trim((string)($meta['background'] ?? ''));
    $meta['shareText'] = trim((string)($meta['shareText'] ?? 'Je viens de répondre à ce sondage. Donne ton avis toi aussi.'));

    $steps = $raw['steps'] ?? $raw;
    if (!is_array($steps)) {
        $steps = [];
    }

    $normalized = [];
    foreach ($steps as $step) {
        if (!is_array($step) || empty($step['type'])) {
            continue;
        }
        $type = (string)$step['type'];
        if ($type === 'intro') {
            $normalized[] = [
                'type' => 'intro',
                'title' => trim((string)($step['title'] ?? $meta['name'])),
                'text' => trim((string)($step['text'] ?? $meta['description'])),
                'button' => trim((string)($step['button'] ?? 'Commencer')),
            ];
            continue;
        }
        if ($type === 'identity') {
            $normalized[] = ['type' => 'identity'];
            continue;
        }
        if ($type === 'multiple') {
            $options = array_values(array_filter(array_map(
                static fn($v) => trim((string)$v),
                is_array($step['options'] ?? null) ? $step['options'] : preg_split('/\r\n|\r|\n/', (string)($step['options'] ?? ''))
            )));
            $normalized[] = [
                'type' => 'multiple',
                'question' => trim((string)($step['question'] ?? 'Question à choix')),
                'selection' => (($step['selection'] ?? 'single') === 'multiple') ? 'multiple' : 'single',
                'options' => $options,
            ];
            continue;
        }
        if ($type === 'text') {
            $normalized[] = [
                'type' => 'text',
                'question' => trim((string)($step['question'] ?? 'Question ouverte')),
                'placeholder' => trim((string)($step['placeholder'] ?? 'Votre réponse...')),
            ];
        }
    }

    if (!$normalized || ($normalized[0]['type'] ?? '') !== 'intro') {
        array_unshift($normalized, [
            'type' => 'intro',
            'title' => $meta['name'],
            'text' => $meta['description'],
            'button' => 'Commencer',
        ]);
    }

    $hasIdentity = false;
    foreach ($normalized as $item) {
        if (($item['type'] ?? '') === 'identity') {
            $hasIdentity = true;
            break;
        }
    }
    if (!$hasIdentity) {
        array_splice($normalized, 1, 0, [['type' => 'identity']]);
    }

    return ['meta' => $meta, 'steps' => array_values($normalized)];
}

function load_form(string $slug): ?array {
    $slug = slugify($slug);
    $file = form_file($slug);
    if (!is_file($file)) {
        return null;
    }
    $data = json_decode((string)file_get_contents($file), true);
    if (!is_array($data)) {
        return null;
    }
    if (array_is_list($data)) {
        $data = ['meta' => meta_defaults($slug), 'steps' => $data];
    }
    return normalize_form_payload($data, $slug);
}

function csv_headers(array $steps): array {
    $headers = ['date', 'prenom', 'nom', '_ip_hash', '_user_agent'];
    $index = 1;
    foreach ($steps as $step) {
        if (in_array($step['type'] ?? '', ['multiple', 'text'], true)) {
            $headers[] = 'Q' . $index;
            $index++;
        }
    }
    return $headers;
}

function ensure_responses_csv(string $slug, array $steps): void {
    $file = responses_file($slug);
    if (is_file($file)) {
        return;
    }
    if (!is_dir(form_dir($slug))) {
        mkdir(form_dir($slug), 0775, true);
    }
    $fp = fopen($file, 'wb');
    if ($fp) {
        fputcsv($fp, csv_headers($steps), ';');
        fclose($fp);
    }
}

function save_form(string $slug, array $payload): void {
    ensure_forms_root();
    $payload = normalize_form_payload($payload, $slug);
    $slug = $payload['meta']['slug'];
    $dir = form_dir($slug);
    if (!is_dir($dir)) {
        mkdir($dir, 0775, true);
    }
    file_put_contents(
        form_file($slug),
        json_encode($payload, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)
    );
    ensure_responses_csv($slug, $payload['steps']);
}

function list_forms(): array {
    ensure_forms_root();
    $items = [];
    foreach (glob(FORMS_ROOT . '/*', GLOB_ONLYDIR) ?: [] as $dir) {
        $slug = basename($dir);
        $form = load_form($slug);
        if (!$form) {
            continue;
        }
        $form['responseCount'] = response_count($slug);
        $form['closed'] = is_form_closed($form);
        $items[] = $form;
    }
    usort($items, static fn($a, $b) => strcmp($a['meta']['name'], $b['meta']['name']));
    return $items;
}

function response_rows(string $slug): array {
    $file = responses_file($slug);
    if (!is_file($file)) {
        return [];
    }
    $fp = fopen($file, 'rb');
    if (!$fp) {
        return [];
    }
    $rows = [];
    $headers = fgetcsv($fp, 0, ';') ?: [];
    while (($line = fgetcsv($fp, 0, ';')) !== false) {
        if (!$line) {
            continue;
        }
        $assoc = [];
        foreach ($headers as $i => $header) {
            $assoc[$header] = $line[$i] ?? '';
        }
        $rows[] = $assoc;
    }
    fclose($fp);
    return $rows;
}

function response_count(string $slug): int {
    return count(response_rows($slug));
}

function base_url(): string {
    $https = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') || (($_SERVER['SERVER_PORT'] ?? '') === '443');
    $scheme = $https ? 'https' : 'http';
    $host = $_SERVER['HTTP_HOST'] ?? 'localhost';
    $scriptName = $_SERVER['SCRIPT_NAME'] ?? '';
    $basePath = rtrim(str_replace('\\', '/', dirname($scriptName)), '/');
    return $scheme . '://' . $host . ($basePath === '/' ? '' : $basePath);
}

function survey_url(string $slug): string {
    return base_url() . '/survey.php?form=' . rawurlencode(slugify($slug));
}

function is_authenticated(): bool {
    return !empty($_SESSION['survey_admin']);
}

function attempt_login(string $password): bool {
    if (hash_equals(admin_password(), $password)) {
        $_SESSION['survey_admin'] = true;
        return true;
    }
    return false;
}

function logout_admin(): void {
    unset($_SESSION['survey_admin']);
}

function require_auth(): void {
    if (!is_authenticated()) {
        header('Location: index.php');
        exit;
    }
}

function client_ip(): string {
    $candidates = [
        $_SERVER['HTTP_CF_CONNECTING_IP'] ?? '',
        $_SERVER['HTTP_X_FORWARDED_FOR'] ?? '',
        $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0',
    ];
    foreach ($candidates as $candidate) {
        if (!$candidate) {
            continue;
        }
        $parts = array_map('trim', explode(',', $candidate));
        foreach ($parts as $part) {
            if (filter_var($part, FILTER_VALIDATE_IP)) {
                return $part;
            }
        }
    }
    return '0.0.0.0';
}

function client_ip_hash(): string {
    return substr(hash('sha256', client_ip()), 0, 24);
}

function recent_ip_attempts(string $slug, int $windowSeconds = 3600): int {
    $now = time();
    $hash = client_ip_hash();
    $count = 0;
    foreach (response_rows($slug) as $row) {
        if (($row['_ip_hash'] ?? '') !== $hash) {
            continue;
        }
        $ts = strtotime((string)($row['date'] ?? ''));
        if ($ts && ($now - $ts) <= $windowSeconds) {
            $count++;
        }
    }
    return $count;
}

function is_form_closed(array $form): bool {
    $slug = $form['meta']['slug'];
    $max = trim((string)($form['meta']['maxResponses'] ?? ''));
    if ($max !== '' && ctype_digit($max) && response_count($slug) >= (int)$max) {
        return true;
    }
    $endDate = trim((string)($form['meta']['endDate'] ?? ''));
    if ($endDate !== '') {
        $deadline = strtotime($endDate . ' 23:59:59 UTC');
        if ($deadline && time() > $deadline) {
            return true;
        }
    }
    return false;
}

function save_response(string $slug, array $answers): array {
    $form = load_form($slug);
    if (!$form) {
        throw new RuntimeException('Sondage introuvable.');
    }
    ensure_responses_csv($slug, $form['steps']);

    $questionAnswers = [];
    $qIndex = 1;
    foreach ($form['steps'] as $step) {
        if (($step['type'] ?? '') === 'multiple' || ($step['type'] ?? '') === 'text') {
            $key = 'Q' . $qIndex;
            $value = $answers[$key] ?? '';
            if (is_array($value)) {
                $value = implode(' | ', array_map('trim', $value));
            }
            $questionAnswers[] = trim((string)$value);
            $qIndex++;
        }
    }

    $row = array_merge([
        gmdate('c'),
        trim((string)($answers['prenom'] ?? '')),
        trim((string)($answers['nom'] ?? '')),
        client_ip_hash(),
        substr((string)($_SERVER['HTTP_USER_AGENT'] ?? ''), 0, 190),
    ], $questionAnswers);

    $fp = fopen(responses_file($slug), 'ab');
    if (!$fp) {
        throw new RuntimeException('Impossible d’écrire les réponses.');
    }
    fputcsv($fp, $row, ';');
    fclose($fp);

    return $row;
}

function build_stats(string $slug): array {
    $form = load_form($slug);
    if (!$form) {
        return ['ok' => false, 'error' => 'Sondage introuvable'];
    }
    $rows = response_rows($slug);
    $charts = [];
    $qIndex = 1;
    foreach ($form['steps'] as $step) {
        $type = $step['type'] ?? '';
        if (!in_array($type, ['multiple', 'text'], true)) {
            continue;
        }
        $key = 'Q' . $qIndex;
        $values = array_map(static fn($row) => trim((string)($row[$key] ?? '')), $rows);
        if ($type === 'multiple') {
            $counts = [];
            foreach ($values as $value) {
                if ($value === '') {
                    continue;
                }
                $parts = array_values(array_filter(array_map('trim', explode('|', $value))));
                foreach ($parts as $part) {
                    $counts[$part] = ($counts[$part] ?? 0) + 1;
                }
            }
            foreach ($step['options'] as $option) {
                $counts[$option] = $counts[$option] ?? 0;
            }
            $charts[] = [
                'key' => $key,
                'question' => $step['question'],
                'kind' => 'multiple',
                'chartType' => 'doughnut',
                'labels' => array_keys($counts),
                'data' => array_values($counts),
                'selection' => $step['selection'] ?? 'single',
            ];
        } else {
            $counts = [];
            foreach ($values as $value) {
                if ($value === '') {
                    continue;
                }
                $label = mb_strimwidth($value, 0, 52, '…', 'UTF-8');
                $counts[$label] = ($counts[$label] ?? 0) + 1;
            }
            arsort($counts);
            $counts = array_slice($counts, 0, 8, true);
            $charts[] = [
                'key' => $key,
                'question' => $step['question'],
                'kind' => 'text',
                'chartType' => 'bar',
                'labels' => array_keys($counts),
                'data' => array_values($counts),
                'topAnswers' => array_keys($counts),
            ];
        }
        $qIndex++;
    }

    return [
        'ok' => true,
        'meta' => $form['meta'],
        'count' => count($rows),
        'charts' => $charts,
    ];
}
