<?php

declare(strict_types=1);

/**
 * Servidor de exemplo do protocolo v1 (EXT-01/EXT-06).
 *
 * Rode com: php -S localhost:8080 docs/integracoes/exemplos/servidor-exemplo.php
 * Localhost serve para testar o exemplo diretamente. Para publicar no Grix,
 * hospede em HTTPS público. Configure GRIX_EXEMPLO_APLICACAO para o slug
 * cadastrado e GRIX_EXEMPLO_TOKEN_A / GRIX_EXEMPLO_TOKEN_B para duas contas de teste.
 *
 * Demonstra as cinco operações: descrição, teste sem efeito, execução de
 * consulta, cálculo, escrita idempotente, reconciliação e um evento de
 * exemplo. Troque o slug, as ferramentas e os dados pelos do seu sistema.
 */

$slug = getenv('GRIX_EXEMPLO_APLICACAO') ?: 'minhaapp';
$versao = getenv('GRIX_EXEMPLO_VERSAO') ?: '1.0.0';
$tokens = [getenv('GRIX_EXEMPLO_TOKEN_A') ?: 'exemplo-conta-a', getenv('GRIX_EXEMPLO_TOKEN_B') ?: 'exemplo-conta-b'];
$credencial = preg_replace('/^Bearer\s+/i', '', $_SERVER['HTTP_AUTHORIZATION'] ?? '');
$conta = array_search($credencial, $tokens, true);
if ($conta === false) {
    http_response_code(401);
    header('Content-Type: application/json; charset=utf-8');
    echo json_encode(['erro' => 'credencial_invalida']);
    return;
}

