<?php

require_once __DIR__ . '/config.php';

function scdiscord_bootstrap(): void
{
    static $bootstrapped = false;

    if ($bootstrapped) {
        return;
    }

    $db = db();

    $db->exec(
        "CREATE TABLE IF NOT EXISTS tbl_scwebhooks (
            cl_scwebhook_id INT(11) NOT NULL AUTO_INCREMENT,
            cl_scwebhook_name VARCHAR(255) NOT NULL,
            cl_scwebhook_url TEXT NOT NULL,
            cl_scwebhook_is_forum TINYINT(1) NOT NULL DEFAULT 0,
            PRIMARY KEY (cl_scwebhook_id)
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci"
    );

    $db->exec(
        "CREATE TABLE IF NOT EXISTS tbl_scbanners (
            cl_scbanner_id INT(11) NOT NULL AUTO_INCREMENT,
            cl_scbanner_name VARCHAR(255) NOT NULL,
            cl_scbanner_url TEXT NOT NULL,
            cl_scbanner_border_color VARCHAR(20) NOT NULL DEFAULT '#ffae00',
            PRIMARY KEY (cl_scbanner_id)
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci"
    );

    $columns_stmt = $db->query("SHOW COLUMNS FROM tbl_scbanners LIKE 'cl_scbanner_border_color'");
    $has_border_color = (bool) $columns_stmt->fetch();
    if (!$has_border_color) {
        $db->exec("ALTER TABLE tbl_scbanners ADD COLUMN cl_scbanner_border_color VARCHAR(20) NOT NULL DEFAULT '#ffae00' AFTER cl_scbanner_url");
    }

    $db->exec(
        "CREATE TABLE IF NOT EXISTS tbl_scnotifications (
            cl_scnotification_id INT(11) NOT NULL AUTO_INCREMENT,
            cl_scnotification_webhook_id INT(11) NOT NULL,
            cl_scnotification_banner_id INT(11) DEFAULT NULL,
            cl_scnotification_title VARCHAR(255) NOT NULL DEFAULT '',
            cl_scnotification_message TEXT NOT NULL,
            cl_scnotification_payload LONGTEXT NOT NULL,
            cl_scnotification_response LONGTEXT DEFAULT NULL,
            cl_scnotification_success TINYINT(1) NOT NULL DEFAULT 0,
            cl_scnotification_created_by VARCHAR(190) NOT NULL,
            cl_scnotification_created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
            PRIMARY KEY (cl_scnotification_id),
            KEY idx_scnotification_webhook (cl_scnotification_webhook_id),
            KEY idx_scnotification_banner (cl_scnotification_banner_id),
            CONSTRAINT fk_scnotification_webhook FOREIGN KEY (cl_scnotification_webhook_id)
                REFERENCES tbl_scwebhooks (cl_scwebhook_id)
                ON UPDATE CASCADE
                ON DELETE RESTRICT,
            CONSTRAINT fk_scnotification_banner FOREIGN KEY (cl_scnotification_banner_id)
                REFERENCES tbl_scbanners (cl_scbanner_id)
                ON UPDATE CASCADE
                ON DELETE SET NULL
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci"
    );

    $stmt_existing_red = $db->prepare('SELECT cl_scbanner_id FROM tbl_scbanners WHERE cl_scbanner_name = :name LIMIT 1');
    $stmt_existing_red->execute(['name' => 'Alerte Rouge']);
    $existing_red_banner = $stmt_existing_red->fetch(PDO::FETCH_ASSOC);

    if ($existing_red_banner) {
        $stmt_update_red = $db->prepare(
            'UPDATE tbl_scbanners
             SET cl_scbanner_border_color = CASE
                    WHEN cl_scbanner_border_color IS NULL OR cl_scbanner_border_color = "" OR cl_scbanner_border_color = "#ffae00"
                        THEN :border_color
                    ELSE cl_scbanner_border_color
                 END
             WHERE cl_scbanner_id = :id'
        );
        $stmt_update_red->execute([
            'border_color' => '#ff3b30',
            'id' => $existing_red_banner['cl_scbanner_id'],
        ]);
    }

    $bootstrapped = true;
}

function scdiscord_mask_webhook_url(string $url): string
{
    $trimmed = trim($url);
    if ($trimmed === '') {
        return '';
    }

    $length = strlen($trimmed);
    if ($length <= 24) {
        return str_repeat('•', max(8, $length));
    }

    return substr($trimmed, 0, 32) . str_repeat('•', 18) . substr($trimmed, -10);
}

