<?php
/**
 * ganancias.php — Reporte de Ganancias por Distribuidor (Panel Admin)
 * Usa exactamente la misma lógica que /network/reporte.php de la app.
 *
 * GET  ?mes=2&anio=2026          → resumen de todos los calificados con sus ganancias
 * GET  ?mes=2&anio=2026&id=12345 → detalle completo de un distribuidor específico
 */
header('Content-Type: application/json; charset=utf-8');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type, Authorization');
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') { http_response_code(200); exit; }

require_once __DIR__ . '/../config.php';

// ── Autenticación por token Bearer ───────────────────────────────────────────
$headers    = getallheaders();
$authHeader = $headers['Authorization'] ?? $headers['authorization'] ?? '';
$token      = str_replace('Bearer ', '', $authHeader);

if (empty($token)) {
    http_response_code(401);
    echo json_encode(['success' => false, 'message' => 'Token requerido']);
    exit;
}

$db  = getDB();
$now = date('Y-m-d H:i:s');
$stmt = $db->prepare(
    "SELECT s.idusuarios_sist FROM admin_sessions s
     WHERE s.token = ? AND s.expira > ? LIMIT 1"
);
$stmt->execute([$token, $now]);
if (!$stmt->fetch()) {
    http_response_code(401);
    echo json_encode(['success' => false, 'message' => 'Sesión expirada o inválida']);
    exit;
}

// ── Parámetros ───────────────────────────────────────────────────────────────
$anio    = isset($_GET['anio']) ? (int)$_GET['anio'] : (int)date('Y');
$mes     = isset($_GET['mes'])  ? (int)$_GET['mes']  : (int)date('m');
$idInver = isset($_GET['id'])   ? (int)$_GET['id']   : null;

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

// ── Constantes de negocio (igual que reporte.php) ───────────────────────────
$MAX_NIVELES = 13;
$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,
];

// ── Función: calcular ganancias de un distribuidor ───────────────────────────
function calcularGanancias($db, $idinv, $mesInicio, $mesFin, $MAX_NIVELES, $PORCENTAJES) {
    // 1. Puntos propios del período
    $stmtPropios = $db->prepare(
        "SELECT COALESCE(SUM(d.puntos), 0) AS puntos_propios
         FROM transacciones t
         JOIN depositos d ON t.idtransacciones = d.transacciones_idtransacciones
         WHERE t.inversionista_id_inver = ?
           AND (t.tipostr_idtipostr = 10 OR t.tipostr_idtipostr = 12)
           AND t.fechat BETWEEN ? AND ?"
    );
    $stmtPropios->execute([$idinv, $mesInicio, $mesFin]);
    $puntosPropios = (float)($stmtPropios->fetch(PDO::FETCH_ASSOC)['puntos_propios'] ?? 0);

    // 2. Calificación
    if ($puntosPropios < 624) {
        $calificacion = 'no_calificado';
    } elseif ($puntosPropios < 1500) {
        $calificacion = 'parcial';
    } else {
        $calificacion = 'calificado';
    }

    // 3. Directos calificados
    $stmtDirectos = $db->prepare(
        "SELECT i2.id_inver,
                COALESCE(SUM(d.puntos), 0) AS puntos
         FROM inversionista i2
         LEFT JOIN transacciones t ON t.inversionista_id_inver = i2.id_inver
             AND (t.tipostr_idtipostr = 10 OR t.tipostr_idtipostr = 12)
             AND t.fechat BETWEEN ? AND ?
         LEFT JOIN depositos d ON t.idtransacciones = d.transacciones_idtransacciones
         WHERE i2.idprom = ?
         GROUP BY i2.id_inver"
    );
    $stmtDirectos->execute([$mesInicio, $mesFin, $idinv]);
    $directosData = $stmtDirectos->fetchAll(PDO::FETCH_ASSOC);

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

    // 4. Niveles abiertos
    if ($calificacion === 'no_calificado') {
        $nivelesAbiertos = 0;
    } elseif ($calificacion === 'parcial') {
        $nivelesAbiertos = ($directos624 >= 1) ? 1 : 0;
    } else {
        $nivelesBase = $directos624;
        if ($directos1500 >= 3) {
            $nivelesEspecial = 5;
        } elseif ($directos1500 >= 2) {
            $nivelesEspecial = 3;
        } else {
            $nivelesEspecial = 0;
        }
        $nivelesAbiertos = min(max($nivelesBase, $nivelesEspecial), $MAX_NIVELES);
    }

    // 5. Puntos por nivel (red del distribuidor hasta nivel 13)
    $puntosNivel = array_fill(1, $MAX_NIVELES, 0.0);

    // Recorrer la red nivel por nivel usando BFS
    $nivelActual = [$idinv];
    for ($n = 1; $n <= $MAX_NIVELES && !empty($nivelActual); $n++) {
        if (empty($nivelActual)) break;

        $placeholders = implode(',', array_fill(0, count($nivelActual), '?'));
        $params       = array_merge([$mesInicio, $mesFin], $nivelActual);

        $stmtNivel = $db->prepare(
            "SELECT i2.id_inver,
                    COALESCE(SUM(d.puntos), 0) AS puntos
             FROM inversionista i2
             LEFT JOIN transacciones t ON t.inversionista_id_inver = i2.id_inver
                 AND (t.tipostr_idtipostr = 10 OR t.tipostr_idtipostr = 12)
                 AND t.fechat BETWEEN ? AND ?
             LEFT JOIN depositos d ON t.idtransacciones = d.transacciones_idtransacciones
             WHERE i2.idprom IN ($placeholders)
             GROUP BY i2.id_inver"
        );
        $stmtNivel->execute($params);
        $personas = $stmtNivel->fetchAll(PDO::FETCH_ASSOC);

        $nivelActual = [];
        foreach ($personas as $p) {
            $puntosNivel[$n] += (float)$p['puntos'];
            $nivelActual[]    = (int)$p['id_inver'];
        }
    }

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

    for ($n = 1; $n <= $MAX_NIVELES; $n++) {
        $pts      = $puntosNivel[$n];
        $pct      = $PORCENTAJES[$n] ?? 0.01;
        $generado = $pts * $pct;
        $recibir  = ($n <= $nivelesAbiertos) ? $generado : 0.0;
        $totalGenerado += $generado;
        $totalRecibir  += $recibir;
        $tablaGanancias[] = [
            'nivel'      => $n,
            'porcentaje' => $pct * 100,
            'puntos'     => round($pts, 0),
            'generado'   => round($generado, 2),
            'recibir'    => round($recibir, 2),
            'abierto'    => ($n <= $nivelesAbiertos),
        ];
    }

    return [
        'puntos_propios'   => $puntosPropios,
        'calificacion'     => $calificacion,
        'directos_624'     => $directos624,
        'directos_1500'    => $directos1500,
        'niveles_abiertos' => $nivelesAbiertos,
        'tabla_ganancias'  => $tablaGanancias,
        'total_generado'   => round($totalGenerado, 2),
        'total_recibir'    => round($totalRecibir, 2),
    ];
}

