<?php
require_once '../../core/config.php';
require_once '../../core/session.php';
require_once '../../core/database.php';
require_once '../../core/auth.php';
require_once '../../core/permissions.php';

require_login();
header('Content-Type: application/json; charset=utf-8');
if (current_user_role() !== 'admin') {
    http_response_code(403);
    echo json_encode(array('success' => false, 'message' => 'No autorizado.'));
    exit;
}
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    http_response_code(405);
    echo json_encode(array('success' => false, 'message' => 'Método no permitido.'));
    exit;
}

function center_bool($value) { return in_array((string)$value, array('1','true','on','yes'), true) ? 1 : 0; }

try {
    csrf_require_valid_request();
    $pdo = db();
    $action = trim((string)($_POST['action'] ?? 'save'));
    $id = (int)($_POST['id'] ?? 0);

    if ($action === 'toggle') {
        if ($id <= 0) throw new RuntimeException('Centro inválido.');
        $stmt = $pdo->prepare("SELECT * FROM finance_centers WHERE id = ? LIMIT 1");
        $stmt->execute(array($id));
        $center = $stmt->fetch(PDO::FETCH_ASSOC);
        if (!$center) throw new RuntimeException('Centro no encontrado.');
        if (in_array($center['center_code'], array('NO_INCOME_CENTER','NO_COST_CENTER'), true)) {
            throw new RuntimeException('Los centros predeterminados del sistema no pueden desactivarse.');
        }
        $newActive = empty($center['is_active']) ? 1 : 0;
        if (!$newActive) {
            $refs = 0;
            $checks = array(
                "SELECT COUNT(*) FROM crm_customers WHERE default_income_center_id = ? OR default_cost_center_id = ? OR supplier_default_cost_center_id = ?" => array($id,$id,$id),
                "SELECT COUNT(*) FROM crm_documents WHERE finance_center_id = ?" => array($id),
                "SELECT COUNT(*) FROM facto_inbox_documents WHERE finance_center_id = ?" => array($id),
                "SELECT COUNT(*) FROM billing_collections WHERE finance_center_id = ?" => array($id),
                "SELECT COUNT(*) FROM cost_categories WHERE default_finance_center_id = ?" => array($id),
                "SELECT COUNT(*) FROM cost_entries WHERE finance_center_id = ?" => array($id),
                "SELECT COUNT(*) FROM cost_allocations WHERE finance_center_id = ?" => array($id),
                "SELECT COUNT(*) FROM cost_recurring_rules WHERE finance_center_id = ?" => array($id),
                "SELECT COUNT(*) FROM cost_payroll_entries WHERE finance_center_id = ?" => array($id)
            );
            foreach ($checks as $sql => $params) { $q=$pdo->prepare($sql); $q->execute($params); $refs += (int)$q->fetchColumn(); }
            $settingsTable = $pdo->query("SELECT COUNT(*) FROM information_schema.tables WHERE table_schema=DATABASE() AND table_name='finance_center_assignment_settings'")->fetchColumn();
            if ((int)$settingsTable > 0) { $q=$pdo->prepare('SELECT COUNT(*) FROM finance_center_assignment_settings WHERE global_cost_center_id=?'); $q->execute(array($id)); $refs += (int)$q->fetchColumn(); }
            if ($refs > 0) throw new RuntimeException('No se puede desactivar: el centro está asignado a contrapartes o documentos. Reasigna esas referencias primero.');
        }
        $pdo->prepare("UPDATE finance_centers SET is_active = ?, is_default = CASE WHEN ? = 0 THEN 0 ELSE is_default END, updated_at = NOW() WHERE id = ?")
            ->execute(array($newActive, $newActive, $id));
        echo json_encode(array('success' => true, 'message' => $newActive ? 'Centro activado.' : 'Centro desactivado.'));
        exit;
    }

    $code = strtoupper(trim((string)($_POST['center_code'] ?? '')));
    $name = trim((string)($_POST['center_name'] ?? ''));
    $type = trim((string)($_POST['center_type'] ?? 'both'));
    $parentId = ($_POST['parent_id'] ?? '') !== '' ? (int)$_POST['parent_id'] : null;
    $description = trim((string)($_POST['description'] ?? ''));
    $isDefault = center_bool($_POST['is_default'] ?? 0);
    $isActive = center_bool($_POST['is_active'] ?? 1);

    if ($code === '' || !preg_match('/^[A-Z0-9_-]{2,50}$/', $code)) throw new RuntimeException('El código debe contener 2 a 50 caracteres: letras, números, guion o guion bajo.');
    if ($name === '') throw new RuntimeException('El nombre del centro es obligatorio.');
    if (!in_array($type, array('cost','income','both'), true)) throw new RuntimeException('Tipo de centro inválido.');
    if ($parentId !== null && $parentId === $id) throw new RuntimeException('Un centro no puede depender de sí mismo.');

    $dup = $pdo->prepare("SELECT id FROM finance_centers WHERE center_code = ? AND id <> ? LIMIT 1");
    $dup->execute(array($code, $id));
    if ($dup->fetchColumn()) throw new RuntimeException('Ya existe un centro con ese código.');

    if ($id > 0) {
        $currentStmt = $pdo->prepare("SELECT * FROM finance_centers WHERE id = ? LIMIT 1");
        $currentStmt->execute(array($id));
        $current = $currentStmt->fetch(PDO::FETCH_ASSOC);
        if (!$current) throw new RuntimeException('Centro no encontrado.');
        if (in_array($current['center_code'], array('NO_INCOME_CENTER','NO_COST_CENTER'), true)) {
            $code = $current['center_code'];
            $type = $current['center_type'];
            $isActive = 1;
            $isDefault = 1;
        }
    }

    $pdo->beginTransaction();
    if ($isDefault) {
        if ($type === 'income') $pdo->exec("UPDATE finance_centers SET is_default = 0 WHERE center_type IN ('income','both')");
        elseif ($type === 'cost') $pdo->exec("UPDATE finance_centers SET is_default = 0 WHERE center_type IN ('cost','both')");
        else $pdo->exec("UPDATE finance_centers SET is_default = 0");
    }

    if ($id > 0) {
        $stmt = $pdo->prepare("UPDATE finance_centers SET center_code=?, center_name=?, center_type=?, parent_id=?, is_default=?, is_active=?, description=?, updated_at=NOW() WHERE id=?");
        $stmt->execute(array($code,$name,$type,$parentId,$isDefault,$isActive,$description !== '' ? $description : null,$id));
    } else {
        $stmt = $pdo->prepare("INSERT INTO finance_centers (center_code,center_name,center_type,parent_id,is_default,is_active,description,created_by,created_at,updated_at) VALUES (?,?,?,?,?,?,?,?,NOW(),NOW())");
        $stmt->execute(array($code,$name,$type,$parentId,$isDefault,$isActive,$description !== '' ? $description : null,current_user_id()));
        $id = (int)$pdo->lastInsertId();
    }
    $pdo->commit();
    echo json_encode(array('success' => true, 'message' => 'Centro financiero guardado.', 'id' => $id), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
} catch (Throwable $e) {
    if (isset($pdo) && $pdo->inTransaction()) $pdo->rollBack();
    http_response_code(400);
    echo json_encode(array('success' => false, 'message' => $e->getMessage()), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
}
