<?php
declare(strict_types=1);

require_once __DIR__ . '/customer_provision.php';
require_once __DIR__ . '/portal_auth.php';

function golder_demo_secret_key_raw(): string
{
    $seed = trim(golder_env('GOLDER_DEMO_SECRET_KEY', ''));
    if ($seed === '') {
        throw new RuntimeException('GOLDER_DEMO_SECRET_KEY is not configured.');
    }

    if (str_starts_with($seed, 'base64:')) {
        $decoded = base64_decode(substr($seed, 7), true);
        if (is_string($decoded) && strlen($decoded) >= 32) {
            return substr($decoded, 0, 32);
        }
        throw new RuntimeException('GOLDER_DEMO_SECRET_KEY base64 payload is invalid.');
    }

    if (str_starts_with($seed, 'hex:')) {
        $decoded = @hex2bin(substr($seed, 4));
        if (is_string($decoded) && strlen($decoded) >= 32) {
            return substr($decoded, 0, 32);
        }
        throw new RuntimeException('GOLDER_DEMO_SECRET_KEY hex payload is invalid.');
    }

    return hash('sha256', $seed, true);
}

function golder_encrypt_demo_secret(string $plain): string
{
    $plain = (string)$plain;
    if ($plain === '') {
        return '';
    }
    $key = golder_demo_secret_key_raw();
    $iv = random_bytes(12);
    $tag = '';
    $cipher = openssl_encrypt($plain, 'aes-256-gcm', $key, OPENSSL_RAW_DATA, $iv, $tag, '', 16);
    if (!is_string($cipher) || $cipher === '') {
        throw new RuntimeException('Demo secret encryption failed.');
    }
    return base64_encode($iv . $tag . $cipher);
}

function golder_decrypt_demo_secret(string $encoded): string
{
    $encoded = trim($encoded);
    if ($encoded === '') {
        return '';
    }
    try {
        $key = golder_demo_secret_key_raw();
    } catch (Throwable $_ignored) {
        return '';
    }
    $raw = base64_decode($encoded, true);
    if (!is_string($raw) || strlen($raw) <= 28) {
        return '';
    }
    $iv = substr($raw, 0, 12);
    $tag = substr($raw, 12, 16);
    $cipher = substr($raw, 28);
    $plain = openssl_decrypt($cipher, 'aes-256-gcm', $key, OPENSSL_RAW_DATA, $iv, $tag, '');
    return is_string($plain) ? $plain : '';
}

function golder_demo_request_by_id(PDO $master, string $requestId): ?array
{
    golder_ensure_payment_tables($master);
    $requestId = trim($requestId);
    if ($requestId === '') {
        return null;
    }
    $st = $master->prepare('SELECT * FROM demo_requests WHERE id = :id LIMIT 1');
    $st->execute([':id' => $requestId]);
    $row = $st->fetch();
    return is_array($row) ? $row : null;
}

function golder_create_demo_request(
    PDO $master,
    int $portalUserId,
    string $fullName,
    string $email,
    string $phone,
    string $planType = 'A-COMPLEX',
    int $pcDevices = 1,
    int $webSessions = 1
): array {
    golder_ensure_payment_tables($master);

    if ($portalUserId <= 0) {
        return ['ok' => false, 'message' => 'portal user is required.'];
    }

    $fullName = trim($fullName);
    $email = strtolower(trim($email));
    $phone = trim($phone);

    if ($fullName === '' || ($email === '' && $phone === '')) {
        return ['ok' => false, 'message' => 'full_name and one contact field are required.'];
    }
    if ($email !== '' && filter_var($email, FILTER_VALIDATE_EMAIL) === false) {
        return ['ok' => false, 'message' => 'email is invalid.'];
    }
    if ($phone !== '' && preg_match('/^[0-9+()\\-\\s]{7,20}$/', $phone) !== 1) {
        return ['ok' => false, 'message' => 'phone is invalid.'];
    }

    $normalized = golder_normalize_plan_limits($planType, $pcDevices, $webSessions);
    $requestId = golder_uuid4();

    $master->prepare(
        'INSERT INTO demo_requests
         (id, portal_user_id, full_name, email, phone, requested_plan_type, requested_pc_devices, requested_web_sessions, status, created_at)
         VALUES
         (:id, :uid, :fn, :em, :ph, :pt, :pc, :ws, :st, UTC_TIMESTAMP())'
    )->execute([
        ':id' => $requestId,
        ':uid' => $portalUserId,
        ':fn' => $fullName,
        ':em' => ($email !== '' ? $email : null),
        ':ph' => ($phone !== '' ? $phone : null),
        ':pt' => (string)$normalized['plan_type'],
        ':pc' => (int)$normalized['max_pc_devices'],
        ':ws' => (int)$normalized['max_web_sessions'],
        ':st' => 'pending',
    ]);

    return ['ok' => true, 'request_id' => $requestId];
}

