<?php
declare(strict_types=1);
// ============================================================
// lib/helpers.php — agendaJuicios OGJ Rosario
// ============================================================

// ── Días hábiles ──────────────────────────────────────────────
function es_dia_habil(PDO $pdo, string $fecha): bool
{
    if ((int)date('N', strtotime($fecha)) >= 6) return false;
    $s = $pdo->prepare("SELECT COUNT(*) FROM ogj_feriados WHERE fecha = ?");
    $s->execute([$fecha]);
    return (int)$s->fetchColumn() === 0;
}

function agregar_dias_habiles(PDO $pdo, string $fecha, int $dias): string
{
    $dt = new DateTime($fecha);
    if ($dias === 0) {
        while (!es_dia_habil($pdo, $dt->format('Y-m-d'))) $dt->modify('+1 day');
        return $dt->format('Y-m-d');
    }
    $agr = 0;
    while ($agr < $dias) {
        $dt->modify('+1 day');
        if (es_dia_habil($pdo, $dt->format('Y-m-d'))) $agr++;
    }
    return $dt->format('Y-m-d');
}

function get_param(PDO $pdo, string $clave, string $default = ''): string
{
    static $cache = [];
    if (!isset($cache[$clave])) {
        $s = $pdo->prepare("SELECT valor FROM agj_parametros WHERE clave = ?");
        $s->execute([$clave]);
        $r = $s->fetch();
        $cache[$clave] = $r ? $r['valor'] : $default;
    }
    return $cache[$clave];
}

// ── Calcular fechas del debate ────────────────────────────────
function calcular_fechas_debate(
    PDO $pdo, string $debate_desde,
    int $jornadas, int $extras = 0, int $pre_alegatos = 0,
    bool $duplicidad = false
): array {
    $desde    = agregar_dias_habiles($pdo, $debate_desde, 0);
    $dias_tot = ($jornadas - 1) + $extras + $pre_alegatos;
    $hasta    = $dias_tot > 0 ? agregar_dias_habiles($pdo, $desde, $dias_tot) : $desde;
    $dv       = (int)get_param($pdo, 'dias_habiles_veredicto', '2');
    $df       = (int)get_param($pdo, 'dias_habiles_fundamentos', '5');
    if ($duplicidad) { $dv *= 2; $df *= 2; }
    $fallo   = agregar_dias_habiles($pdo, $hasta, $dv);
    $bloqueo = agregar_dias_habiles($pdo, $fallo, $df);
    return [
        'debate_desde'      => $desde,
        'debate_hasta'      => $hasta,
        'fecha_fallo'       => $fallo,
        'fecha_fin_bloqueo' => $bloqueo,
    ];
}

// ── Calcular prioridad ────────────────────────────────────────

/**
 * Devuelve el desglose de la prioridad como array de componentes + total.
 * Cada componente: ['label' => string, 'valor' => int]
 */
