<?php
// /votacao/api/index.php
declare(strict_types=1);

/**
 * API Pública - Atividades Legislativas
 * -------------------------------------------------------------------------
 * Exemplos (GET):
 *   /votacao/api/vereadores
 *   /votacao/api/vereadores/12
 *   /votacao/api/vereadores/12/materias?ano=2025
 *   /votacao/api/comissoes
 *   /votacao/api/comissoes/3
 *   /votacao/api/legislaturas
 *   /votacao/api/legislaturas/2
 *   /votacao/api/legislaturas/2/mesa
 *   /votacao/api/legislaturas/2/vereadores
 *   /votacao/api/legislacao?q=educa&ano=2024&tipo_id=1
 *   /votacao/api/legislacao/100
 *   /votacao/api/sessoes?status=ativa&data_from=2025-01-01&data_to=2025-12-31
 *   /votacao/api/sessoes/10
 *   /votacao/api/sessoes/10/materias
 *   /votacao/api/sessoes/10/quorum
 *   /votacao/api/atas
 *   /votacao/api/atas/5
 * -------------------------------------------------------------------------
 * Padrões:
 *  - JSON UTF-8; CORS liberado (GET/OPTIONS).
 *  - Paginação: page (>=1), per_page (1..100, padrão=20).
 *  - Filtros por querystring conforme endpoint.
 *  - Campos/expansões: alguns endpoints aceitam "expand" (ex.: materias_count).
 */

if (!defined('BASE')) define('BASE', '/votacao');

require_once __DIR__ . '/../src/db.php';
require_once __DIR__ . '/../src/helpers.php'; // se tiver função h() ou utilidades

/* ------------------------ Infra básica: headers/CORS --------------------- */
header('Content-Type: application/json; charset=utf-8');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type, Accept, Origin');

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

/* ----------------------------- Utilitários ------------------------------- */
function json_out($data, int $status = 200, ?int $maxAge = null): void {
  http_response_code($status);
  $json = json_encode($data, JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES);
  // ETag simples p/ cache condicional
  $etag = '"' . substr(sha1($json), 0, 16) . '"';
  header('ETag: ' . $etag);
  if ($maxAge !== null) header('Cache-Control: public, max-age=' . $maxAge);
  if (isset($_SERVER['HTTP_IF_NONE_MATCH']) && trim($_SERVER['HTTP_IF_NONE_MATCH']) === $etag) {
    http_response_code(304); exit;
  }
  // pretty opcional
  if (($_GET['pretty'] ?? '') === '1') {
    $json = json_encode($data, JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES|JSON_PRETTY_PRINT);
  }
  echo $json;
  exit;
}
function not_found($msg='Não encontrado.'){ json_out(['ok'=>false,'error'=>$msg],404); }
function bad_request($msg='Parâmetros inválidos.'){ json_out(['ok'=>false,'error'=>$msg],400); }
function server_error($msg='Erro interno.'){ json_out(['ok'=>false,'error'=>$msg],500); }

function num($v, $def=0){ $n = (int)$v; return $n ?: $def; }
function str($v){ return trim((string)($v ?? '')); }
function page_params(): array {
  $page = max(1, (int)($_GET['page'] ?? 1));
  $per  = (int)($_GET['per_page'] ?? 20);
  if ($per < 1) $per = 20; if ($per > 100) $per = 100;
  return [$page, $per, ($page-1)*$per];
}
function table_exists(PDO $pdo, string $table): bool {
  static $cache = [];
  if (isset($cache[$table])) return $cache[$table];
  $stmt = $pdo->prepare("SELECT 1 FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = :t");
  $stmt->execute([':t'=>$table]);
  return $cache[$table] = (bool)$stmt->fetchColumn();
}
function column_exists(PDO $pdo, string $table, string $column): bool {
  $stmt = $pdo->prepare("SELECT 1 FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = :t AND column_name = :c");
  $stmt->execute([':t'=>$table, ':c'=>$column]);
  return (bool)$stmt->fetchColumn();
}
function map_user_public(array $u): array {
  return [
    'id'      => (int)$u['id'],
    'nome'    => $u['nome'],
    'partido' => $u['partido'] ?? null,
    'foto'    => $u['foto'] ? (BASE . '/' . ltrim($u['foto'], '/')) : null,
  ];
}