function golder_add_demo_request_message(PDO $master, string $requestId, string $senderType, string $senderName, string $message): void
{
    golder_ensure_payment_tables($master);
    $requestId = trim($requestId);
    $senderType = trim($senderType);
    $senderName = trim($senderName);
    $message = trim($message);
    if ($requestId === '' || $senderType === '' || $message === '') {
        return;
    }
    $master->prepare(
        'INSERT INTO demo_request_messages (demo_request_id, sender_type, sender_name, message_text, created_at)
         VALUES (:id, :st, :sn, :msg, UTC_TIMESTAMP())'
    )->execute([
        ':id' => $requestId,
        ':st' => substr($senderType, 0, 20),
        ':sn' => ($senderName !== '' ? substr($senderName, 0, 120) : null),
        ':msg' => $message,
    ]);
}

function golder_demo_request_list_for_portal(PDO $master, int $portalUserId, int $limit = 100): array
{
    golder_ensure_payment_tables($master);
    $limit = max(1, min(300, $limit));
    $st = $master->prepare(
        'SELECT id, status, full_name, email, phone, requested_plan_type, requested_pc_devices, requested_web_sessions,
                admin_message, demo_code, demo_username, demo_password_enc, demo_expires_at, mail_status, created_at, updated_at, approved_at, rejected_at
         FROM demo_requests
         WHERE portal_user_id = :uid
         ORDER BY created_at DESC
         LIMIT ' . (int)$limit
    );
    $st->execute([':uid' => $portalUserId]);
    return $st->fetchAll() ?: [];
}

function golder_demo_request_detail_for_portal(PDO $master, int $portalUserId, string $requestId): ?array
{
    $row = golder_demo_request_by_id($master, $requestId);
    if (!$row) {
        return null;
    }
    if ((int)($row['portal_user_id'] ?? 0) !== $portalUserId) {
        return null;
    }
    $row['demo_password'] = golder_decrypt_demo_secret((string)($row['demo_password_enc'] ?? ''));
    $row['messages'] = golder_demo_request_messages($master, $requestId);
    return $row;
}

function golder_build_demo_username(string $email, string $phone): string
{
    $base = trim($email);
    if ($base !== '' && strpos($base, '@') !== false) {
        $base = strstr($base, '@', true) ?: $base;
    }
    if ($base === '') {
        $base = 'demo_' . substr(hash('sha256', $phone . microtime(true)), 0, 6);
    }
    $base = preg_replace('/[^a-zA-Z0-9_]/', '', $base) ?: 'demo';
    return 'demo_' . strtolower($base);
}

