<?php
declare(strict_types=1);

require_once __DIR__ . '/db.php';

try {
    cadastro_require_write_access();
    $pdo = cadastro_pdo();
    $schema = cadastro_schema();
    $qSchema = cadastro_quote_ident($schema);
    $json = cadastro_read_json();

    $entity = trim((string)($json['entity'] ?? ''));
    $data = isset($json['data']) && is_array($json['data']) ? $json['data'] : [];

    $allowed = ['lote', 'construcao', 'componente', 'construcao_update', 'componente_update'];
    if (!in_array($entity, $allowed, true)) {
        cadastro_out(['ok' => false, 'message' => 'Entity inválida: ' . $entity], 400);
    }

    $wkt = trim((string)($data['wkt'] ?? ''));
    $geom = cadastro_geom_expr(':wkt');
    $area = cadastro_area_expr($geom);
    $user = cadastro_user();

    if ($entity === 'lote') {
        // Novo DDL: mun_jequie.ctm_lotes possui id_lote e geom.
        // O modo desenho NÃO usa mun_jequie.jequie_2025.
        // Salva/atualiza o lote diretamente em ctm_lotes, incluindo geom EPSG:4674.
        $seq = cadastro_normalize_nullable($data['sequencial_contribuinte'] ?? null);
        if (!$seq) cadastro_out(['ok' => false, 'message' => 'sequencial_contribuinte é obrigatório'], 400);
        if ($wkt === '') cadastro_out(['ok' => false, 'message' => 'wkt é obrigatório para lote'], 400);

        $params = [
            ':seq' => $seq,
            ':inscricao' => cadastro_normalize_nullable($data['inscricao'] ?? $data['inscricao_imobiliaria'] ?? null),
            ':inscricao_red' => cadastro_normalize_nullable($data['inscricao_red'] ?? $data['inscricao_reduzida'] ?? null),
            ':setor' => cadastro_normalize_nullable($data['setor'] ?? null),
            ':quadra' => cadastro_normalize_nullable($data['quadra'] ?? null),
            ':lote' => cadastro_normalize_nullable($data['lote'] ?? null),
            ':unidade' => cadastro_normalize_nullable($data['unidade'] ?? null),
            ':logradouro' => cadastro_normalize_nullable($data['logradouro'] ?? null),
            ':numero_lot' => cadastro_normalize_nullable($data['numero_lot'] ?? $data['numero'] ?? null),
            ':complemento' => cadastro_normalize_nullable($data['complemento'] ?? null),
            ':bairro' => cadastro_normalize_nullable($data['bairro'] ?? null),
            ':cep' => cadastro_normalize_nullable($data['cep'] ?? null),
            ':distrito' => cadastro_normalize_nullable($data['distrito'] ?? null),
            ':zoneamento' => cadastro_normalize_nullable($data['zoneamento'] ?? null),
            ':status_conf' => cadastro_normalize_nullable($data['status_conf'] ?? 'MAPA'),
            ':origem_dado' => cadastro_normalize_nullable($data['origem_dado'] ?? 'MAPA'),
            ':observacao' => cadastro_normalize_nullable($data['observacao'] ?? null),
            ':situacao' => cadastro_normalize_nullable($data['situacao'] ?? null),
            ':name' => cadastro_normalize_nullable($data['name'] ?? $data['proprietario_nome'] ?? null),
            ':updated_by' => $user,
            ':wkt' => $wkt,
        ];

        $pdo->beginTransaction();

        $sqlUpdate = "
            UPDATE {$qSchema}.ctm_lotes
               SET inscricao = COALESCE(:inscricao, inscricao),
                   inscricao_red = COALESCE(:inscricao_red, inscricao_red),
                   setor = COALESCE(:setor, setor),
                   quadra = COALESCE(:quadra, quadra),
                   lote = COALESCE(:lote, lote),
                   unidade = COALESCE(:unidade, unidade),
                   logradouro = COALESCE(:logradouro, logradouro),
                   numero_lot = COALESCE(:numero_lot, numero_lot),
                   complemento = COALESCE(:complemento, complemento),
                   bairro = COALESCE(:bairro, bairro),
                   cep = COALESCE(:cep, cep),
                   distrito = COALESCE(:distrito, distrito),
                   zoneamento = COALESCE(:zoneamento, zoneamento),
                   area_lote_m2 = {$area},
                   area_sistema_m2 = COALESCE(area_sistema_m2, {$area}),
                   status_conf = COALESCE(:status_conf, status_conf),
                   origem_dado = COALESCE(:origem_dado, origem_dado),
                   observacao = COALESCE(:observacao, observacao),
                   situacao = COALESCE(:situacao, situacao),
                   " . '"name"' . " = COALESCE(:name, " . '"name"' . "),
                   geom = {$geom},
                   latitude = ST_Y(ST_PointOnSurface({$geom})),
                   longitude = ST_X(ST_PointOnSurface({$geom})),
                   updated_at = now(),
                   updated_by = :updated_by
             WHERE sequencial_contribuinte = :seq
             RETURNING id_lote, area_lote_m2, latitude, longitude
        ";
        $st = $pdo->prepare($sqlUpdate);
        $st->execute($params);
        $row = $st->fetch();

        if (!$row) {
            $sqlInsert = "
                INSERT INTO {$qSchema}.ctm_lotes
                    (sequencial_contribuinte, inscricao, inscricao_red, setor, quadra, lote, unidade,
                     logradouro, numero_lot, complemento, bairro, cep, distrito, zoneamento,
                     area_lote_m2, area_sistema_m2, status_conf, origem_dado, observacao,
                     updated_at, updated_by, geom, latitude, longitude, situacao, " . '"name"' . ")
                VALUES
                    (:seq, :inscricao, :inscricao_red, :setor, :quadra, :lote, :unidade,
                     :logradouro, :numero_lot, :complemento, :bairro, :cep, :distrito, :zoneamento,
                     {$area}, {$area}, :status_conf, :origem_dado, :observacao,
                     now(), :updated_by, {$geom}, ST_Y(ST_PointOnSurface({$geom})), ST_X(ST_PointOnSurface({$geom})), :situacao, :name)
                RETURNING id_lote, area_lote_m2, latitude, longitude
            ";
            $ins = $pdo->prepare($sqlInsert);
            $ins->execute($params);
            $row = $ins->fetch();
            $action = 'inserido';
        } else {
            $action = 'atualizado';
        }

        $pdo->commit();

        cadastro_out([
            'ok' => true,
            'message' => "Lote {$action} em ctm_lotes",
            'entity' => 'lote',
            'sequencial_contribuinte' => $seq,
            'id' => $row['id_lote'] ?? null,
            'id_lote' => $row['id_lote'] ?? null,
            'area_lote_m2' => $row['area_lote_m2'] ?? null,
            'latitude' => $row['latitude'] ?? null,
            'longitude' => $row['longitude'] ?? null,
            'schema' => $schema,
            'table' => 'ctm_lotes',
            'geom_saved' => true,
        ]);
    }

    if ($entity === 'construcao') {
        if ($wkt === '') cadastro_out(['ok' => false, 'message' => 'wkt é obrigatório para construção'], 400);
        $seq = cadastro_normalize_nullable($data['sequencial_contribuinte'] ?? null);
        if (!$seq) cadastro_out(['ok' => false, 'message' => 'sequencial_contribuinte é obrigatório'], 400);

        $sql = "
            INSERT INTO {$qSchema}.ctm_construcoes
                (sequencial_contribuinte, tipo_const, padrao, pavimentos, ano_const, area_const_m2, updated_at, geom, data_construcao, fonte_data)
            VALUES
                (:seq, :tipo_const, :padrao, :pavimentos, :ano_const, {$area}, now(), {$geom}, :data_construcao, :fonte_data)
            RETURNING id_const, area_const_m2
        ";
        $st = $pdo->prepare($sql);
        $st->execute([
            ':seq' => $seq,
            ':tipo_const' => cadastro_normalize_nullable($data['tipo_const'] ?? null),
            ':padrao' => cadastro_normalize_nullable($data['padrao'] ?? null),
            ':pavimentos' => isset($data['pavimentos']) && $data['pavimentos'] !== '' ? max(1, (int)$data['pavimentos']) : null,
            ':ano_const' => isset($data['ano_const']) && $data['ano_const'] !== '' ? (int)$data['ano_const'] : null,
            ':data_construcao' => cadastro_normalize_nullable($data['data_construcao'] ?? null),
            ':fonte_data' => cadastro_normalize_nullable($data['fonte_data'] ?? 'MAPA'),
            ':wkt' => $wkt,
        ]);
        $row = $st->fetch() ?: [];
        cadastro_out(['ok' => true, 'message' => 'Construção salva', 'id' => $row['id_const'] ?? null, 'id_const' => $row['id_const'] ?? null, 'area_const_m2' => $row['area_const_m2'] ?? null, 'schema' => $schema]);
    }

    if ($entity === 'componente') {
        if ($wkt === '') cadastro_out(['ok' => false, 'message' => 'wkt é obrigatório para componente'], 400);
        $seq = cadastro_normalize_nullable($data['sequencial_contribuinte'] ?? null);
        if (!$seq) cadastro_out(['ok' => false, 'message' => 'sequencial_contribuinte é obrigatório'], 400);

        $sql = "
            INSERT INTO {$qSchema}.ctm_componentes
                (sequencial_contribuinte, tipo_comp, coberta, valor_agrega, area_comp_m2, updated_at, geom)
            VALUES
                (:seq, :tipo_comp, :coberta, :valor_agrega, {$area}, now(), {$geom})
            RETURNING id_comp, area_comp_m2
        ";
        $st = $pdo->prepare($sql);
        $st->execute([
            ':seq' => $seq,
            ':tipo_comp' => cadastro_normalize_nullable($data['tipo_comp'] ?? null),
            ':coberta' => cadastro_normalize_nullable($data['coberta'] ?? 'NAO'),
            ':valor_agrega' => cadastro_normalize_nullable($data['valor_agrega'] ?? 'SIM'),
            ':wkt' => $wkt,
        ]);
        $row = $st->fetch() ?: [];
        cadastro_out(['ok' => true, 'message' => 'Componente salvo', 'id' => $row['id_comp'] ?? null, 'id_comp' => $row['id_comp'] ?? null, 'area_comp_m2' => $row['area_comp_m2'] ?? null, 'schema' => $schema]);
    }

    if ($entity === 'construcao_update') {
        $id = (int)($data['id_const'] ?? 0);
        if ($id <= 0) cadastro_out(['ok' => false, 'message' => 'id_const é obrigatório'], 400);

        $sets = [
            'tipo_const = COALESCE(:tipo_const, tipo_const)',
            'padrao = COALESCE(:padrao, padrao)',
            'pavimentos = COALESCE(:pavimentos, pavimentos)',
            'ano_const = COALESCE(:ano_const, ano_const)',
            'updated_at = now()',
        ];
        if ($wkt !== '') {
            $sets[] = "geom = {$geom}";
            $sets[] = "area_const_m2 = {$area}";
        }
        $sql = "UPDATE {$qSchema}.ctm_construcoes SET " . implode(', ', $sets) . " WHERE id_const = :id RETURNING id_const, area_const_m2";
        $st = $pdo->prepare($sql);
        $params = [
            ':id' => $id,
            ':tipo_const' => cadastro_normalize_nullable($data['tipo_const'] ?? null),
            ':padrao' => cadastro_normalize_nullable($data['padrao'] ?? null),
            ':pavimentos' => isset($data['pavimentos']) && $data['pavimentos'] !== '' ? max(1, (int)$data['pavimentos']) : null,
            ':ano_const' => isset($data['ano_const']) && $data['ano_const'] !== '' ? (int)$data['ano_const'] : null,
        ];
        if ($wkt !== '') $params[':wkt'] = $wkt;
        $st->execute($params);
        $row = $st->fetch();
        if (!$row) cadastro_out(['ok' => false, 'message' => "Construção não encontrada: {$id}"], 404);
        cadastro_out(['ok' => true, 'message' => 'Construção atualizada', 'id' => $row['id_const'], 'id_const' => $row['id_const'], 'area_const_m2' => $row['area_const_m2'] ?? null, 'schema' => $schema]);
    }

    if ($entity === 'componente_update') {
        $id = (int)($data['id_comp'] ?? 0);
        if ($id <= 0) cadastro_out(['ok' => false, 'message' => 'id_comp é obrigatório'], 400);

        $sets = [
            'tipo_comp = COALESCE(:tipo_comp, tipo_comp)',
            'coberta = COALESCE(:coberta, coberta)',
            'valor_agrega = COALESCE(:valor_agrega, valor_agrega)',
            'updated_at = now()',
        ];
        if ($wkt !== '') {
            $sets[] = "geom = {$geom}";
            $sets[] = "area_comp_m2 = {$area}";
        }
        $sql = "UPDATE {$qSchema}.ctm_componentes SET " . implode(', ', $sets) . " WHERE id_comp = :id RETURNING id_comp, area_comp_m2";
        $st = $pdo->prepare($sql);
        $params = [
            ':id' => $id,
            ':tipo_comp' => cadastro_normalize_nullable($data['tipo_comp'] ?? null),
            ':coberta' => cadastro_normalize_nullable($data['coberta'] ?? null),
            ':valor_agrega' => cadastro_normalize_nullable($data['valor_agrega'] ?? null),
        ];
        if ($wkt !== '') $params[':wkt'] = $wkt;
        $st->execute($params);
        $row = $st->fetch();
        if (!$row) cadastro_out(['ok' => false, 'message' => "Componente não encontrado: {$id}"], 404);
        cadastro_out(['ok' => true, 'message' => 'Componente atualizado', 'id' => $row['id_comp'], 'id_comp' => $row['id_comp'], 'area_comp_m2' => $row['area_comp_m2'] ?? null, 'schema' => $schema]);
    }

    cadastro_out(['ok' => false, 'message' => 'Fluxo não tratado'], 400);
} catch (Throwable $e) {
    if (isset($pdo) && $pdo instanceof PDO && $pdo->inTransaction()) {
        $pdo->rollBack();
    }
    cadastro_out(['ok' => false, 'message' => 'Erro ao salvar cadastro: ' . $e->getMessage()], 500);
}