/* ------------------------------ Router ----------------------------------- */
$reqPath = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH) ?: '/';
$prefix  = rtrim(BASE, '/') . '/api';
$path    = preg_replace('#^'.preg_quote($prefix,'#').'#','',$reqPath);
$parts   = array_values(array_filter(explode('/', $path), fn($x)=>$x!==''));
// $parts[0] => recurso; $parts[1] => id; $parts[2] => sub-recurso...

try {

  /* ------------------------------ VEREADORES ----------------------------- */
  if (($parts[0] ?? '') === 'vereadores') {
    if (!isset($parts[1])) {
      // GET /vereadores
      [$page,$per,$off] = page_params();
      $q   = str($_GET['q'] ?? '');
      $leg = num($_GET['legislatura_id'] ?? 0);
      $ativo = (int)($_GET['ativo'] ?? 1);

      $conds = ["u.tipo_usuario='vereador'"];
      $p = [];
      if ($ativo >= 0) { $conds[] = "u.ativo=:atv"; $p[':atv'] = $ativo; }
      if ($q !== '') { $conds[] = "(u.nome LIKE :q OR COALESCE(u.partido,'') LIKE :q)"; $p[':q'] = "%$q%"; }

      $sql = "SELECT u.id,u.nome,u.partido,u.foto
              FROM usuarios u ";
      if ($leg>0 && table_exists($pdo,'legislatura_vereadores')) {
        $sql .= " JOIN legislatura_vereadores lv ON lv.vereador_id=u.id AND lv.legislatura_id=:leg ";
        $p[':leg'] = $leg;
      }
      $sql .= " WHERE ".implode(' AND ',$conds)." ORDER BY u.nome LIMIT :lim OFFSET :off";
      $st = $pdo->prepare($sql);
      foreach($p as $k=>$v) $st->bindValue($k,$v,is_int($v)?PDO::PARAM_INT:PDO::PARAM_STR);
      $st->bindValue(':lim',$per,PDO::PARAM_INT);
      $st->bindValue(':off',$off,PDO::PARAM_INT);
      $st->execute();
      $rows = array_map('map_user_public', $st->fetchAll());

      // expand= materias_count
      $expand = str($_GET['expand'] ?? '');
      if ($expand && strpos($expand,'materias_count')!==false) {
        $ids = array_column($rows,'id');
        if ($ids){
          $in = implode(',', array_fill(0,count($ids),'?'));
          $stm = $pdo->prepare("SELECT autor_id, COUNT(*) c FROM materias WHERE autor_id IN ($in) GROUP BY autor_id");
          $stm->execute($ids);
          $counts = []; foreach($stm as $r){ $counts[(int)$r['autor_id']] = (int)$r['c']; }
          foreach($rows as &$r){ $r['materias_count'] = $counts[$r['id']] ?? 0; }
        }
      }

      json_out(['ok'=>true,'page'=>$page,'per_page'=>$per,'items'=>$rows], 200, 30);
    }

    // /vereadores/{id}
    $vereador_id = (int)$parts[1];
    if (!$vereador_id) not_found();

    if (!isset($parts[2])) {
      $st = $pdo->prepare("SELECT id,nome,partido,foto,ativo FROM usuarios WHERE id=:id AND tipo_usuario='vereador' LIMIT 1");
      $st->execute([':id'=>$vereador_id]);
      $u = $st->fetch();
      if (!$u) not_found('Vereador não encontrado.');

      $resp = map_user_public($u);
      $resp['ativo'] = (int)$u['ativo'];

      // Comissões (se existir comissoes_membros)
      if (table_exists($pdo,'comissoes_membros')) {
        $q = $pdo->prepare("SELECT c.id,c.nome,c.tipo,cm.cargo
                            FROM comissoes_membros cm
                            JOIN comissoes c ON c.id=cm.comissao_id
                            WHERE cm.vereador_id=:v
                            ORDER BY c.nome");
        $q->execute([':v'=>$vereador_id]);
        $resp['comissoes'] = $q->fetchAll();
      }

      // Legislaturas do vereador (se existir legislatura_vereadores)
      if (table_exists($pdo,'legislatura_vereadores')) {
        $q = $pdo->prepare("SELECT l.id,l.numero,l.periodo,l.data_inicio,l.data_fim
                            FROM legislatura_vereadores lv
                            JOIN legislaturas l ON l.id=lv.legislatura_id
                            WHERE lv.vereador_id=:v
                            ORDER BY l.data_inicio DESC");
        $q->execute([':v'=>$vereador_id]);
        $resp['legislaturas'] = $q->fetchAll();
      }

      json_out(['ok'=>true,'item'=>$resp], 200, 60);
    }

    // /vereadores/{id}/materias
    if (($parts[2] ?? '') === 'materias') {
      [$page,$per,$off] = page_params();
      $ano  = num($_GET['ano'] ?? 0);
      $tipo = str($_GET['tipo'] ?? '');
      $sess = num($_GET['sessao_id'] ?? 0);
      $pub  = ($_GET['publico'] ?? '')==='1';

      $p = [':v'=>$vereador_id];
      $conds = ["m.autor_id=:v"];
      if ($ano>0){ $conds[]="m.ano=:a"; $p[':a']=$ano; }
      if ($tipo!==''){ $conds[]="m.tipo=:t"; $p[':t']=$tipo; }

      $sql = "SELECT m.id,m.numero,m.ano,m.tipo,m.titulo,m.descricao,
                     sm.status, sm.resultado, s.id AS sessao_id, s.data_sessao
              FROM materias m
              LEFT JOIN sessao_materias sm ON sm.materia_id=m.id
              LEFT JOIN sessoes s ON s.id=sm.sessao_id";
      if ($sess>0){ $conds[] = "s.id=:sid"; $p[':sid']=$sess; }
      if ($pub){ $conds[] = "(sm.publicar_site=1 OR sm.publicar_site IS NULL)"; }
      $sql .= " WHERE ".implode(' AND ',$conds)." ORDER BY s.data_sessao DESC, m.id DESC LIMIT :lim OFFSET :off";

      $st = $pdo->prepare($sql);
      foreach($p as $k=>$v){ $st->bindValue($k,$v,is_int($v)?PDO::PARAM_INT:PDO::PARAM_STR); }
      $st->bindValue(':lim',$per,PDO::PARAM_INT);
      $st->bindValue(':off',$off,PDO::PARAM_INT);
      $st->execute();
      json_out(['ok'=>true,'page'=>$page,'per_page'=>$per,'items'=>$st->fetchAll()], 200, 30);
    }

    not_found();
  }

  /* ------------------------------ COMISSÕES ------------------------------ */
  if (($parts[0] ?? '') === 'comissoes') {
    if (!isset($parts[1])) {
      [$page,$per,$off] = page_params();
      $sql = "SELECT id,nome,tipo,ativo FROM comissoes ORDER BY nome LIMIT :lim OFFSET :off";
      $st  = $pdo->prepare($sql);
      $st->bindValue(':lim',$per,PDO::PARAM_INT);
      $st->bindValue(':off',$off,PDO::PARAM_INT);
      $st->execute();
      json_out(['ok'=>true,'page'=>$page,'per_page'=>$per,'items'=>$st->fetchAll()], 200, 60);
    }

    $cid = (int)$parts[1];
    if (!$cid) not_found();

    if (!isset($parts[2])) {
      $st = $pdo->prepare("SELECT id,nome,tipo,ativo,finalidade FROM comissoes WHERE id=:id LIMIT 1");
      $st->execute([':id'=>$cid]);
      $c = $st->fetch();
      if (!$c) not_found('Comissão não encontrada.');

      $c['membros'] = [];
      if (table_exists($pdo,'comissoes_membros')) {
        $q = $pdo->prepare("SELECT u.id,u.nome,u.partido,u.foto, cm.cargo
                            FROM comissoes_membros cm
                            JOIN usuarios u ON u.id=cm.vereador_id
                            WHERE cm.comissao_id=:id
                            ORDER BY cm.cargo DESC, u.nome");
        $q->execute([':id'=>$cid]);
        $mem = [];
        foreach($q as $r){
          $mem[] = [
            'cargo' => $r['cargo'],
            'vereador' => map_user_public($r)
          ];
        }
        $c['membros'] = $mem;
      }
      json_out(['ok'=>true,'item'=>$c], 200, 120);
    }

    not_found();
  }

  /* ----------------------------- LEGISLATURAS ---------------------------- */
  if (($parts[0] ?? '') === 'legislaturas') {
    if (!isset($parts[1])) {
      [$page,$per,$off] = page_params();
      $st = $pdo->prepare("
        SELECT id,numero,periodo,data_inicio,data_fim,ativo
        FROM legislaturas
        ORDER BY data_inicio DESC, id DESC
        LIMIT :lim OFFSET :off
      ");
      $st->bindValue(':lim',$per,PDO::PARAM_INT);
      $st->bindValue(':off',$off,PDO::PARAM_INT);
      $st->execute();
      json_out(['ok'=>true,'page'=>$page,'per_page'=>$per,'items'=>$st->fetchAll()], 200, 120);
    }

    $lid = (int)$parts[1];
    if (!$lid) not_found();

    // /legislaturas/{id}
    if (!isset($parts[2])) {
      $st = $pdo->prepare("SELECT id,numero,periodo,data_inicio,data_fim,ativo FROM legislaturas WHERE id=:id LIMIT 1");
      $st->execute([':id'=>$lid]);
      $L = $st->fetch();
      if (!$L) not_found('Legislatura não encontrada.');

      // composição
      $L['vereadores'] = [];
      if (table_exists($pdo,'legislatura_vereadores')) {
        $q = $pdo->prepare("SELECT u.id,u.nome,u.partido,u.foto
                            FROM legislatura_vereadores lv
                            JOIN usuarios u ON u.id=lv.vereador_id
                            WHERE lv.legislatura_id=:id
                            ORDER BY u.nome");
        $q->execute([':id'=>$lid]);
        $L['vereadores'] = array_map('map_user_public', $q->fetchAll());
      }

      // mesa diretora
      $L['mesa'] = [];
      if (table_exists($pdo,'legislatura_mesa')) {
        $q = $pdo->prepare("SELECT lm.cargo, u.id,u.nome,u.partido,u.foto
                            FROM legislatura_mesa lm
                            JOIN usuarios u ON u.id=lm.vereador_id
                            WHERE lm.legislatura_id=:id
                            ORDER BY FIELD(lm.cargo,'Presidente','Vice-Presidente','1º Secretário','2º Secretário'), u.nome");
        $q->execute([':id'=>$lid]);
        $mesa=[];
        foreach($q as $r){
          $mesa[] = ['cargo'=>$r['cargo'],'vereador'=>map_user_public($r)];
        }
        $L['mesa'] = $mesa;
      }

      json_out(['ok'=>true,'item'=>$L], 200, 120);
    }

    // /legislaturas/{id}/mesa
    if (($parts[2] ?? '') === 'mesa') {
      if (!table_exists($pdo,'legislatura_mesa')) json_out(['ok'=>true,'items'=>[]],200,60);
      $q = $pdo->prepare("SELECT lm.cargo, u.id,u.nome,u.partido,u.foto
                          FROM legislatura_mesa lm
                          JOIN usuarios u ON u.id=lm.vereador_id
                          WHERE lm.legislatura_id=:id
                          ORDER BY FIELD(lm.cargo,'Presidente','Vice-Presidente','1º Secretário','2º Secretário'), u.nome");
      $q->execute([':id'=>$lid]);
      $items=[]; foreach($q as $r){ $items[]=['cargo'=>$r['cargo'],'vereador'=>map_user_public($r)]; }
      json_out(['ok'=>true,'items'=>$items], 200, 120);
    }

    // /legislaturas/{id}/vereadores
    if (($parts[2] ?? '') === 'vereadores') {
      if (!table_exists($pdo,'legislatura_vereadores')) json_out(['ok'=>true,'items'=>[]],200,60);
      $q = $pdo->prepare("SELECT u.id,u.nome,u.partido,u.foto
                          FROM legislatura_vereadores lv
                          JOIN usuarios u ON u.id=lv.vereador_id
                          WHERE lv.legislatura_id=:id
                          ORDER BY u.nome");
      $q->execute([':id'=>$lid]);
      json_out(['ok'=>true,'items'=>array_map('map_user_public',$q->fetchAll())], 200, 120);
    }

    not_found();
  }

  /* ------------------------------ LEGISLAÇÃO ----------------------------- */
  if (($parts[0] ?? '') === 'legislacao') {
    if (!isset($parts[1])) {
      [$page,$per,$off] = page_params();
      $q       = str($_GET['q'] ?? '');
      $tipo_id = num($_GET['tipo_id'] ?? 0);
      $tema_id = num($_GET['tema_id'] ?? 0);
      $ano     = num($_GET['ano'] ?? 0);

      $sql = "SELECT l.id, l.data_norma, l.numero, l.ementa, l.pdf_path,
                     t.nome AS tipo_nome, te.nome AS tema_nome
              FROM legislacao l
              JOIN legislacao_tipos t ON t.id=l.tipo_id
              LEFT JOIN legislacao_temas te ON te.id=l.tema_id
              WHERE 1=1";
      $p = [];
      if ($q !== '') {
        $sql .= " AND (l.numero LIKE :q OR l.ementa LIKE :q OR l.palavras_chave LIKE :q)";
        $p[':q'] = "%$q%";
      }
      if ($tipo_id>0){ $sql.=" AND l.tipo_id=:tid"; $p[':tid']=$tipo_id; }
      if ($tema_id>0){ $sql.=" AND l.tema_id=:tm";  $p[':tm']=$tema_id; }
      if ($ano>0){     $sql.=" AND YEAR(l.data_norma)=:yy"; $p[':yy']=$ano; }
      $sql .= " ORDER BY l.data_norma DESC, l.id DESC LIMIT :lim OFFSET :off";

      $st = $pdo->prepare($sql);
      foreach($p as $k=>$v){ $st->bindValue($k,$v,is_int($v)?PDO::PARAM_INT:PDO::PARAM_STR); }
      $st->bindValue(':lim',$per,PDO::PARAM_INT);
      $st->bindValue(':off',$off,PDO::PARAM_INT);
      $st->execute();
      $rows = $st->fetchAll();
      foreach($rows as &$r){
        $r['pdf_url'] = $r['pdf_path'] ? (BASE . '/' . ltrim($r['pdf_path'],'/')) : null;
      }
      json_out(['ok'=>true,'page'=>$page,'per_page'=>$per,'items'=>$rows], 200, 60);
    }

    $lid = (int)$parts[1];
    $st = $pdo->prepare("SELECT l.*, t.nome AS tipo_nome, te.nome AS tema_nome
                         FROM legislacao l
                         JOIN legislacao_tipos t ON t.id=l.tipo_id
                         LEFT JOIN legislacao_temas te ON te.id=l.tema_id
                         WHERE l.id=:id LIMIT 1");
    $st->execute([':id'=>$lid]);
    $row = $st->fetch();
    if (!$row) not_found('Norma não encontrada.');
    $row['pdf_url'] = $row['pdf_path'] ? (BASE . '/' . ltrim($row['pdf_path'],'/')) : null;
    json_out(['ok'=>true,'item'=>$row], 200, 120);
  }

  /* -------------------------------- SESSÕES ------------------------------ */
  if (($parts[0] ?? '') === 'sessoes') {
    if (!isset($parts[1])) {
      [$page,$per,$off] = page_params();
      $status = str($_GET['status'] ?? '');
      $d1     = str($_GET['data_from'] ?? '');
      $d2     = str($_GET['data_to'] ?? '');
      $leg    = num($_GET['legislatura_id'] ?? 0);

      $conds = ["1=1"]; $p=[];
      if ($status!==''){ $conds[]="status=:st"; $p[':st']=$status; }
      if ($d1!==''){ $conds[]="data_sessao>=:d1"; $p[':d1']=$d1; }
      if ($d2!==''){ $conds[]="data_sessao<=:d2"; $p[':d2']=$d2; }
      if ($leg>0){ $conds[]="legislatura_id=:lg"; $p[':lg']=$leg; }

      $sql = "SELECT id,numero,tipo,data_sessao,legislatura_id,status
              FROM sessoes
              WHERE ".implode(' AND ',$conds)."
              ORDER BY data_sessao DESC, id DESC
              LIMIT :lim OFFSET :off";
      $st = $pdo->prepare($sql);
      foreach($p as $k=>$v){ $st->bindValue($k,$v,is_int($v)?PDO::PARAM_INT:PDO::PARAM_STR); }
      $st->bindValue(':lim',$per,PDO::PARAM_INT);
      $st->bindValue(':off',$off,PDO::PARAM_INT);
      $st->execute();
      json_out(['ok'=>true,'page'=>$page,'per_page'=>$per,'items'=>$st->fetchAll()], 200, 30);
    }

    $sid = (int)$parts[1];
    if (!$sid) not_found();

    if (!isset($parts[2])) {
      $st = $pdo->prepare("SELECT * FROM sessoes WHERE id=:id LIMIT 1");
      $st->execute([':id'=>$sid]);
      $s = $st->fetch();
      if (!$s) not_found('Sessão não encontrada.');

      // contagem de matérias
      $q = $pdo->prepare("SELECT COUNT(*) c FROM sessao_materias WHERE sessao_id=:s");
      $q->execute([':s'=>$sid]);
      $s['materias_count'] = (int)$q->fetchColumn();

      json_out(['ok'=>true,'item'=>$s], 200, 60);
    }

    // /sessoes/{id}/materias
    if (($parts[2] ?? '') === 'materias') {
      $st = $pdo->prepare("
        SELECT sm.id AS sm_id, sm.ordem, sm.status, sm.resultado,
               sm.votos_favor, sm.votos_contra, sm.votos_abstencao, sm.publicar_site,
               m.id AS materia_id, m.numero, m.ano, m.tipo, m.titulo, m.descricao,
               u.id AS autor_id, u.nome AS autor_nome, u.partido AS autor_partido
        FROM sessao_materias sm
        JOIN materias m ON m.id=sm.materia_id
        LEFT JOIN usuarios u ON u.id=m.autor_id
        WHERE sm.sessao_id=:s
        ORDER BY sm.ordem ASC, sm.id ASC
      ");
      $st->execute([':s'=>$sid]);
      json_out(['ok'=>true,'items'=>$st->fetchAll()], 200, 30);
    }

    // /sessoes/{id}/quorum
    if (($parts[2] ?? '') === 'quorum') {
      // detecta tabela de presenças (melhor esforço)
      $candidates = ['sessoes_quorum','sessao_quorum','quorum','presencas','presenca_sessao'];
      $table = null; $col = null;
      foreach($candidates as $t){
        if (!table_exists($pdo,$t)) continue;
        // precisa ter colunas sessao_id e vereador_id
        if (column_exists($pdo,$t,'sessao_id') && column_exists($pdo,$t,'vereador_id')) {
          // coluna de presença
          foreach (['presente','presenca','status'] as $cname){
            if (column_exists($pdo,$t,$cname)){ $table=$t; $col=$cname; break 2; }
          }
        }
      }

      // lista base de vereadores (da legislatura da sessão, se existir)
      $qL = $pdo->prepare("SELECT legislatura_id FROM sessoes WHERE id=:s LIMIT 1");
      $qL->execute([':s'=>$sid]);
      $leg = (int)($qL->fetchColumn() ?: 0);

      if ($leg>0 && table_exists($pdo,'legislatura_vereadores')) {
        $qV = $pdo->prepare("SELECT u.id,u.nome,u.partido,u.foto
                             FROM legislatura_vereadores lv
                             JOIN usuarios u ON u.id=lv.vereador_id
                             WHERE lv.legislatura_id=:l
                             ORDER BY u.nome");
        $qV->execute([':l'=>$leg]);
      } else {
        $qV = $pdo->query("SELECT id,nome,partido,foto FROM usuarios WHERE tipo_usuario='vereador' AND ativo=1 ORDER BY nome");
      }
      $vereadores = $qV->fetchAll();
      $map = [];
      foreach($vereadores as $v){ $map[(int)$v['id']] = map_user_public($v) + ['presente'=>null]; }

      // se achou tabela de presenças, preenche
      if ($table && $col) {
        $sqlP = "SELECT vereador_id, $col AS vcol FROM $table WHERE sessao_id=:s";
        $stP = $pdo->prepare($sqlP);
        $stP->execute([':s'=>$sid]);
        foreach($stP as $r){
          $vid = (int)$r['vereador_id'];
          $val = $r['vcol'];
          $presente = null;
          if (is_numeric($val)) $presente = ((int)$val) ? 1 : 0;
          elseif (is_string($val)) $presente = (strtolower($val)==='presente' || strtolower($val)==='1') ? 1 : 0;
          $map[$vid]['presente'] = $presente;
        }
      }

      $items = array_values($map);
      $presentes = array_sum(array_map(fn($x)=> (int)($x['presente']===1), $items));
      json_out(['ok'=>true,'sessao_id'=>$sid,'presentes'=>$presentes,'total'=>count($items),'itens'=>$items,
                'fonte'=>$table?:null], 200, 15);
    }

    not_found();
  }

  /* --------------------------------- ATAS -------------------------------- */
  if (($parts[0] ?? '') === 'atas') {
    // Estratégia:
    // 1) Se existir tabela "atas" -> usa.
    // 2) Senão, tenta expor sessões com coluna "ata_pdf" (arquivo da ata).
    if (!isset($parts[1])) {
      [$page,$per,$off] = page_params();
      if (table_exists($pdo,'atas')) {
        $st = $pdo->prepare("SELECT id, sessao_id, titulo, resumo, pdf_path, created_at
                             FROM atas ORDER BY id DESC LIMIT :lim OFFSET :off");
        $st->bindValue(':lim',$per,PDO::PARAM_INT);
        $st->bindValue(':off',$off,PDO::PARAM_INT);
        $st->execute();
        $rows = $st->fetchAll();
        foreach($rows as &$r){ $r['pdf_url'] = $r['pdf_path'] ? (BASE.'/'.ltrim($r['pdf_path'],'/')) : null; }
        json_out(['ok'=>true,'page'=>$page,'per_page'=>$per,'items'=>$rows], 200, 60);
      } elseif (column_exists($pdo,'sessoes','ata_pdf')) {
        $st = $pdo->prepare("SELECT id AS sessao_id, numero, data_sessao, ata_pdf
                             FROM sessoes WHERE ata_pdf IS NOT NULL AND ata_pdf<>'' 
                             ORDER BY id DESC LIMIT :lim OFFSET :off");
        $st->bindValue(':lim',$per,PDO::PARAM_INT);
        $st->bindValue(':off',$off,PDO::PARAM_INT);
        $st->execute();
        $rows = $st->fetchAll();
        foreach($rows as &$r){ $r['pdf_url'] = $r['ata_pdf'] ? (BASE.'/'.ltrim($r['ata_pdf'],'/')) : null; }
        json_out(['ok'=>true,'page'=>$page,'per_page'=>$per,'items'=>$rows], 200, 60);
      } else {
        json_out(['ok'=>true,'items'=>[],'note'=>'Sem tabela "atas" e sem coluna "sessoes.ata_pdf".'],200,10);
      }
    }

    $aid = (int)$parts[1];
    if (!$aid) not_found();

    if (table_exists($pdo,'atas')) {
      $st = $pdo->prepare("SELECT id, sessao_id, titulo, resumo, pdf_path, created_at FROM atas WHERE id=:id");
      $st->execute([':id'=>$aid]);
      $row = $st->fetch();
      if (!$row) not_found('Ata não encontrada.');
      $row['pdf_url'] = $row['pdf_path'] ? (BASE.'/'.ltrim($row['pdf_path'],'/')) : null;
      json_out(['ok'=>true,'item'=>$row], 200, 120);
    } else {
      // fallback por sessão se usar sessoes.ata_pdf
      $st = $pdo->prepare("SELECT id AS sessao_id, numero, data_sessao, ata_pdf FROM sessoes WHERE id=:id LIMIT 1");
      $st->execute([':id'=>$aid]);
      $row = $st->fetch();
      if (!$row || empty($row['ata_pdf'])) not_found('Ata não encontrada.');
      $row['pdf_url'] =