function scdiscord_normalize_hex_color(string $color): string
{
    $candidate = strtoupper(trim($color));
    if ($candidate === '') {
        return '#FFAE00';
    }

    if ($candidate[0] !== '#') {
        $candidate = '#' . $candidate;
    }

    if (!preg_match('/^#[0-9A-F]{6}$/', $candidate)) {
        return '#FFAE00';
    }

    return $candidate;
}

function scdiscord_hex_to_decimal(string $color): int
{
    return hexdec(ltrim(scdiscord_normalize_hex_color($color), '#'));
}

function scdiscord_build_mentions(bool $notify_here, bool $notify_everyone): array
{
    $parts = [];

    if ($notify_here) {
        $parts[] = '@here';
    }

    if ($notify_everyone) {
        $parts[] = '@everyone';
    }

    return $parts;
}

function scdiscord_build_thread_name(string $title, string $location, string $start_date): string
{
    $parts = [];

    if ($title !== '') {
        $parts[] = $title;
    }

    if ($location !== '') {
        $parts[] = $location;
    }

    if ($start_date !== '') {
        $parts[] = $start_date;
    }

    $thread_name = trim(implode(' • ', $parts));

    if ($thread_name === '') {
        $thread_name = 'Notification Discord';
    }

    return mb_substr($thread_name, 0, 100);
}

function scdiscord_post_webhook(string $webhook_url, array $payload): array
{
    $target_url = $webhook_url;
    $separator = (str_contains($target_url, '?')) ? '&' : '?';
    $target_url .= $separator . 'wait=true';

    $json_payload = json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);

    if ($json_payload === false) {
        return [
            'success' => false,
            'http_code' => 0,
            'response' => 'Erreur d\'encodage JSON.',
        ];
    }

    if (function_exists('curl_init')) {
        $ch = curl_init($target_url);
        curl_setopt_array($ch, [
            CURLOPT_POST => true,
            CURLOPT_POSTFIELDS => $json_payload,
            CURLOPT_HTTPHEADER => [
                'Content-Type: application/json',
                'Content-Length: ' . strlen($json_payload),
            ],
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_TIMEOUT => 20,
        ]);

        $response = curl_exec($ch);
        $http_code = (int) curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $curl_error = curl_error($ch);
        curl_close($ch);

        if ($response === false) {
            return [
                'success' => false,
                'http_code' => $http_code,
                'response' => $curl_error !== '' ? $curl_error : 'Erreur CURL inconnue.',
            ];
        }

        return [
            'success' => $http_code >= 200 && $http_code < 300,
            'http_code' => $http_code,
            'response' => $response,
        ];
    }

    $context = stream_context_create([
        'http' => [
            'method' => 'POST',
            'header' => "Content-Type: application/json\r\n",
            'content' => $json_payload,
            'timeout' => 20,
            'ignore_errors' => true,
        ],
    ]);

    $response = @file_get_contents($target_url, false, $context);
    $http_code = 0;
    if (isset($http_response_header) && is_array($http_response_header)) {
        foreach ($http_response_header as $header_line) {
            if (preg_match('#^HTTP/\S+\s+(\d{3})#', $header_line, $matches)) {
                $http_code = (int) $matches[1];
                break;
            }
        }
    }

    return [
        'success' => $response !== false && $http_code >= 200 && $http_code < 300,
        'http_code' => $http_code,
        'response' => $response === false ? 'Erreur lors de la requête HTTP.' : $response,
    ];
}

function scdiscord_get_bot_token(): string
{
    $candidates = [];

    if (defined('DISCORD_BOT_TOKEN') && is_string(DISCORD_BOT_TOKEN)) {
        $candidates[] = DISCORD_BOT_TOKEN;
    }

    foreach (['DISCORD_BOT_TOKEN', 'SC_DISCORD_BOT_TOKEN', 'BOT_TOKEN'] as $env_key) {
        $value = getenv($env_key);
        if ($value !== false) {
            $candidates[] = $value;
        }
    }

    foreach ($candidates as $candidate) {
        $token = trim((string) $candidate);
        if ($token !== '') {
            return $token;
        }
    }

    return '';
}

function scdiscord_decode_json_response(?string $response): array
{
    if (!is_string($response) || trim($response) === '') {
        return [];
    }

    $decoded = json_decode($response, true);
    return is_array($decoded) ? $decoded : [];
}

