<?php
/**
 * Cardix Admin - MySQL Proxy API
 * =========================================================
 * INSTRUÇÕES DE DEPLOY:
 * 1. Copie este arquivo para o seu servidor em 31.97.64.165
 * 2. Coloque em um diretório acessível pelo Apache/Nginx
 *    Ex: /var/www/html/cardix-api/api.php
 * 3. Acesse pelo browser: http://31.97.64.165/cardix-api/api.php?action=tables
 * 4. Atualize a variável API_URL em src/lib/config.ts com a URL correta
 * =========================================================
 */

// ---- Configurações ----
define('API_SECRET', 'cardix-admin-2024');
define('DB_HOST', 'localhost'); // Use 'localhost' se MySQL está no mesmo servidor
define('DB_NAME', 'cardix');
define('DB_USER', 'wander');
define('DB_PASS', 'DIpIYIp25O');
define('DB_PORT', 3306);

// ---- CORS Headers ----
header('Content-Type: application/json; charset=utf-8');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type, X-API-Key');

if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
    http_response_code(204);
    exit;
}

// ---- Autenticação por API Key ----
$apiKey = $_SERVER['HTTP_X_API_KEY'] ?? '';
if ($apiKey !== API_SECRET) {
    http_response_code(401);
    echo json_encode(['error' => 'Não autorizado. Forneça o header X-API-Key.']);
    exit;
}

// ---- Conexão PDO ----
try {
    $pdo = new PDO(
        "mysql:host=" . DB_HOST . ";dbname=" . DB_NAME . ";port=" . DB_PORT . ";charset=utf8mb4",
        DB_USER,
        DB_PASS,
        [
            PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
            PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8mb4"
        ]
    );
} catch (PDOException $e) {
    http_response_code(500);
    echo json_encode(['error' => 'Falha na conexão com o banco de dados: ' . $e->getMessage()]);
    exit;
}

// ---- Helpers ----
function sanitizeIdentifier(string $name): string {
    return preg_replace('/[^a-zA-Z0-9_]/', '', $name);
}

function getPrimaryKey(PDO $pdo, string $table): string {
    $stmt = $pdo->query("SHOW KEYS FROM `{$table}` WHERE Key_name = 'PRIMARY'");
    $row = $stmt->fetch();
    return $row ? $row['Column_name'] : 'id';
}

function jsonResponse(mixed $data, int $status = 200): void {
    http_response_code($status);
    echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
    exit;
}

// ---- Roteamento ----
$method = $_SERVER['REQUEST_METHOD'];
$action = $_GET['action'] ?? null;
$table  = isset($_GET['table']) ? sanitizeIdentifier($_GET['table']) : null;
$id     = $_GET['id'] ?? null;

// ACTION: Listar todas as tabelas
if ($action === 'tables') {
    $stmt = $pdo->query("SHOW TABLES");
    jsonResponse($stmt->fetchAll(PDO::FETCH_COLUMN));
}

