<?php
/**
 * distribuidor-reporte-red.php
 * GET ?id={id_inver}&anio={anio}&mes={mes}
 * Devuelve el reporte de red de un distribuidor para el período indicado.
 *
 * Columnas verificadas contra archivos funcionales del proyecto:
 *   transacciones : idtransacciones, inversionista_id_inver, fechat, tipostr_idtipostr
 *   depositos     : transacciones_idtransacciones, puntos
 *   inversionista : id_inver, idprom, referencia, nombre, appat, apmat, rfc
 */
header('Content-Type: application/json; charset=utf-8');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Headers: Authorization, Content-Type');
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') { http_response_code(204); exit; }

require_once __DIR__ . '/../../config.php';
$db = getDB();
$db->exec("SET NAMES utf8mb4");

$idinv = isset($_GET['id'])   ? (int)$_GET['id']   : 0;
$anio  = isset($_GET['anio']) ? (int)$_GET['anio'] : (int)date('Y');
$mes   = isset($_GET['mes'])  ? (int)$_GET['mes']  : (int)date('m');

if ($idinv <= 0) {
    http_response_code(400);
    echo json_encode(['ok' => false, 'error' => 'id_inver requerido']);
    exit;
}

$mesInicio = sprintf('%04d-%02d-01', $anio, $mes);
$mesFin    = date('Y-m-t', strtotime($mesInicio));

$MAX_NIVELES = 18;

$PORCENTAJES = [
    1  => 0.10,
    2  => 0.17,
    3  => 0.17,
    4  => 0.17,
    5  => 0.01,
    6  => 0.01,
    7  => 0.01,
    8  => 0.01,
    9  => 0.01,
    10 => 0.01,
    11 => 0.01,
    12 => 0.01,
    13 => 0.01,
    14 => 0.01,
    15 => 0.01,
    16 => 0.01,
    17 => 0.01,
    18 => 0.01,
];