function scdiscord_bot_request(string $method, string $url, string $bot_token, ?array $payload = null): array
{
    $headers = [
        'Authorization: Bot ' . $bot_token,
    ];

    $json_payload = null;
    if ($payload !== null) {
        $json_payload = json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
        if ($json_payload === false) {
            return [
                'success' => false,
                'http_code' => 0,
                'response' => 'Erreur d\'encodage JSON.',
            ];
        }
        $headers[] = 'Content-Type: application/json';
        $headers[] = 'Content-Length: ' . strlen($json_payload);
    }

    if (function_exists('curl_init')) {
        $ch = curl_init($url);
        curl_setopt_array($ch, [
            CURLOPT_CUSTOMREQUEST => strtoupper($method),
            CURLOPT_HTTPHEADER => $headers,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_TIMEOUT => 20,
        ]);

        if ($json_payload !== null) {
            curl_setopt($ch, CURLOPT_POSTFIELDS, $json_payload);
        }

        $response = curl_exec($ch);
        $http_code = (int) curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $curl_error = curl_error($ch);
        curl_close($ch);

        if ($response === false) {
            return [
                'success' => false,
                'http_code' => $http_code,
                'response' => $curl_error !== '' ? $curl_error : 'Erreur CURL inconnue.',
            ];
        }

        return [
            'success' => $http_code >= 200 && $http_code < 300,
            'http_code' => $http_code,
            'response' => $response,
        ];
    }

    $header_lines = implode("\r\n", $headers) . "\r\n";
    $context = stream_context_create([
        'http' => [
            'method' => strtoupper($method),
            'header' => $header_lines,
            'content' => $json_payload ?? '',
            'timeout' => 20,
            'ignore_errors' => true,
        ],
    ]);

    $response = @file_get_contents($url, false, $context);
    $http_code = 0;
    if (isset($http_response_header) && is_array($http_response_header)) {
        foreach ($http_response_header as $header_line) {
            if (preg_match('#^HTTP/\S+\s+(\d{3})#', $header_line, $matches)) {
                $http_code = (int) $matches[1];
                break;
            }
        }
    }

    return [
        'success' => $response !== false && $http_code >= 200 && $http_code < 300,
        'http_code' => $http_code,
        'response' => $response === false ? 'Erreur lors de la requête HTTP.' : $response,
    ];
}

function scdiscord_apply_bot_actions(array $message_data, bool $use_reactions, bool $use_publicthread, string $thread_name): array
{
    if (!$use_reactions && !$use_publicthread) {
        return [
            'success' => true,
            'http_code' => 200,
            'response' => 'Aucune action bot demandée.',
            'details' => [],
        ];
    }

    $message_id = trim((string) ($message_data['id'] ?? ''));
    $channel_id = trim((string) ($message_data['channel_id'] ?? ''));

    if ($message_id === '' || $channel_id === '') {
        return [
            'success' => false,
            'http_code' => 0,
            'response' => 'Réponse Discord invalide : id de message ou channel_id manquant.',
            'details' => [],
        ];
    }

    $bot_token = scdiscord_get_bot_token();
    if ($bot_token === '') {
        return [
            'success' => false,
            'http_code' => 0,
            'response' => 'Token bot Discord manquant. Définis DISCORD_BOT_TOKEN côté serveur.',
            'details' => [],
        ];
    }

    $details = [];
    $last_http_code = 200;
    $failed = false;

    if ($use_reactions) {
        foreach (['👍', '⌛', '❔', '👎'] as $emoji) {
            $url = 'https://discord.com/api/v10/channels/' . rawurlencode($channel_id) . '/messages/' . rawurlencode($message_id) . '/reactions/' . rawurlencode($emoji) . '/@me';
            $result = scdiscord_bot_request('PUT', $url, $bot_token);
            $action_success = !empty($result['success']);
            $last_http_code = (int) ($result['http_code'] ?? $last_http_code);
            $details[] = [
                'action' => 'reaction',
                'emoji' => $emoji,
                'success' => $action_success,
                'http_code' => $last_http_code,
                'response' => (string) ($result['response'] ?? ''),
            ];

            if (!$action_success) {
                $failed = true;
            }

            sleep(1);
        }
    }

    if ($use_publicthread) {
        $thread_payload = [
            'name' => $thread_name !== '' ? $thread_name : 'Discussion - Opération',
            'auto_archive_duration' => 1440,
            'type' => 11,
        ];
        $url = 'https://discord.com/api/v10/channels/' . rawurlencode($channel_id) . '/messages/' . rawurlencode($message_id) . '/threads';
        $result = scdiscord_bot_request('POST', $url, $bot_token, $thread_payload);
        $action_success = !empty($result['success']);
        $last_http_code = (int) ($result['http_code'] ?? $last_http_code);
        $details[] = [
            'action' => 'thread',
            'success' => $action_success,
            'http_code' => $last_http_code,
            'response' => (string) ($result['response'] ?? ''),
        ];

        if (!$action_success) {
            $failed = true;
        }
    }

    return [
        'success' => !$failed,
        'http_code' => $failed ? $last_http_code : 200,
        'response' => json_encode($details, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),
        'details' => $details,
    ];
}