// ACTION: Schema de uma tabela (colunas + FKs)
if ($action === 'schema' && $table) {
    $stmt = $pdo->query("DESCRIBE `{$table}`");
    $columns = $stmt->fetchAll();

    $fkStmt = $pdo->prepare("
        SELECT COLUMN_NAME, REFERENCED_TABLE_NAME, REFERENCED_COLUMN_NAME
        FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
        WHERE TABLE_SCHEMA = DATABASE()
          AND TABLE_NAME = ?
          AND REFERENCED_TABLE_NAME IS NOT NULL
    ");
    $fkStmt->execute([$table]);
    $fks = $fkStmt->fetchAll();

    // Para cada FK, detecta a melhor coluna de exibição
    $fkDisplay = [];
    foreach ($fks as $fk) {
        $refTable = $fk['REFERENCED_TABLE_NAME'];
        $descStmt = $pdo->query("DESCRIBE `{$refTable}`");
        $refCols  = $descStmt->fetchAll();

        $displayCol = null;
        foreach ($refCols as $col) {
            if ($col['Field'] !== $fk['REFERENCED_COLUMN_NAME'] &&
                (strpos($col['Type'], 'varchar') !== false || strpos($col['Type'], 'text') !== false)) {
                $displayCol = $col['Field'];
                break;
            }
        }
        $fkDisplay[$fk['COLUMN_NAME']] = [
            'table'      => $refTable,
            'keyCol'     => $fk['REFERENCED_COLUMN_NAME'],
            'displayCol' => $displayCol ?? $fk['REFERENCED_COLUMN_NAME'],
        ];
    }

    jsonResponse(['columns' => $columns, 'foreignKeys' => $fks, 'fkDisplay' => $fkDisplay]);
}

// ACTION: Opções para campo FK (select dropdown)
if ($action === 'fk_options' && $table) {
    $pkCol    = sanitizeIdentifier($_GET['pk'] ?? 'id');
    $labelCol = sanitizeIdentifier($_GET['label'] ?? $pkCol);

    $stmt = $pdo->query(
        "SELECT `{$pkCol}` AS `value`, `{$labelCol}` AS `label` FROM `{$table}` ORDER BY `{$labelCol}` LIMIT 500"
    );
    jsonResponse($stmt->fetchAll());
}

// ---- CRUD ----
if (!$table) {
    jsonResponse(['error' => 'Parâmetro "table" obrigatório'], 400);
}

$pk = getPrimaryKey($pdo, $table);

switch ($method) {

    // READ (listagem paginada ou registro único)
    case 'GET':
        if ($id !== null) {
            $stmt = $pdo->prepare("SELECT * FROM `{$table}` WHERE `{$pk}` = ?");
            $stmt->execute([$id]);
            $row = $stmt->fetch();
            jsonResponse($row !== false ? $row : null);
        }

        $page   = max(1, intval($_GET['page'] ?? 1));
        $limit  = min(100, max(5, intval($_GET['limit'] ?? 10)));
        $offset = ($page - 1) * $limit;
        $search = trim($_GET['search'] ?? '');

        // Busca simples em todas as colunas varchar
        $whereClause = '';
        $searchParams = [];
        if ($search !== '') {
            $descStmt = $pdo->query("DESCRIBE `{$table}`");
            $cols = $descStmt->fetchAll(PDO::FETCH_COLUMN, 0);
            $conditions = [];
            foreach ($cols as $col) {
                $conditions[] = "`{$col}` LIKE ?";
                $searchParams[] = "%{$search}%";
            }
            $whereClause = 'WHERE ' . implode(' OR ', $conditions);
        }

        $countStmt = $pdo->query("SELECT COUNT(*) FROM `{$table}` {$whereClause}");
        if ($searchParams) {
            $countStmt = $pdo->prepare("SELECT COUNT(*) FROM `{$table}` {$whereClause}");
            $countStmt->execute($searchParams);
        }
        $total = (int) $countStmt->fetchColumn();

        $dataStmt = $pdo->prepare("SELECT * FROM `{$table}` {$whereClause} LIMIT ? OFFSET ?");
        $params = array_merge($searchParams, [$limit, $offset]);
        $dataStmt->execute($params);
        $data = $dataStmt->fetchAll();

        jsonResponse([
            'data'       => $data,
            'total'      => $total,
            'page'       => $page,
            'limit'      => $limit,
            'totalPages' => (int) ceil($total / $limit),
        ]);
        break;

    // CREATE
    case 'POST':
        $body = json_decode(file_get_contents('php://input'), true);
        if (!$body || !is_array($body)) {
            jsonResponse(['error' => 'Body JSON inválido'], 400);
        }

        $cols         = array_keys($body);
        $placeholders = implode(', ', array_fill(0, count($cols), '?'));
        $colNames     = '`' . implode('`, `', $cols) . '`';

        $stmt = $pdo->prepare("INSERT INTO `{$table}` ({$colNames}) VALUES ({$placeholders})");
        $stmt->execute(array_values($body));
        jsonResponse(['id' => $pdo->lastInsertId(), 'message' => 'Registro criado com sucesso!']);
        break;

    // UPDATE
    case 'PUT':
        if ($id === null) jsonResponse(['error' => 'ID obrigatório para atualização'], 400);

        $body = json_decode(file_get_contents('php://input'), true);
        if (!$body || !is_array($body)) {
            jsonResponse(['error' => 'Body JSON inválido'], 400);
        }

        $sets = implode(', ', array_map(fn($col) => "`{$col}` = ?", array_keys($body)));
        $stmt = $pdo->prepare("UPDATE `{$table}` SET {$sets} WHERE `{$pk}` = ?");
        $stmt->execute([...array_values($body), $id]);
        jsonResponse(['message' => 'Registro atualizado com sucesso!']);
        break;

    // DELETE
    case 'DELETE':
        if ($id === null) jsonResponse(['error' => 'ID obrigatório para exclusão'], 400);
        $stmt = $pdo->prepare("DELETE FROM `{$table}` WHERE `{$pk}` = ?");
        $stmt->execute([$id]);
        jsonResponse(['message' => 'Registro excluído com sucesso!']);
        break;

    default:
        jsonResponse(['error' => 'Método não permitido'], 405);
}
