<?php
declare(strict_types=1);

function revenda_credit_ensure_schema(PDO $db): void
{
    $db->exec("CREATE TABLE IF NOT EXISTS revenda_credito_opcoes (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        quantidade_creditos INTEGER NOT NULL DEFAULT 0,
        valor REAL NOT NULL DEFAULT 0,
        gateway_nome TEXT DEFAULT '',
        status TEXT NOT NULL DEFAULT 'ativo',
        created_at TEXT DEFAULT CURRENT_TIMESTAMP,
        updated_at TEXT DEFAULT CURRENT_TIMESTAMP
    )");

    $db->exec("CREATE TABLE IF NOT EXISTS revenda_credito_pedidos (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        payment_id TEXT UNIQUE,
        external_reference TEXT,
        revendedor_id INTEGER NOT NULL,
        opcao_id INTEGER,
        creditos INTEGER NOT NULL DEFAULT 0,
        valor REAL NOT NULL DEFAULT 0,
        gateway_nome TEXT DEFAULT '',
        status TEXT NOT NULL DEFAULT 'pendente',
        credited_at TEXT DEFAULT NULL,
        payload_json TEXT DEFAULT '',
        created_at TEXT DEFAULT CURRENT_TIMESTAMP,
        updated_at TEXT DEFAULT CURRENT_TIMESTAMP
    )");

    try {
        $cols = [];
        foreach ($db->query("PRAGMA table_info(revenda_credito_opcoes)") as $col) {
            $cols[] = strtolower((string)($col['name'] ?? ''));
        }
        if (!in_array('gateway_nome', $cols, true)) {
            $db->exec("ALTER TABLE revenda_credito_opcoes ADD COLUMN gateway_nome TEXT DEFAULT ''");
        }
        if (!in_array('updated_at', $cols, true)) {
            $db->exec("ALTER TABLE revenda_credito_opcoes ADD COLUMN updated_at TEXT DEFAULT CURRENT_TIMESTAMP");
        }
    } catch (Throwable $e) {}
}

function revenda_credit_gateway_label(string $gateway): string
{
    $map = [
        'pushinpay' => 'Pushin Pay',
        'mercadopago' => 'Mercado Pago',
        'pixmanual' => 'PIX Manual',
        'paypal' => 'PayPal',
        '' => 'Padrão do sistema',
    ];
    $gateway = strtolower(trim($gateway));
    return $map[$gateway] ?? ucfirst($gateway);
}

function revenda_credit_gateway_options(PDO $db): array
{
    $cfg = $db->query("SELECT * FROM pushin_config WHERE id = 1 LIMIT 1")->fetch(PDO::FETCH_ASSOC) ?: [];
    $options = [];
    if (trim((string)($cfg['pushin_token'] ?? '')) !== '') {
        $options['pushinpay'] = 'Pushin Pay';
    }
    if (trim((string)($cfg['mercado_pago_token'] ?? '')) !== '') {
        $options['mercadopago'] = 'Mercado Pago';
    }
    if (trim((string)($cfg['pix_manual_chave'] ?? '')) !== '') {
        $options['pixmanual'] = 'PIX Manual';
    }
    if (trim((string)($cfg['paypal_client_id'] ?? '')) !== '' && trim((string)($cfg['paypal_client_secret'] ?? '')) !== '') {
        $options['paypal'] = 'PayPal';
    }
    return $options;
}

function revenda_credit_list_options(PDO $db, bool $onlyActive = false): array
{
    revenda_credit_ensure_schema($db);
    $sql = 'SELECT * FROM revenda_credito_opcoes';
    if ($onlyActive) {
        $sql .= " WHERE status = 'ativo'";
    }
    $sql .= ' ORDER BY quantidade_creditos ASC, valor ASC, id DESC';
    return $db->query($sql)->fetchAll(PDO::FETCH_ASSOC) ?: [];
}

function revenda_credit_get_option(PDO $db, int $id): ?array
{
    revenda_credit_ensure_schema($db);
    $st = $db->prepare('SELECT * FROM revenda_credito_opcoes WHERE id = ? LIMIT 1');
    $st->execute([$id]);
    $row = $st->fetch(PDO::FETCH_ASSOC);
    return $row ?: null;
}

function revenda_credit_upsert_order(PDO $db, array $data): void
{
    revenda_credit_ensure_schema($db);
    $paymentId = trim((string)($data['payment_id'] ?? ''));
    $externalReference = trim((string)($data['external_reference'] ?? ''));
    $existing = null;

    if ($paymentId !== '') {
        $st = $db->prepare('SELECT id FROM revenda_credito_pedidos WHERE payment_id = ? LIMIT 1');
        $st->execute([$paymentId]);
        $existing = $st->fetchColumn();
    }
    if (!$existing and $externalReference !== '') {
        $st = $db->prepare('SELECT id FROM revenda_credito_pedidos WHERE external_reference = ? LIMIT 1');
        $st->execute([$externalReference]);
        $existing = $st->fetchColumn();
    }

    $payload = json_encode($data, JSON_UNESCAPED_UNICODE);
    if ($existing) {
        $st = $db->prepare('UPDATE revenda_credito_pedidos SET payment_id = COALESCE(NULLIF(?,\'\'), payment_id), external_reference = COALESCE(NULLIF(?,\'\'), external_reference), revendedor_id = ?, opcao_id = ?, creditos = ?, valor = ?, gateway_nome = ?, status = ?, payload_json = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?');
        $st->execute([
            $paymentId,
            $externalReference,
            (int)($data['revendedor_id'] ?? 0),
            isset($data['opcao_id']) ? (int)$data['opcao_id'] : null,
            (int)($data['creditos'] ?? 0),
            (float)($data['valor'] ?? 0),
            (string)($data['gateway_nome'] ?? ''),
            (string)($data['status'] ?? 'pendente'),
            $payload,
            (int)$existing,
        ]);
    } else {
        $st = $db->prepare('INSERT INTO revenda_credito_pedidos (payment_id, external_reference, revendedor_id, opcao_id, creditos, valor, gateway_nome, status, payload_json, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)');
        $st->execute([
            $paymentId !== '' ? $paymentId : null,
            $externalReference !== '' ? $externalReference : null,
            (int)($data['revendedor_id'] ?? 0),
            isset($data['opcao_id']) ? (int)$data['opcao_id'] : null,
            (int)($data['creditos'] ?? 0),
            (float)($data['valor'] ?? 0),
            (string)($data['gateway_nome'] ?? ''),
            (string)($data['status'] ?? 'pendente'),
            $payload,
        ]);
    }
}