try {
    // ── BFS: construir red de 18 niveles ────────────────────────────────────────
    // Recorremos la red usando idprom (patrocinador) de la tabla inversionista.
    // Para cada nivel obtenemos los distribuidores cuyo idprom está en el nivel anterior,
    // y sumamos sus puntos del período via transacciones + depositos.
    $currentLevel = [$idinv];
    $niveles      = [];
    $allIds       = [$idinv]; // para evitar ciclos
    $directosData = []; // nivel 1: [{id_inver, puntos}]

    for ($nivel = 1; $nivel <= $MAX_NIVELES; $nivel++) {
        if (empty($currentLevel)) break;

        $placeholders = implode(',', array_fill(0, count($currentLevel), '?'));

        // Obtener todos los distribuidores del siguiente nivel (idprom IN currentLevel)
        // y sumar sus puntos del período (tipos 10, 11, 12)
        $stmt = $db->prepare(
            "SELECT
                i.id_inver,
                i.referencia,
                i.nombre,
                i.appat,
                i.apmat,
                COALESCE(SUM(d.puntos), 0) AS puntos
             FROM inversionista i
             LEFT JOIN transacciones t
                ON t.inversionista_id_inver = i.id_inver
                AND t.fechat BETWEEN ? AND ?
                AND t.tipostr_idtipostr IN (10, 11, 12)
             LEFT JOIN depositos d
                ON d.transacciones_idtransacciones = t.idtransacciones
             WHERE i.idprom IN ($placeholders)
             GROUP BY i.id_inver, i.referencia, i.nombre, i.appat, i.apmat
             ORDER BY puntos DESC, i.appat ASC, i.nombre ASC"
        );

        $params = array_merge([$mesInicio, $mesFin], $currentLevel);
        $stmt->execute($params);
        $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

        $nextLevel         = [];
        $personasConPuntos = [];
        $totalPuntos       = 0.0;

        foreach ($rows as $row) {
            $id = (int)$row['id_inver'];
            if (in_array($id, $allIds, true)) continue; // evitar ciclos
            $allIds[]    = $id;
            $nextLevel[] = $id;

            $puntos = (float)$row['puntos'];

            if ($nivel === 1) {
                $directosData[] = ['id_inver' => $id, 'puntos' => $puntos];
            }

            if ($puntos > 0) {
                $personasConPuntos[] = [
                    'id_inver'        => $id,
                    'referencia'      => $row['referencia'] ?? '',
                    'nombre_completo' => trim(
                        ($row['nombre'] ?? '') . ' ' .
                        ($row['appat']  ?? '') . ' ' .
                        ($row['apmat']  ?? '')
                    ),
                    'puntos' => $puntos,
                ];
                $totalPuntos += $puntos;
            }
        }

        if (!empty($personasConPuntos)) {
            $niveles[$nivel] = [
                'nivel'          => $nivel,
                'personas'       => $personasConPuntos,
                'total_personas' => count($personasConPuntos),
                'total_puntos'   => $totalPuntos,
            ];
        }

        $currentLevel = $nextLevel;
    }

    // ── Totales generales ────────────────────────────────────────────────────────
    $totalPersonas      = 0;
    $totalPuntosGeneral = 0.0;
    foreach ($niveles as $n) {
        $totalPersonas      += $n['total_personas'];
        $totalPuntosGeneral += $n['total_puntos'];
    }

    // ── Puntos propios del período ───────────────────────────────────────────────
    $stmtPropios = $db->prepare(
        "SELECT COALESCE(SUM(d.puntos), 0) AS puntos_propios
         FROM transacciones t
         JOIN depositos d ON d.transacciones_idtransacciones = t.idtransacciones
         WHERE t.inversionista_id_inver = ?
           AND t.fechat BETWEEN ? AND ?
           AND t.tipostr_idtipostr IN (10, 11, 12)"
    );
    $stmtPropios->execute([$idinv, $mesInicio, $mesFin]);
    $rowPropios    = $stmtPropios->fetch(PDO::FETCH_ASSOC);
    $puntosPropios = (float)($rowPropios['puntos_propios'] ?? 0);

    // ── Calificación ─────────────────────────────────────────────────────────────
    // < 624: no calificado | 624–1499: parcial | >= 1500: calificado
    if ($puntosPropios < 624) {
        $calificacion = 'no_calificado';
    } elseif ($puntosPropios < 1500) {
        $calificacion = 'parcial';
    } else {
        $calificacion = 'calificado';
    }

    // ── Directos calificados ─────────────────────────────────────────────────────
    $directos624  = 0;
    $directos1500 = 0;
    foreach ($directosData as $d) {
        if ($d['puntos'] >= 624)  $directos624++;
        if ($d['puntos'] >= 1500) $directos1500++;
    }

    // ── Niveles abiertos ─────────────────────────────────────────────────────────
    // No calificado  : 0 niveles
    // Parcial        : máx 1 nivel, solo si tiene ≥1 directo con 624+
    // Calificado     :
    //   Base         : 1 nivel por cada directo con 624+
    //   Especial     : 2 directos con 1500+ → 3 niveles; 3 directos con 1500+ → 5 niveles
    //   Para nivel 6+: necesita N directos con 624+ (N = número del nivel)
    //   Máximo       : 18 niveles
    $nivelesAbiertos = 0;

    if ($calificacion === 'no_calificado') {
        $nivelesAbiertos = 0;

    } elseif ($calificacion === 'parcial') {
        $nivelesAbiertos = ($directos624 >= 1) ? 1 : 0;

    } else {
        // Calificado completo
        $nivelesBase = $directos624;

        if ($directos1500 >= 3) {
            $nivelesEspecial = 5;
        } elseif ($directos1500 >= 2) {
            $nivelesEspecial = 3;
        } else {
            $nivelesEspecial = 0;
        }

        $nivelesAbiertos = min(max($nivelesBase, $nivelesEspecial), $MAX_NIVELES);
    }

    // ── Tabla de ganancias ───────────────────────────────────────────────────────
    $tablaGanancias = [];
    $totalGenerado  = 0.0;
    $totalRecibir   = 0.0;

    for ($n = 1; $n <= $MAX_NIVELES; $n++) {
        $puntosNivel = isset($niveles[$n]) ? (float)$niveles[$n]['total_puntos'] : 0.0;
        $porcentaje  = $PORCENTAJES[$n] ?? 0.01;
        $generado    = $puntosNivel * $porcentaje;
        $recibir     = ($n <= $nivelesAbiertos) ? $generado : 0.0;

        $totalGenerado += $generado;
        $totalRecibir  += $recibir;

        $tablaGanancias[] = [
            'nivel'      => $n,
            'porcentaje' => $porcentaje * 100,
            'puntos'     => $puntosNivel,
            'generado'   => round($generado, 2),
            'recibir'    => round($recibir, 2),
            'abierto'    => ($n <= $nivelesAbiertos),
        ];
    }

    echo json_encode([
        'ok'      => true,
        'periodo' => [
            'anio'   => $anio,
            'mes'    => $mes,
            'inicio' => $mesInicio,
            'fin'    => $mesFin,
        ],
        'puntos_propios'      => $puntosPropios,
        'calificacion'        => $calificacion,
        'directos_624'        => $directos624,
        'directos_1500'       => $directos1500,
        'niveles_abiertos'    => $nivelesAbiertos,
        'niveles'             => array_values($niveles),
        'total_personas'      => $totalPersonas,
        'total_puntos'        => $totalPuntosGeneral,
        'tabla_ganancias'     => $tablaGanancias,
        'total_generado'      => round($totalGenerado, 2),
        'total_recibir'       => round($totalRecibir, 2),
    ], JSON_UNESCAPED_UNICODE);

} catch (Throwable $e) {
    http_response_code(500);
    echo json_encode([
        'ok'    => false,
        'error' => 'Error interno: ' . $e->getMessage(),
    ], JSON_UNESCAPED_UNICODE);
}
