<?php
/**
 * AURA FARMING — Diamantes — Parte 04
 * Loja de Diamantes para o usuário.
 *
 * Esta etapa apenas mostra os pacotes, saldo, histórico e cria pedido interno
 * com status pending. Mercado Pago entra somente na Parte 05.
 */

if (!defined('AURA_DIAMONDS_PART04_VERSION')) {
    define('AURA_DIAMONDS_PART04_VERSION', '4.0.0');
}

require_once __DIR__ . '/diamond_functions.php';

function afDiamondShopConfig(PDO $pdo, string $key, mixed $default = null): mixed
{
    try {
        $st = $pdo->prepare('SELECT valor, tipo FROM af_configuracoes WHERE chave = ? LIMIT 1');
        $st->execute([$key]);
        $row = $st->fetch();
        if (!$row) return $default;
        return match ((string)($row['tipo'] ?? 'string')) {
            'bool' => filter_var($row['valor'], FILTER_VALIDATE_BOOLEAN),
            'int' => (int)$row['valor'],
            'float' => (float)$row['valor'],
            'json' => json_decode((string)$row['valor'], true) ?: $default,
            default => (string)$row['valor'],
        };
    } catch (Throwable $e) {
        return $default;
    }
}

function afDiamondShopMoney(float|int|string $amount, string $currency = 'BRL'): string
{
    $amount = (float)$amount;
    if ($currency === 'BRL') {
        return 'R$ ' . number_format($amount, 2, ',', '.');
    }
    return number_format($amount, 2, ',', '.') . ' ' . $currency;
}

function afDiamondShopTotalDiamonds(array $package): int
{
    return max(0, (int)($package['diamonds'] ?? 0)) + max(0, (int)($package['bonus_diamonds'] ?? 0));
}

function afDiamondShopListActivePackages(PDO $pdo): array
{
    afDiamondsAssertInstalled($pdo);
    $st = $pdo->query('SELECT * FROM af_diamond_packages WHERE active = 1 ORDER BY sort_order ASC, diamonds ASC, id ASC');
    return $st->fetchAll() ?: [];
}

function afDiamondShopGetActivePackage(PDO $pdo, int $packageId): ?array
{
    afDiamondsAssertInstalled($pdo);
    if ($packageId <= 0) return null;
    $st = $pdo->prepare('SELECT * FROM af_diamond_packages WHERE id = ? AND active = 1 LIMIT 1');
    $st->execute([$packageId]);
    $row = $st->fetch();
    return $row ?: null;
}

function afDiamondShopListUserOrders(PDO $pdo, int $userId, int $limit = 20): array
{
    afDiamondsAssertInstalled($pdo);
    afDiamondsValidUserId($userId);
    $limit = max(1, min(100, $limit));
    $st = $pdo->prepare("SELECT * FROM af_diamond_orders WHERE user_id = ? ORDER BY id DESC LIMIT {$limit}");
    $st->execute([$userId]);
    return $st->fetchAll() ?: [];
}

function afDiamondShopFindUserOrderByUuid(PDO $pdo, int $userId, string $uuid): ?array
{
    afDiamondsAssertInstalled($pdo);
    afDiamondsValidUserId($userId);
    $uuid = trim($uuid);
    if (!preg_match('/^[a-f0-9\-]{32,36}$/i', $uuid)) return null;
    $st = $pdo->prepare('SELECT * FROM af_diamond_orders WHERE user_id = ? AND public_uuid = ? LIMIT 1');
    $st->execute([$userId, $uuid]);
    $row = $st->fetch();
    return $row ?: null;
}