function revenda_credit_apply_payment(PDO $db, array $pagamento): array
{
    revenda_credit_ensure_schema($db);
    $ctx = $pagamento['payment_context'] ?? [];
    if (!is_array($ctx) || (($ctx['type'] ?? '') !== 'revenda_credito')) {
        return ['success' => false, 'error' => 'Pagamento não é de crédito de revenda'];
    }

    $revendedorId = (int)($ctx['revendedor_id'] ?? 0);
    $creditos = (int)($ctx['creditos'] ?? 0);
    $opcaoId = isset($ctx['opcao_id']) ? (int)$ctx['opcao_id'] : null;
    $paymentId = trim((string)($pagamento['payment_id'] ?? ''));
    $externalReference = trim((string)($pagamento['external_reference'] ?? ''));
    $gateway = trim((string)($pagamento['gateway_nome'] ?? ''));
    $status = strtolower(trim((string)($pagamento['status'] ?? 'pendente')));
    $valor = (float)($pagamento['total'] ?? 0);

    if ($revendedorId <= 0 || $creditos <= 0) {
        return ['success' => false, 'error' => 'Contexto de crédito inválido'];
    }

    $db->beginTransaction();
    try {
        $pedido = null;
        if ($paymentId !== '') {
            $st = $db->prepare('SELECT * FROM revenda_credito_pedidos WHERE payment_id = ? LIMIT 1');
            $st->execute([$paymentId]);
            $pedido = $st->fetch(PDO::FETCH_ASSOC) ?: null;
        }
        if (!$pedido && $externalReference !== '') {
            $st = $db->prepare('SELECT * FROM revenda_credito_pedidos WHERE external_reference = ? LIMIT 1');
            $st->execute([$externalReference]);
            $pedido = $st->fetch(PDO::FETCH_ASSOC) ?: null;
        }
        if (!$pedido) {
            revenda_credit_upsert_order($db, [
                'payment_id' => $paymentId,
                'external_reference' => $externalReference,
                'revendedor_id' => $revendedorId,
                'opcao_id' => $opcaoId,
                'creditos' => $creditos,
                'valor' => $valor,
                'gateway_nome' => $gateway,
                'status' => $status,
                'payload_json' => json_encode($pagamento, JSON_UNESCAPED_UNICODE),
            ]);
            if ($paymentId !== '') {
                $st = $db->prepare('SELECT * FROM revenda_credito_pedidos WHERE payment_id = ? LIMIT 1');
                $st->execute([$paymentId]);
                $pedido = $st->fetch(PDO::FETCH_ASSOC) ?: null;
            }
        }

        if ($pedido && !empty($pedido['credited_at'])) {
            $db->commit();
            return ['success' => true, 'already_processed' => true, 'creditos' => (int)($pedido['creditos'] ?? $creditos)];
        }

        $st = $db->prepare('SELECT id, creditos FROM revendedores WHERE id = ? LIMIT 1');
        $st->execute([$revendedorId]);
        $rev = $st->fetch(PDO::FETCH_ASSOC);
        if (!$rev) {
            throw new RuntimeException('Revenda não encontrada para creditar.');
        }

        $novoSaldo = (int)($rev['creditos'] ?? 0) + $creditos;
        $db->prepare('UPDATE revendedores SET creditos = ? WHERE id = ?')->execute([$novoSaldo, $revendedorId]);
        $db->prepare('UPDATE revenda_credito_pedidos SET status = ?, credited_at = CURRENT_TIMESTAMP, updated_at = CURRENT_TIMESTAMP, payment_id = COALESCE(NULLIF(?,\'\'), payment_id), external_reference = COALESCE(NULLIF(?,\'\'), external_reference), gateway_nome = ?, payload_json = ? WHERE id = ?')->execute([
            'paid',
            $paymentId,
            $externalReference,
            $gateway,
            json_encode($pagamento, JSON_UNESCAPED_UNICODE),
            (int)$pedido['id'],
        ]);
        $db->commit();
        return ['success' => true, 'creditos' => $creditos, 'saldo' => $novoSaldo, 'revendedor_id' => $revendedorId];
    } catch (Throwable $e) {
        if ($db->inTransaction()) {
            $db->rollBack();
        }
        return ['success' => false, 'error' => $e->getMessage()];
    }
}