function calcular_prioridad_detalle(array $aa): array
{
    $hoy  = new DateTime('today');
    $comp = [['label' => 'Base', 'valor' => 100]];
    $p    = 100;

    $diasAA = 0;
    if (!empty($aa['fecha_auto_apertura'])) {
        $faa    = new DateTime($aa['fecha_auto_apertura']);
        $diasAA = (int)$hoy->diff($faa)->days;
        $comp[] = ['label' => "Antigüedad del caso ($diasAA días desde AA)", 'valor' => $diasAA];
        $p     += $diasAA;
    }

    if (($aa['estado_imputado'] ?? '') === 'Preso') {
        if (!empty($aa['fecha_detencion'])) {
            $det    = new DateTime($aa['fecha_detencion']);
            $dp     = (int)$hoy->diff($det)->days;
            $val    = $dp * 3;
            $comp[] = ['label' => "Días en PP: $dp días × 3", 'valor' => $val];
            $p     += $val;
        }
        if (!empty($aa['vencimiento_pp_actual'])) {
            $venc = new DateTime($aa['vencimiento_pp_actual']);
            if ($venc <= $hoy) {
                $comp[] = ['label' => 'PP vencida', 'valor' => 1000];
                $p     += 1000;
            } elseif (($dv = (int)$hoy->diff($venc)->days) <= 90) {
                $comp[] = ['label' => "PP vence en $dv días (< 90)", 'valor' => 500];
                $p     += 500;
            }
        }
    } elseif (!empty($aa['medidas_juzgado_familia'])) {
        $val    = $diasAA * 3;
        $comp[] = ['label' => "Medidas Juzgado de Familia ($diasAA días × 3)", 'valor' => $val];
        $p     += $val;
    }

    foreach (['fecha_prescripcion_menor' => 'menor', 'fecha_prescripcion_mayor' => 'mayor'] as $campo => $tipo) {
        if (!empty($aa[$campo])) {
            $fp = new DateTime($aa[$campo]);
            if ($fp > $hoy && ($dp = (int)$hoy->diff($fp)->days) <= 90) {
                $comp[] = ['label' => "Prescripción $tipo vence en $dp días (< 90)", 'valor' => 500];
                $p     += 500;
                break;
            }
        }
    }

    $agr = (int)($aa['prioridad_agregada'] ?? 0);
    if ($agr !== 0) {
        $comp[] = ['label' => 'Ajuste manual', 'valor' => $agr];
        $p     += $agr;
    }

    return ['componentes' => $comp, 'total' => max(0, $p)];
}

function calcular_prioridad(array $aa): int
{
    return calcular_prioridad_detalle($aa)['total'];
}

// ── Litigantes asociativos ────────────────────────────────────

/**
 * Guarda los litigantes de un AA en la tabla agj_aa_litigantes.
 * $litigantes = [ ['litigante_id'=>'F001','rol_en_causa'=>'Fiscal'], ... ]
 * Reemplaza todos los existentes del AA.
 */
function guardar_litigantes(PDO $pdo, int $aa_id, array $litigantes): void
{
    $pdo->prepare("DELETE FROM agj_aa_litigantes WHERE aa_id = ?")->execute([$aa_id]);
    if (empty($litigantes)) return;
    $ins = $pdo->prepare(
        "INSERT INTO agj_aa_litigantes (aa_id, litigante_id, rol_en_causa, orden) VALUES (?,?,?,?)"
    );
    $orden_por_rol = ['Fiscal'=>1,'Defensor'=>1,'Querellante'=>1];
    foreach ($litigantes as $lit) {
        if (empty($lit['litigante_id']) || empty($lit['rol_en_causa'])) continue;
        $rol = $lit['rol_en_causa'];
        $ins->execute([$aa_id, $lit['litigante_id'], $rol, $orden_por_rol[$rol] ?? 1]);
        $orden_por_rol[$rol]++;
    }
}

/**
 * Guarda los jueces intervinientes en IPP en agj_aa_jueces_ipp.
 * $juez_ids = ['J001','J002', ...]
 */
function guardar_jueces_ipp(PDO $pdo, int $aa_id, array $juez_ids): void
{
    $pdo->prepare("DELETE FROM agj_aa_jueces_ipp WHERE aa_id = ?")->execute([$aa_id]);
    if (empty($juez_ids)) return;
    $ins = $pdo->prepare(
        "INSERT INTO agj_aa_jueces_ipp (aa_id, juez_id, orden) VALUES (?,?,?)"
    );
    foreach (array_values($juez_ids) as $i => $jid) {
        if (empty($jid)) continue;
        $ins->execute([$aa_id, $jid, $i + 1]);
    }
}

/**
 * Carga los litigantes de un AA agrupados por rol.
 * Retorna ['Fiscal'=>[...], 'Defensor'=>[...], 'Querellante'=>[...]]
 */