try {
    // ── Modo detalle: un solo distribuidor ──────────────────────────────────
    if ($idInver !== null) {
        // Obtener datos básicos del distribuidor
        $stmtInv = $db->prepare(
            "SELECT id_inver, referencia, rfc,
                    TRIM(CONCAT(nombre, ' ', appat, ' ', COALESCE(apmat,''))) AS nombre_completo
             FROM inversionista WHERE id_inver = ? LIMIT 1"
        );
        $stmtInv->execute([$idInver]);
        $inv = $stmtInv->fetch(PDO::FETCH_ASSOC);
        if (!$inv) {
            http_response_code(404);
            echo json_encode(['success' => false, 'message' => 'Distribuidor no encontrado']);
            exit;
        }

        $ganancias = calcularGanancias($db, $idInver, $mesInicio, $mesFin, $MAX_NIVELES, $PORCENTAJES);

        echo json_encode(array_merge(
            ['success' => true, 'mes' => $mes, 'anio' => $anio,
             'fechaInicio' => $mesInicio, 'fechaFin' => $mesFin],
            $inv,
            $ganancias
        ), JSON_UNESCAPED_UNICODE);
        exit;
    }

    // ── Modo listado: todos los calificados del mes ──────────────────────────
    // Obtener todos los distribuidores con >= 624 puntos en el período
    $stmtCal = $db->prepare(
        "SELECT i.id_inver, i.referencia, i.rfc,
                TRIM(CONCAT(i.nombre, ' ', i.appat, ' ', COALESCE(i.apmat,''))) AS nombre_completo,
                SUM(d.puntos) AS puntos_propios
         FROM transacciones t
         JOIN depositos d ON t.idtransacciones = d.transacciones_idtransacciones
         JOIN inversionista i ON t.inversionista_id_inver = i.id_inver
         WHERE (t.tipostr_idtipostr = 10 OR t.tipostr_idtipostr = 12)
           AND t.fechat BETWEEN :inicio AND :fin
         GROUP BY i.id_inver, i.referencia, i.rfc, i.nombre, i.appat, i.apmat
         HAVING SUM(d.puntos) >= 624
         ORDER BY SUM(d.puntos) DESC"
    );
    $stmtCal->execute([':inicio' => $mesInicio, ':fin' => $mesFin]);
    $calificados = $stmtCal->fetchAll(PDO::FETCH_ASSOC);

    $totalRecibir   = 0.0;
    $totalGenerado  = 0.0;
    $resultados     = [];

    foreach ($calificados as $inv) {
        $idinv     = (int)$inv['id_inver'];
        $puntosPropios = (float)$inv['puntos_propios'];

        // Calificación
        if ($puntosPropios < 1500) {
            $calificacion = 'parcial';
        } else {
            $calificacion = 'calificado';
        }

        // Directos calificados (simplificado para el listado)
        $stmtDir = $db->prepare(
            "SELECT COALESCE(SUM(d.puntos), 0) AS puntos
             FROM inversionista i2
             LEFT JOIN transacciones t ON t.inversionista_id_inver = i2.id_inver
                 AND (t.tipostr_idtipostr = 10 OR t.tipostr_idtipostr = 12)
                 AND t.fechat BETWEEN ? AND ?
             LEFT JOIN depositos d ON t.idtransacciones = d.transacciones_idtransacciones
             WHERE i2.idprom = ?
             GROUP BY i2.id_inver
             HAVING COALESCE(SUM(d.puntos), 0) >= 624"
        );
        $stmtDir->execute([$mesInicio, $mesFin, $idinv]);
        $directosRows = $stmtDir->fetchAll(PDO::FETCH_ASSOC);
        $directos624  = count($directosRows);

        $stmtDir1500 = $db->prepare(
            "SELECT COALESCE(SUM(d.puntos), 0) AS puntos
             FROM inversionista i2
             LEFT JOIN transacciones t ON t.inversionista_id_inver = i2.id_inver
                 AND (t.tipostr_idtipostr = 10 OR t.tipostr_idtipostr = 12)
                 AND t.fechat BETWEEN ? AND ?
             LEFT JOIN depositos d ON t.idtransacciones = d.transacciones_idtransacciones
             WHERE i2.idprom = ?
             GROUP BY i2.id_inver
             HAVING COALESCE(SUM(d.puntos), 0) >= 1500"
        );
        $stmtDir1500->execute([$mesInicio, $mesFin, $idinv]);
        $directos1500 = count($stmtDir1500->fetchAll());

        // Niveles abiertos
        if ($calificacion === 'parcial') {
            $nivelesAbiertos = ($directos624 >= 1) ? 1 : 0;
        } else {
            $nivelesBase = $directos624;
            if ($directos1500 >= 3) {
                $nivelesEspecial = 5;
            } elseif ($directos1500 >= 2) {
                $nivelesEspecial = 3;
            } else {
                $nivelesEspecial = 0;
            }
            $nivelesAbiertos = min(max($nivelesBase, $nivelesEspecial), $MAX_NIVELES);
        }

        // Calcular ganancias de todos los niveles con BFS
        $puntosNivelLista = array_fill(1, $MAX_NIVELES, 0.0);
        $nivelActualLista = [$idinv];
        for ($n = 1; $n <= $MAX_NIVELES && !empty($nivelActualLista); $n++) {
            $phs    = implode(',', array_fill(0, count($nivelActualLista), '?'));
            $params = array_merge([$mesInicio, $mesFin], $nivelActualLista);
            $stmtNL = $db->prepare(
                "SELECT i2.id_inver, COALESCE(SUM(d.puntos), 0) AS puntos
                 FROM inversionista i2
                 LEFT JOIN transacciones t ON t.inversionista_id_inver = i2.id_inver
                     AND (t.tipostr_idtipostr = 10 OR t.tipostr_idtipostr = 12)
                     AND t.fechat BETWEEN ? AND ?
                 LEFT JOIN depositos d ON t.idtransacciones = d.transacciones_idtransacciones
                 WHERE i2.idprom IN ($phs)
                 GROUP BY i2.id_inver"
            );
            $stmtNL->execute($params);
            $personasL = $stmtNL->fetchAll(PDO::FETCH_ASSOC);
            $nivelActualLista = [];
            foreach ($personasL as $p) {
                $puntosNivelLista[$n] += (float)$p['puntos'];
                $nivelActualLista[]    = (int)$p['id_inver'];
            }
        }

        // Calcular ganancia N1 y ganancia total
        $gananciaEstimada   = 0.0;
        $gananciaTotalLista = 0.0;
        for ($n = 1; $n <= $MAX_NIVELES; $n++) {
            if ($n > $nivelesAbiertos) break;
            $pct = $PORCENTAJES[$n] ?? 0.01;
            $gan = $puntosNivelLista[$n] * $pct;
            if ($n === 1) $gananciaEstimada = $gan;
            $gananciaTotalLista += $gan;
        }

        $totalRecibir += $gananciaTotalLista;

        $resultados[] = [
            'id_inver'        => $idinv,
            'referencia'      => $inv['referencia'],
            'rfc'             => $inv['rfc'],
            'nombre_completo' => trim($inv['nombre_completo']),
            'puntos_propios'  => round($puntosPropios, 0),
            'calificacion'    => $calificacion,
            'directos_624'    => $directos624,
            'directos_1500'   => $directos1500,
            'niveles_abiertos'=> $nivelesAbiertos,
            'ganancia_n1'     => round($gananciaEstimada, 2),
            'ganancia_total'  => round($gananciaTotalLista, 2),
        ];
    }

    echo json_encode([
        'success'          => true,
        'mes'              => $mes,
        'anio'             => $anio,
        'fechaInicio'      => $mesInicio,
        'fechaFin'         => $mesFin,
        'total'            => count($resultados),
        'total_a_pagar'    => round($totalRecibir, 2),
        'distribuidores'   => $resultados,
    ], JSON_UNESCAPED_UNICODE);

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