function golder_approve_demo_request(PDO $master, string $requestId, string $adminUser, string $passwordOverride = ''): array
{
    golder_ensure_payment_tables($master);
    golder_demo_secret_key_raw();

    $row = golder_demo_request_by_id($master, $requestId);
    if (!$row) {
        return ['ok' => false, 'message' => 'demo request not found.'];
    }
    if ((string)($row['status'] ?? '') !== 'pending') {
        return ['ok' => false, 'message' => 'demo request is not pending.'];
    }

    $email = trim((string)($row['email'] ?? ''));
    $phone = trim((string)($row['phone'] ?? ''));
    $username = golder_build_demo_username($email, $phone);

    $passwordOverride = trim($passwordOverride);
    $demoPassword = ($passwordOverride !== '') ? $passwordOverride : golder_generate_password(10);
    if (strlen($demoPassword) < 6) {
        return ['ok' => false, 'message' => 'demo password is too short.'];
    }

    $provision = golder_provision_customer_with_tenant(
        $master,
        $username,
        $demoPassword,
        $email,
        $phone,
        (string)($row['requested_plan_type'] ?? 'A-COMPLEX'),
        (int)($row['requested_pc_devices'] ?? 1),
        (int)($row['requested_web_sessions'] ?? 1),
        golder_demo_duration_key(),
        true
    );
    if (empty($provision['ok'])) {
        return ['ok' => false, 'message' => (string)($provision['message'] ?? 'provision failed.')];
    }

    $customerId = (int)($provision['customer_id'] ?? 0);
    if ($customerId <= 0) {
        return ['ok' => false, 'message' => 'provision returned invalid customer id.'];
    }

    $demoCode = golder_generate_demo_code($master);
    $expiresAt = golder_demo_expiry_from_now();
    $encPassword = golder_encrypt_demo_secret($demoPassword);

    $master->prepare(
        'INSERT INTO demo_licenses (customer_id, demo_code, starts_at, expires_at, status)
         VALUES (:cid, :dc, UTC_TIMESTAMP(), :ex, :st)'
    )->execute([
        ':cid' => $customerId,
        ':dc' => $demoCode,
        ':ex' => $expiresAt,
        ':st' => 'active',
    ]);

    $master->prepare(
        'UPDATE demo_requests
         SET status = :st,
             approved_by = :ab,
             approved_at = UTC_TIMESTAMP(),
             approved_customer_id = :cid,
             demo_code = :dc,
             demo_username = :du,
             demo_password_enc = :pw,
             demo_expires_at = :ex,
             updated_at = UTC_TIMESTAMP()
         WHERE id = :id'
    )->execute([
        ':st' => 'approved',
        ':ab' => $adminUser,
        ':cid' => $customerId,
        ':dc' => $demoCode,
        ':du' => (string)($provision['username'] ?? $username),
        ':pw' => $encPassword,
        ':ex' => $expiresAt,
        ':id' => $requestId,
    ]);

    golder_add_demo_request_message(
        $master,
        $requestId,
        'admin',
        $adminUser,
        'Demo talebiniz onaylandi.'
    );

    $mailResult = ['ok' => false, 'message' => 'mail skipped'];
    if ($email !== '') {
        $subject = 'Golder demo credentials';
        $text = "Merhaba,\n\nDemo talebiniz onaylandi.\nKullanici adi: " . (string)($provision['username'] ?? $username)
            . "\nSifre: " . $demoPassword
            . "\nDemo kodu: " . $demoCode
            . "\nSure: " . golder_demo_duration_human()
            . "\nBitis: " . $expiresAt
            . "\n";
        $html = '<p>Merhaba,</p>'
            . '<p>Demo talebiniz onaylandi.</p>'
            . '<p><strong>Kullanici adi:</strong> ' . htmlspecialchars((string)($provision['username'] ?? $username), ENT_QUOTES, 'UTF-8') . '<br>'
            . '<strong>Sifre:</strong> ' . htmlspecialchars($demoPassword, ENT_QUOTES, 'UTF-8') . '<br>'
            . '<strong>Demo kodu:</strong> ' . htmlspecialchars($demoCode, ENT_QUOTES, 'UTF-8') . '<br>'
            . '<strong>Sure:</strong> ' . htmlspecialchars(golder_demo_duration_human(), ENT_QUOTES, 'UTF-8') . '<br>'
            . '<strong>Bitis:</strong> ' . htmlspecialchars($expiresAt, ENT_QUOTES, 'UTF-8') . '</p>';
        $mailResult = golder_send_smtp_mail($email, $subject, $text, $html);
    }

    $master->prepare(
        'UPDATE demo_requests
         SET mail_status = :ms,
             mail_last_error = :me,
             updated_at = UTC_TIMESTAMP()
         WHERE id = :id'
    )->execute([
        ':ms' => !empty($mailResult['ok']) ? 'sent' : 'failed',
        ':me' => !empty($mailResult['ok']) ? null : substr((string)($mailResult['message'] ?? 'mail failed'), 0, 1000),
        ':id' => $requestId,
    ]);

    return [
        'ok' => true,
        'customer_id' => $customerId,
        'demo_code' => $demoCode,
        'expires_at' => $expiresAt,
        'credentials' => [
            'username' => (string)($provision['username'] ?? $username),
            'password' => $demoPassword,
        ],
        'mail' => $mailResult,
    ];
}

function golder_reject_demo_request(PDO $master, string $requestId, string $adminUser, string $message): array
{
    golder_ensure_payment_tables($master);
    $row = golder_demo_request_by_id($master, $requestId);
    if (!$row) {
        return ['ok' => false, 'message' => 'demo request not found.'];
    }
    if ((string)($row['status'] ?? '') !== 'pending') {
        return ['ok' => false, 'message' => 'demo request is not pending.'];
    }
    $message = trim($message);
    if ($message === '') {
        $message = 'Demo talebiniz reddedildi.';
    }

    $master->prepare(
        'UPDATE demo_requests
         SET status = :st,
             rejected_by = :rb,
             rejected_at = UTC_TIMESTAMP(),
             admin_message = :msg,
             updated_at = UTC_TIMESTAMP()
         WHERE id = :id'
    )->execute([
        ':st' => 'rejected',
        ':rb' => $adminUser,
        ':msg' => $message,
        ':id' => $requestId,
    ]);

    golder_add_demo_request_message($master, $requestId, 'admin', $adminUser, $message);
    return ['ok' => true];
}


