<?php
require_once __DIR__ . "/_bootstrap.php";

header("Content-Type: application/json; charset=utf-8");

function jexit($ok, $data = [], $code = 200){
  http_response_code($code);
  echo json_encode(array_merge(["ok"=>$ok], $data), JSON_UNESCAPED_UNICODE);
  exit;
}

function money_to_decimal($s){
  $s = trim((string)$s);
  $s = str_replace(["R$", "\n", "\r", "\t", " "], "", $s);
  $s = str_replace(".", "", $s);
  $s = str_replace(",", ".", $s);
  if ($s === "" || !is_numeric($s)) return null;
  return (float)$s;
}

function table_exists(PDO $pdo, string $table): bool {
  $st = $pdo->prepare("SELECT COUNT(*) c FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = ?");
  $st->execute([$table]);
  return ((int)($st->fetch(PDO::FETCH_ASSOC)['c'] ?? 0)) > 0;
}

function column_exists(PDO $pdo, string $table, string $column): bool {
  $st = $pdo->prepare("
    SELECT COUNT(*) c
    FROM INFORMATION_SCHEMA.COLUMNS
    WHERE TABLE_SCHEMA = DATABASE()
      AND TABLE_NAME = ?
      AND COLUMN_NAME = ?
  ");
  $st->execute([$table, $column]);
  return ((int)($st->fetch(PDO::FETCH_ASSOC)['c'] ?? 0)) > 0;
}

function get_open_caixa(PDO $pdo): ?array {
  if (!table_exists($pdo, 'caixas')) return null;
  $st = $pdo->query("
    SELECT id, usuario_id, aberto_em, saldo_inicial, observacoes
    FROM caixas
    WHERE status='ABERTO'
    ORDER BY id DESC
    LIMIT 1
  ");
  $cx = $st->fetch(PDO::FETCH_ASSOC);
  return $cx ?: null;
}

function ensure_caixa_lancamentos(PDO $pdo){
  if (!table_exists($pdo, 'caixa_lancamentos')) {
    // ✅ Cria já com suporte a pendentes
    $pdo->exec("
      CREATE TABLE caixa_lancamentos (
        id INT AUTO_INCREMENT PRIMARY KEY,
        caixa_id INT NULL,
        usuario_id INT NULL,
        tipo ENUM('ENTRADA','SAIDA') NOT NULL DEFAULT 'ENTRADA',
        categoria VARCHAR(40) NOT NULL DEFAULT 'OUTRO',
        valor DECIMAL(10,2) NOT NULL,
        descricao VARCHAR(255) NULL,
        ref_table VARCHAR(40) NULL,
        ref_id INT NULL,
        status ENUM('OK','PENDENTE','CANCELADO') NOT NULL DEFAULT 'OK',
        conciliado_em DATETIME NULL,
        caixa_conciliado_id INT NULL,
        criado_em DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
        INDEX (caixa_id),
        INDEX (criado_em),
        INDEX (categoria),
        INDEX idx_caixa_lanc_status (status, criado_em)
      ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
    ");
    // FK só se existir caixas
    if (table_exists($pdo, 'caixas')) {
      try{
        $pdo->exec("
          ALTER TABLE caixa_lancamentos
            ADD CONSTRAINT fk_caixa_lancamentos_caixa
            FOREIGN KEY (caixa_id) REFERENCES caixas(id)
            ON DELETE SET NULL
        ");
      }catch(Throwable $e){
        // ignora
      }
    }
    return;
  }

  // ✅ Se já existe, garante colunas/índices necessários
  try { $pdo->exec("ALTER TABLE caixa_lancamentos MODIFY caixa_id INT NULL"); } catch(Throwable $e){}

  if (!column_exists($pdo, 'caixa_lancamentos', 'status')) {
    $pdo->exec("ALTER TABLE caixa_lancamentos ADD COLUMN status ENUM('OK','PENDENTE','CANCELADO') NOT NULL DEFAULT 'OK'");
  }
  if (!column_exists($pdo, 'caixa_lancamentos', 'conciliado_em')) {
    $pdo->exec("ALTER TABLE caixa_lancamentos ADD COLUMN conciliado_em DATETIME NULL");
  }
  if (!column_exists($pdo, 'caixa_lancamentos', 'caixa_conciliado_id')) {
    $pdo->exec("ALTER TABLE caixa_lancamentos ADD COLUMN caixa_conciliado_id INT NULL");
  }
  try { $pdo->exec("CREATE INDEX idx_caixa_lanc_status ON caixa_lancamentos(status, criado_em)"); } catch(Throwable $e){}
}

function pendentes_resumo(PDO $pdo): array {
  if (!table_exists($pdo, 'caixa_lancamentos')) return ["qtd"=>0, "valor"=>0.0];
  if (!column_exists($pdo, 'caixa_lancamentos', 'status')) return ["qtd"=>0, "valor"=>0.0];

  $st = $pdo->query("
    SELECT
      COUNT(*) qtd,
      COALESCE(SUM(CASE WHEN tipo='ENTRADA' THEN valor ELSE -valor END),0) valor
    FROM caixa_lancamentos
    WHERE status='PENDENTE'
  ");
  $r = $st->fetch(PDO::FETCH_ASSOC) ?: ["qtd"=>0,"valor"=>0];
  return ["qtd" => (int)$r["qtd"], "valor" => (float)$r["valor"]];
}

function conciliar_pendentes(PDO $pdo, int $caixaId, bool $apenasHoje = false): int {
  if (!table_exists($pdo, 'caixa_lancamentos')) return 0;
  if (!column_exists($pdo, 'caixa_lancamentos', 'status')) return 0;

  if ($apenasHoje){
    $st = $pdo->prepare("
      UPDATE caixa_lancamentos
      SET caixa_id = ?,
          status = 'OK',
          conciliado_em = NOW(),
          caixa_conciliado_id = ?
      WHERE status='PENDENTE'
        AND criado_em >= CURDATE()
    ");
    $st->execute([$caixaId, $caixaId]);
  } else {
    $st = $pdo->prepare("
      UPDATE caixa_lancamentos
      SET caixa_id = ?,
          status = 'OK',
          conciliado_em = NOW(),
          caixa_conciliado_id = ?
      WHERE status='PENDENTE'
    ");
    $st->execute([$caixaId, $caixaId]);
  }
  return $st->rowCount();
}

// ✅ autenticação (ajuste conforme sua sessão real)
if (!isset($_SESSION['staff']['id'])) {
  jexit(false, ["error"=>"Não autenticado."], 401);
}
$usuarioId = (int)$_SESSION['staff']['id'];

$action = $_GET["action"] ?? $_POST["action"] ?? "";

try {
  // garante estrutura
  ensure_caixa_lancamentos($pdo);

  if ($action === "status") {
    $cx = get_open_caixa($pdo);
    $pend = pendentes_resumo($pdo);
    jexit(true, [
      "caixa_aberto" => $cx ? true : false,
      "caixa" => $cx ?: null,
      "pendentes" => $pend
    ]);
  }

  if ($action === "abrir") {
    if (!table_exists($pdo, 'caixas')) {
      jexit(false, ["error"=>"Tabela 'caixas' não encontrada. Verifique o módulo de caixa."], 500);
    }

    $saldoInicial = money_to_decimal($_POST["saldo_inicial"] ?? "");
    $obs = trim((string)($_POST["observacoes"] ?? ""));

    if ($saldoInicial === null || $saldoInicial < 0) {
      jexit(false, ["error"=>"Informe um saldo inicial válido."], 422);
    }

    $pdo->beginTransaction();

    $st = $pdo->query("SELECT id FROM caixas WHERE status='ABERTO' LIMIT 1 FOR UPDATE");
    $open = $st->fetch(PDO::FETCH_ASSOC);
    if ($open) {
      $pdo->rollBack();
      jexit(false, ["error"=>"Já existe um caixa ABERTO. Feche antes de abrir outro."], 409);
    }

    $ins = $pdo->prepare("
      INSERT INTO caixas (usuario_id, aberto_em, saldo_inicial, status, observacoes)
      VALUES (?, NOW(), ?, 'ABERTO', ?)
    ");
    $ins->execute([
      $usuarioId,
      number_format($saldoInicial, 2, ".", ""),
      $obs
    ]);

    $caixaId = (int)$pdo->lastInsertId();

    $ins2 = $pdo->prepare("
      INSERT INTO caixa_lancamentos (caixa_id, usuario_id, tipo, categoria, valor, descricao, status)
      VALUES (?, ?, 'ENTRADA', 'SALDO_INICIAL', ?, 'Abertura do caixa (saldo inicial)', 'OK')
    ");
    $ins2->execute([$caixaId, $usuarioId, number_format($saldoInicial, 2, ".", "")]);

    // ✅ concilia automaticamente pendentes de HOJE
    $conciliados = conciliar_pendentes($pdo, $caixaId, true);

    $pdo->commit();

    jexit(true, [
      "message" => "Caixa aberto com sucesso.",
      "caixa_id" => $caixaId,
      "conciliados_hoje" => $conciliados
    ]);
  }

  if ($action === "resumo") {
    $cx = get_open_caixa($pdo);
    $pend = pendentes_resumo($pdo);

    if (!$cx) {
      jexit(true, [
        "caixa_aberto" => false,
        "caixa" => null,
        "totais" => ["entradas"=>0,"saidas"=>0,"saldo_atual"=>0],
        "por_categoria" => [],
        "pendentes" => $pend
      ]);
    }

    $caixaId = (int)$cx["id"];

    $st = $pdo->prepare("
      SELECT
        COALESCE(SUM(CASE WHEN tipo='ENTRADA' THEN valor ELSE 0 END),0) entradas,
        COALESCE(SUM(CASE WHEN tipo='SAIDA'  THEN valor ELSE 0 END),0) saidas
      FROM caixa_lancamentos
      WHERE caixa_id = ?
        AND (status IS NULL OR status='OK')
    ");
    $st->execute([$caixaId]);
    $t = $st->fetch(PDO::FETCH_ASSOC) ?: ["entradas"=>0,"saidas"=>0];

    $entradas = (float)$t["entradas"];
    $saidas   = (float)$t["saidas"];
    $saldoAtual = $entradas - $saidas;

    $st2 = $pdo->prepare("
      SELECT categoria,
             COALESCE(SUM(CASE WHEN tipo='ENTRADA' THEN valor ELSE 0 END),0) entradas,
             COALESCE(SUM(CASE WHEN tipo='SAIDA'  THEN valor ELSE 0 END),0) saidas
      FROM caixa_lancamentos
      WHERE caixa_id = ?
        AND (status IS NULL OR status='OK')
      GROUP BY categoria
      ORDER BY categoria
    ");
    $st2->execute([$caixaId]);
    $cats = $st2->fetchAll(PDO::FETCH_ASSOC);

    jexit(true, [
      "caixa_aberto" => true,
      "caixa" => $cx,
      "totais" => ["entradas"=>$entradas,"saidas"=>$saidas,"saldo_atual"=>$saldoAtual],
      "por_categoria" => $cats,
      "pendentes" => $pend
    ]);
  }

  if ($action === "pendentes_resumo") {
    jexit(true, ["pendentes" => pendentes_resumo($pdo)]);
  }

  if ($action === "pendentes_listar") {
    if (!table_exists($pdo, 'caixa_lancamentos') || !column_exists($pdo, 'caixa_lancamentos', 'status')) {
      jexit(true, ["itens" => []]);
    }
    $st = $pdo->query("
      SELECT id, tipo, categoria, valor, descricao, ref_table, ref_id, criado_em
      FROM caixa_lancamentos
      WHERE status='PENDENTE'
      ORDER BY id DESC
      LIMIT 100
    ");
    jexit(true, ["itens" => $st->fetchAll(PDO::FETCH_ASSOC)]);
  }

  if ($action === "conciliar_pendentes") {
    $cx = get_open_caixa($pdo);
    if (!$cx) jexit(false, ["error"=>"Não há caixa ABERTO para conciliar."], 409);

    $apenasHoje = (($_POST["apenas_hoje"] ?? $_GET["apenas_hoje"] ?? "") === "1");

    $pdo->beginTransaction();
    $qtd = conciliar_pendentes($pdo, (int)$cx["id"], $apenasHoje);
    $pdo->commit();

    jexit(true, ["message"=>"Pendentes conciliados.", "qtd"=>$qtd]);
  }

  jexit(false, ["error"=>"Ação inválida."], 400);

} catch (Throwable $e) {
  if ($pdo->inTransaction()) $pdo->rollBack();
  jexit(false, ["error"=>"Erro interno: ".$e->getMessage()], 500);
}