function cargar_litigantes_aa(PDO $pdo, int $aa_id): array
{
    $s = $pdo->prepare("
        SELECT al.litigante_id, al.rol_en_causa, al.orden, vl.nombre, vl.rol AS rol_origen
        FROM agj_aa_litigantes al
        JOIN v_litigantes vl ON al.litigante_id = vl.litigante_id
        WHERE al.aa_id = ?
        ORDER BY al.rol_en_causa, al.orden, al.id
    ");
    $s->execute([$aa_id]);
    $result = ['Fiscal'=>[], 'Defensor'=>[], 'Querellante'=>[]];
    foreach ($s->fetchAll() as $r) {
        $result[$r['rol_en_causa']][] = $r;
    }
    return $result;
}

/**
 * Carga los jueces IPP de un AA.
 */
function cargar_jueces_ipp_aa(PDO $pdo, int $aa_id): array
{
    $s = $pdo->prepare("
        SELECT ji.juez_id, mj.nombre
        FROM agj_aa_jueces_ipp ji
        JOIN mrbs_juez mj ON ji.juez_id = mj.juez_id
        WHERE ji.aa_id = ?
        ORDER BY ji.orden, ji.id
    ");
    $s->execute([$aa_id]);
    return $s->fetchAll();
}

/**
 * Devuelve IDs únicos de jueces que aparecen en mrbs_entry para el cuij dado.
 */
function jueces_de_cuij(PDO $pdo, string $cuij_principal, string $otros_cuijs = ''): array
{
    $ignorar = ['J000','JT00','JC00','JIPP'];
    $cuijs   = array_values(array_unique(array_filter(
        array_merge([$cuij_principal], preg_split('/\s+/', trim($otros_cuijs)))
    )));
    if (empty($cuijs)) return [];
    $jueces = [];
    $stmt = $pdo->prepare(
        "SELECT juez_id, juez2_id, juez3_id FROM mrbs_entry WHERE name LIKE ? LIMIT 500"
    );
    foreach ($cuijs as $cuij) {
        if (strlen($cuij) < 5) continue;
        $stmt->execute(['%' . $cuij . '%']);
        foreach ($stmt->fetchAll() as $row) {
            foreach (['juez_id','juez2_id','juez3_id'] as $col) {
                $jid = trim($row[$col] ?? '');
                if ($jid && !in_array($jid, $ignorar, true)) {
                    $jueces[] = $jid;
                }
            }
        }
    }
    return array_values(array_unique($jueces));
}

// ── Superposición ─────────────────────────────────────────────
// $presidente_id_prop: juez_id del presidente en el NUEVO agendamiento (aplica RN4)
// $fecha_fallo_prop:   fecha_fallo del NUEVO agendamiento (para aplicar RN5 a vocales)
function verificar_superposicion(
    PDO $pdo, string $desde, string $hasta,
    array $juez_ids, int $excluir_ag = 0,
    array $litigante_ids = [],
    string $presidente_id_prop = '',
    string $fecha_fallo_prop = ''
): array {
    $juez_ids      = array_values(array_filter($juez_ids,      fn($j) => $j && $j !== 'J000'));
    $litigante_ids = array_values(array_filter($litigante_ids));

    if (empty($juez_ids) && empty($litigante_ids)) return [];

    $conds = [];
    $extraParams = [];
    if (!empty($juez_ids)) {
        $ph = implode(',', array_fill(0, count($juez_ids), '?'));
        $conds[] = "(ag.presidente_id IN ($ph) OR ag.vocal_1_id IN ($ph) OR ag.vocal_2_id IN ($ph))";
        array_push($extraParams, ...$juez_ids, ...$juez_ids, ...$juez_ids);
    }
    if (!empty($litigante_ids)) {
        $ph2 = implode(',', array_fill(0, count($litigante_ids), '?'));
        $conds[] = "EXISTS (SELECT 1 FROM agj_aa_litigantes _al WHERE _al.aa_id = aa.id AND _al.litigante_id IN ($ph2))";
        array_push($extraParams, ...$litigante_ids);
    }

    $s = $pdo->prepare("
        SELECT ag.id, ag.aa_id AS aa_id_conflicto,
               aa.cuij_principal AS cuij, aa.imputados,
               ag.debate_desde, ag.fecha_fallo, ag.fecha_fin_bloqueo,
               ag.condicion, ag.sub_condicion,
               ag.presidente_id, ag.vocal_1_id, ag.vocal_2_id,
               jPte.nombre AS pte, jV1.nombre AS v1, jV2.nombre AS v2
        FROM agj_agendamientos ag
        JOIN agj_autos_apertura aa ON ag.aa_id = aa.id
        LEFT JOIN mrbs_juez jPte ON ag.presidente_id = jPte.juez_id
        LEFT JOIN mrbs_juez jV1  ON ag.vocal_1_id    = jV1.juez_id
        LEFT JOIN mrbs_juez jV2  ON ag.vocal_2_id    = jV2.juez_id
        WHERE ag.estado NOT IN ('Cancelado')
          AND ag.deleted_at IS NULL
          AND ag.id <> ?
          AND ag.debate_desde <= ?
          AND ag.fecha_fin_bloqueo >= ?
          AND (" . implode(' OR ', $conds) . ")
    ");
    $s->execute(array_merge([$excluir_ag, $hasta, $desde], $extraParams));
    $candidatos = $s->fetchAll();

    if (empty($candidatos)) return [];

    // Batch: qué litigantes nuestros aparecen en los AAs en conflicto
    $litPorAA = [];
    if (!empty($litigante_ids)) {
        $aaIds = array_unique(array_column($candidatos, 'aa_id_conflicto'));
        $ph3   = implode(',', array_fill(0, count($aaIds), '?'));
        $ph4   = implode(',', array_fill(0, count($litigante_ids), '?'));
        $stmtL = $pdo->prepare("
            SELECT al.aa_id, vl.nombre
            FROM agj_aa_litigantes al
            JOIN v_litigantes vl ON al.litigante_id = vl.litigante_id
            WHERE al.aa_id IN ($ph3) AND al.litigante_id IN ($ph4)
        ");
        $stmtL->execute(array_merge($aaIds, $litigante_ids));
        foreach ($stmtL->fetchAll() as $r) {
            $litPorAA[$r['aa_id']][] = $r['nombre'];
        }
    }

    $conflictos = [];
    foreach ($candidatos as $c) {
        $ini = max($desde, $c['debate_desde']);
        $fin = min($hasta, $c['fecha_fin_bloqueo']);
        if ($ini > $fin) continue;
        $dt = new DateTime($ini); $fe = new DateTime($fin);
        $hayHabil = false;
        while ($dt <= $fe) {
            if (es_dia_habil($pdo, $dt->format('Y-m-d'))) { $hayHabil = true; break; }
            $dt->modify('+1 day');
        }
        if (!$hayHabil) continue;

        // Qué jueces del tribunal nuevo colisionan con este agendamiento
        // RN4 (presidente del NUEVO): solapa con [existente.desde..existente.fin_bloqueo]
        // RN5 (vocal del NUEVO):      solapa con [existente.desde..existente.fecha_fallo]
        $juecesConfl = [];
        foreach (['presidente_id' => 'pte', 'vocal_1_id' => 'v1', 'vocal_2_id' => 'v2'] as $idF => $nomF) {
            $jid = $c[$idF] ?? '';
            if (!$jid || !in_array($jid, $juez_ids, true) || empty($c[$nomF])) continue;

            $esPresidenteNuevo = ($presidente_id_prop && $jid === $presidente_id_prop);

            if ($esPresidenteNuevo || !$fecha_fallo_prop) {
                // RN4: presidente → el SQL ya garantizó el solapamiento de período completo
                $juecesConfl[] = $c[$nomF];
            } else {
                // RN5: vocal → conflicto solo si [existente.debate_desde..existente.fecha_fallo]
                //              solapa con [nuevo.debate_desde..nuevo.fecha_fallo]
                $exFallo = $c['fecha_fallo'] ?? '';
                if ($exFallo && $c['debate_desde'] <= $fecha_fallo_prop && $exFallo >= $desde) {
                    $juecesConfl[] = $c[$nomF];
                }
            }
        }

        $litConfl = $litPorAA[$c['aa_id_conflicto']] ?? [];
        if (empty($juecesConfl) && empty($litConfl)) continue;

        $conflictos[] = array_merge($c, [
            'jueces_conflicto'     => $juecesConfl,
            'litigantes_conflicto' => $litConfl,
        ]);
    }
    return $conflictos;
}

// ── Helpers UI ────────────────────────────────────────────────
function ordenLink(string $col, string $label, string $ord, string $dir): string
{
    $nd = ($ord === $col && $dir === 'ASC') ? 'DESC' : 'ASC';
    $p  = array_merge($_GET, ['orden' => $col, 'dir' => $nd, 'page' => 1]);
    $fl = $ord === $col ? ($dir === 'ASC' ? ' ▲' : ' ▼') : '';
    return "<a href='?" . http_build_query($p) . "'>$label$fl</a>";
}

function paginacion(int $page, int $total_pages): string
{
    if ($total_pages <= 1) return '';
    $get = $_GET;
    $mk  = fn(int $p, string $l, bool $a=false, bool $d=false) =>
        "<button onclick=\"location.href='?" . http_build_query(array_merge($get,['page'=>$p])) . "'\"" .
        ($a ? " class='on'" : "") . ($d ? " disabled" : "") . ">$l</button>";
    $h = '<div class="pg">';
    $h .= $mk(1,'«',false,$page<=1) . $mk(max(1,$page-1),'‹',false,$page<=1);
    for ($p=max(1,$page-2);$p<=min($total_pages,$page+2);$p++) $h .= $mk($p,"$p",$p===$page);
    $h .= $mk(min($total_pages,$page+1),'›',false,$page>=$total_pages) . $mk($total_pages,'»',false,$page>=$total_pages);
    $h .= '<span class="pgi"></span></div>';
    return $h;
}

function badgeEstadoImp(string $ei): string
{
    $m = ['Preso'=>'bp-p','En libertad'=>'bp-l','Rebelde'=>'bp-r','Internado'=>'bp-i'];
    return "<span class='bp " . ($m[$ei] ?? 'bp-l') . "'>$ei</span>";
}

function badgeCondicion(string $c): string
{
    return $c === 'SobreAgendado'
        ? "<span class='bj bj-s'>⚠️ Sobre-ag.</span>"
        : "<span class='bj bj-t'>Titular</span>";
}

function fmtFecha(?string $d): string
{
    return $d ? date('d/m/Y', strtotime($d)) : '—';
}

/**
 * Renderiza una celda con múltiples litigantes (uno por línea).
 * El string viene de GROUP_CONCAT con \n como separador.
 */
function celdaLitigantes(?string $nombres): string
{
    if (empty($nombres)) return '<span style="color:#94a3b8">—</span>';
    $items = explode("\n", $nombres);
    return implode('<br>', array_map('htmlspecialchars', $items));
}

/**
 * Verifica si el usuario en sesión tiene permiso para realizar $accion en $app.
 * Si mrbs_userApp está vacío o la app no está configurada → acceso total (setup inicial).
 */
function perm(string $app, string $accion = 'ver'): bool
{
    $level = (int)($_SESSION['userLevel'] ?? 0);
    if ($level <= 0) return false;
    if (empty($_SESSION['userApp'])) return true;
    $p = $_SESSION['userApp'][$app] ?? null;
    if ($p === null) return true;
    return $level >= (int)($p[$accion] ?? 99);
}