function json(array $dados, int $status = 200): void
{
    http_response_code($status);
    header('Content-Type: application/json; charset=utf-8');
    echo json_encode($dados, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
}

function descricao(string $slug, string $versao): array
{
    return [
        'protocolo' => '1.0',
        'contrato' => 1,
        'aplicacao' => $slug,
        'versao' => $versao,
        'ferramentas' => [
            [
                'id' => $slug . '_catalogo_buscar',
                'capacidade' => 'catalogo.listar',
                'descricao' => 'Busca produtos por termo.',
                'efeito' => 'consulta',
                'identidade' => 'visitante',
                'entrada' => ['q' => 'string'],
                'saida' => ['itens' => 'lista'],
                'prazo_ms' => 3000,
                'apresentacoes' => ['opcoes'],
            ],
            [
                'id' => $slug . '_orcamento_simular',
                'capacidade' => 'orcamento.simular',
                'descricao' => 'Calcula a composição sem efeito comercial.',
                'efeito' => 'simulacao',
                'identidade' => 'visitante',
                'entrada' => ['referencia' => 'string', 'quantidade' => 'int?'],
                'saida' => ['total_centavos' => 'int'],
                'prazo_ms' => 5000,
                'apresentacoes' => ['orcamento'],
            ],
            [
                'id' => $slug . '_cotacao_registrar',
                'capacidade' => 'proposta.registrar',
                'descricao' => 'Registra a cotação em rascunho.',
                'efeito' => 'escrita',
                'identidade' => 'cliente_verificado',
                'entrada' => ['simulacao_ref' => 'string', 'titular_ref' => 'string'],
                'saida' => ['cotacao_ref' => 'string'],
                'prazo_ms' => 10000,
                'idempotencia' => 'chave da operação; mesma chave devolve a mesma cotação',
                'apresentacoes' => ['acompanhamento'],
            ],
        ],
        'conhecimento' => ['Atenda pelo nome do produto e confirme a quantidade antes de calcular.'],
        'apresentacoes' => ['opcoes', 'orcamento', 'acompanhamento'],
    ];
}

$caminho = (string) (parse_url((string) ($_SERVER['REQUEST_URI'] ?? '/'), PHP_URL_PATH) ?? '/');
$metodo = (string) ($_SERVER['REQUEST_METHOD'] ?? 'GET');
$corpo = json_decode((string) file_get_contents('php://input'), true) ?: [];

if ($metodo === 'GET' && $caminho === '/integracao/v1/descricao') {
    json(descricao($slug, $versao));
    return;
}

if ($metodo === 'POST' && $caminho === '/integracao/v1/testar') {
    $porCapacidade = [];
    foreach (descricao($slug, $versao)['ferramentas'] as $ferramenta) {
        $porCapacidade[] = ['ferramenta' => $ferramenta['id'], 'capacidade' => $ferramenta['capacidade'], 'ok' => true, 'mensagem' => 'verificada sem efeito comercial'];
    }
    json(['ok' => true, 'por_capacidade' => $porCapacidade]);
    return;
}

if ($metodo === 'POST' && preg_match('#^/integracao/v1/ferramentas/([^/]+)/executar$#', $caminho, $m) === 1) {
    $id = $m[1];
    $entrada = is_array($corpo['entrada'] ?? null) ? $corpo['entrada'] : [];
    $chave = (string) ($corpo['chave'] ?? '');
    if ($id === $slug . '_catalogo_buscar') {
        json(['estado' => 'concluida', 'resultado' => ['itens' => [
            ['referencia' => 'item-1', 'nome' => 'Produto exemplo'],
        ]]]);
        return;
    }
    if ($id === $slug . '_orcamento_simular') {
        $quantidade = max(1, (int) ($entrada['quantidade'] ?? 1));
        json(['estado' => 'concluida', 'resultado' => [
            'simulacao_ref' => 'sim-' . substr(hash('sha256', json_encode($entrada)), 0, 8),
            'composicao' => [['item' => 'Produto exemplo', 'quantidade' => $quantidade, 'valor_centavos' => 10000 * $quantidade]],
            'total_centavos' => 10000 * $quantidade,
            'versao_regras' => $versao,
        ]]);
        return;
    }
    if ($id === $slug . '_cotacao_registrar') {
        if (($corpo['principal'] ?? 'visitante') === 'visitante') {
            json(['estado' => 'falhou', 'erro' => 'permissao_negada', 'mensagem' => 'Cotação exige cliente verificado.']);
            return;
        }
        $ref = 'cot-' . substr(hash('sha256', $conta . ':' . $chave), 0, 12);
        $arquivo = sys_get_temp_dir() . '/grix-exemplo-' . hash('sha256', $slug . ':' . $tokens[$conta]) . '.json';
        $fp = fopen($arquivo, 'c+');
        if (!$fp || !flock($fp, LOCK_EX)) { json(['estado' => 'falhou', 'erro' => 'erro_interno'], 500); return; }
        $cotacoes = json_decode(stream_get_contents($fp), true) ?: [];
        $hash = hash('sha256', json_encode($entrada));
        if (isset($cotacoes[$ref]) && $cotacoes[$ref]['entrada_hash'] !== $hash) {
            flock($fp, LOCK_UN); fclose($fp);
            json(['estado' => 'falhou', 'erro' => 'conflito', 'mensagem' => 'A chave já foi usada com outros dados.']); return;
        }
        $cotacoes[$ref] = ['entrada_hash' => $hash, 'resultado' => ['cotacao_ref' => $ref]];
        rewind($fp); ftruncate($fp, 0); fwrite($fp, json_encode($cotacoes)); fflush($fp);
        flock($fp, LOCK_UN); fclose($fp);
        json(['estado' => 'concluida', 'resultado' => ['cotacao_ref' => $ref], 'referencia_externa' => $ref]);
        return;
    }
    json(['estado' => 'falhou', 'erro' => 'nao_encontrado', 'mensagem' => 'Ferramenta desconhecida.'], 404);
    return;
}

if ($metodo === 'GET' && $caminho === '/integracao/v1/operacoes') {
    $ref = (string) ($_GET['ref'] ?? '');
    $arquivo = sys_get_temp_dir() . '/grix-exemplo-' . hash('sha256', $slug . ':' . $tokens[$conta]) . '.json';
    $fp = is_file($arquivo) ? fopen($arquivo, 'r') : false;
    $cotacoes = [];
    if ($fp) { flock($fp, LOCK_SH); $cotacoes = json_decode(stream_get_contents($fp), true) ?: []; flock($fp, LOCK_UN); fclose($fp); }
    json(isset($cotacoes[$ref]) ? ['estado' => 'concluida', 'resultado' => $cotacoes[$ref]['resultado']] : ['estado' => 'falhou', 'erro' => 'nao_encontrado', 'mensagem' => 'Operação não localizada.']);
    return;
}

json(['estado' => 'falhou', 'erro' => 'nao_encontrado', 'mensagem' => 'Rota desconhecida.'], 404);