function afDiamondShopCanUserBuy(PDO $pdo, int $userId): array
{
    if ($userId <= 0) {
        return ['allowed' => false, 'code' => 'login_required', 'message' => 'Entre na conta para comprar Diamantes.'];
    }

    $requireAdultVerified = (bool)afDiamondShopConfig($pdo, 'diamond_purchase_require_adult_verified', true);

    if (function_exists('afResumoIdade')) {
        $age = afResumoIdade($pdo, $userId);
        if (empty($age['completo'])) {
            return [
                'allowed' => false,
                'code' => 'age_required',
                'message' => 'Confirme sua data de nascimento antes de comprar Diamantes.',
                'redirect' => SITE_URL . '/pages/verificar-idade.php',
                'age' => $age,
            ];
        }

        $tipo = (string)($age['tipo_conta'] ?? '');
        $status = (string)($age['status'] ?? '');

        if ($tipo === 'minor' || str_contains($status, 'minor')) {
            return [
                'allowed' => false,
                'code' => 'minor_purchase_blocked',
                'message' => 'Compras de Diamantes estão bloqueadas para contas protegidas de menores.',
                'redirect' => SITE_URL . '/pages/seguranca-menor.php',
                'age' => $age,
            ];
        }

        if ($requireAdultVerified && !in_array($status, ['adult_verified', 'guardian_verified'], true)) {
            return [
                'allowed' => false,
                'code' => 'adult_verification_required',
                'message' => 'Confirme sua maioridade antes de comprar Diamantes.',
                'redirect' => SITE_URL . '/pages/verificar-maioridade.php',
                'age' => $age,
            ];
        }
    }

    try {
        $st = $pdo->prepare("SELECT status, seguranca_status, suspenso_ate FROM af_usuarios WHERE id = ? LIMIT 1");
        $st->execute([$userId]);
        $u = $st->fetch();
        if (!$u || (int)($u['status'] ?? 0) !== 1) {
            return ['allowed' => false, 'code' => 'inactive_account', 'message' => 'Sua conta não está ativa para comprar Diamantes.'];
        }
        if ((string)($u['seguranca_status'] ?? '') === 'banido') {
            return ['allowed' => false, 'code' => 'banned_account', 'message' => 'Esta conta não pode comprar Diamantes.'];
        }
        if (!empty($u['suspenso_ate']) && strtotime((string)$u['suspenso_ate']) > time()) {
            return ['allowed' => false, 'code' => 'suspended_account', 'message' => 'Esta conta está suspensa temporariamente.'];
        }
    } catch (Throwable $e) {
        // Se a tabela de usuários for diferente em alguma instalação, não bloqueia por compatibilidade.
    }

    return ['allowed' => true, 'code' => 'ok', 'message' => 'Compra permitida.'];
}

function afDiamondShopStatusLabel(string $status): array
{
    return match ($status) {
        'approved' => ['Aprovado', 'success', '✓'],
        'pending' => ['Pendente', 'warning', '⏳'],
        'rejected' => ['Recusado', 'danger', '✕'],
        'cancelled' => ['Cancelado', 'muted', '•'],
        'refunded' => ['Reembolsado', 'info', '↩'],
        'expired' => ['Expirado', 'muted', '⌛'],
        'failed' => ['Falhou', 'danger', '!'],
        default => [ucfirst($status ?: 'desconhecido'), 'muted', '•'],
    };
}

function afDiamondShopCreatePendingOrder(PDO $pdo, int $userId, int $packageId): array
{
    afDiamondsAssertInstalled($pdo);
    afDiamondsValidUserId($userId);

    $permission = afDiamondShopCanUserBuy($pdo, $userId);
    if (empty($permission['allowed'])) {
        throw new RuntimeException((string)($permission['message'] ?? 'Compra de Diamantes bloqueada para esta conta.'));
    }

    $package = afDiamondShopGetActivePackage($pdo, $packageId);
    if (!$package) {
        throw new RuntimeException('Pacote de Diamantes indisponível ou inativo.');
    }

    $diamonds = (int)$package['diamonds'];
    $bonus = (int)($package['bonus_diamonds'] ?? 0);
    $totalDiamonds = $diamonds + $bonus;
    $amount = (float)$package['price'];
    if ($totalDiamonds <= 0 || $amount <= 0) {
        throw new RuntimeException('Pacote de Diamantes inválido.');
    }

    $tx = afDiamondsTxBegin($pdo);
    try {
        afDiamondsEnsureWallet($pdo, $userId, true);

        $uuid = afDiamondsUuid();
        $externalReference = 'AFD-' . strtoupper(str_replace('-', '', $uuid));
        $idempotencyKey = hash('sha256', $externalReference . '|' . $userId . '|' . $packageId);

        $st = $pdo->prepare('INSERT INTO af_diamond_orders
            (public_uuid, user_id, package_id, package_code, package_name, diamonds, bonus_diamonds, total_diamonds, amount, currency, status, external_reference, idempotency_key, expires_at, created_at, updated_at)
            VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,DATE_ADD(NOW(), INTERVAL 1 DAY),NOW(),NOW())');
        $st->execute([
            $uuid,
            $userId,
            (int)$package['id'],
            (string)$package['code'],
            (string)$package['name'],
            $diamonds,
            $bonus,
            $totalDiamonds,
            number_format($amount, 2, '.', ''),
            (string)($package['currency'] ?? 'BRL'),
            'pending',
            $externalReference,
            $idempotencyKey,
        ]);

        $orderId = (int)$pdo->lastInsertId();
        $order = afDiamondShopFindUserOrderByUuid($pdo, $userId, $uuid);
        if (!$order) {
            throw new RuntimeException('Pedido criado, mas não foi possível recuperar o registro.');
        }

        afDiamondsAudit($pdo, 'diamond_order_created_pending', 'diamond_order', $orderId, [], $order, [
            'subject_user_id' => $userId,
            'source' => 'diamonds_part04_shop',
            'package_id' => (int)$package['id'],
        ]);

        afDiamondsTxCommit($pdo, $tx);
        return $order;
    } catch (Throwable $e) {
        afDiamondsTxRollback($pdo, $tx);
        throw $e;
    }
}
