<?php
date_default_timezone_set('America/La_Paz');
header('Content-Type: application/json; charset=UTF-8');

require 'db_connection.php';

// ─── Parámetros ──────────────────────────────────────────────────────────────
$today   = date('Y-m-d');
$month_s = date('Y-m-01');

$from = (isset($_GET['from']) && preg_match('/^\d{4}-\d{2}-\d{2}$/', $_GET['from']))
        ? $_GET['from'] : $month_s;
$to   = (isset($_GET['to'])   && preg_match('/^\d{4}-\d{2}-\d{2}$/', $_GET['to']))
        ? $_GET['to']   : $today;
$user      = (isset($_GET['user']) && $_GET['user'] !== '')
             ? $conn->real_escape_string($_GET['user']) : null;
$area_id   = (isset($_GET['area_id'])   && (int)$_GET['area_id']   > 0) ? (int)$_GET['area_id']   : null;
$region_id = (isset($_GET['region_id']) && (int)$_GET['region_id'] > 0) ? (int)$_GET['region_id'] : null;

if ($from > $to) { $tmp = $from; $from = $to; $to = $tmp; }

$EVT_SUCCESS = [4102, 4864, 4865, 4866, 4867, 4868];
$evt_in = implode(',', $EVT_SUCCESS);

// ─── Conexión local (cbn) para turnos y áreas ────────────────────────────────
$cbn = new mysqli('localhost', 'root', 'Tykun.2026', 'cbn');
$cbn->set_charset('utf8mb4');

// ─── Filtro por área o región ─────────────────────────────────────────────────
// Si se pide filtrar por área o región, resolvemos los USRIDs permitidos
$allowed_usrids = null; // null = sin filtro (todos)
if ($area_id || $region_id) {
    if ($area_id) {
        $r_ua = $cbn->query("SELECT usrid FROM user_areas WHERE area_id = $area_id");
    } else {
        $r_ua = $cbn->query(
            "SELECT ua.usrid FROM user_areas ua
             JOIN areas a ON ua.area_id = a.id
             WHERE a.region_id = $region_id"
        );
    }
    $allowed_usrids = [];
    if ($r_ua) {
        while ($ru = $r_ua->fetch_assoc()) $allowed_usrids[] = $ru['usrid'];
    }
    // Si no hay usuarios en ese área/región, devolvemos vacío de inmediato
    if (empty($allowed_usrids)) {
        $cbn->close();
        echo json_encode(['data' => [], 'total_records' => 0, 'from' => $from, 'to' => $to,
                          'filter_area_id' => $area_id, 'filter_region_id' => $region_id]);
        exit;
    }
}

// ─── Helper: resolver turno para un usuario en una fecha ─────────────────────
function resolve_shift(mysqli $cbn, string $usrid, string $date): ?array {
    $stmt = $cbn->prepare(
        "SELECT us.shift_id, us.cycle_id, us.assignment_type, us.valid_from
         FROM user_shifts us
         WHERE us.usrid = ?
           AND us.valid_from <= ?
           AND (us.valid_until IS NULL OR us.valid_until >= ?)
         ORDER BY us.valid_from DESC
         LIMIT 1"
    );
    $stmt->bind_param('sss', $usrid, $date, $date);
    $stmt->execute();
    $row = $stmt->get_result()->fetch_assoc();
    $stmt->close();
    if (!$row) return null;

    if ($row['assignment_type'] === 'fixed') {
        if (!$row['shift_id']) return null;
        $s = $cbn->query("SELECT id, name, start_time, end_time, tolerance_min, color FROM shifts WHERE id = " . (int)$row['shift_id'])->fetch_assoc();
        if (!$s) return null;
        $wd = (int)(new DateTime($date))->format('w');
        $scheduled = $cbn->query(
            "SELECT 1 FROM shift_schedules WHERE shift_id = {$s['id']} AND weekday = {$wd}"
        )->num_rows > 0;
        return ['shift' => $s, 'day_off' => !$scheduled, 'source' => 'fixed'];
    }

    if (!$row['cycle_id']) return null;
    $cycle = $cbn->query("SELECT id, name, cycle_days FROM shift_cycles WHERE id = " . (int)$row['cycle_id'])->fetch_assoc();
    if (!$cycle) return null;
    $from_dt = new DateTime($row['valid_from']);
    $cur_dt  = new DateTime($date);
    $diff    = (int)$from_dt->diff($cur_dt)->days;
    $offset  = $diff % (int)$cycle['cycle_days'];
    $slot = $cbn->query(
        "SELECT scs.shift_id, s.name, s.start_time, s.end_time, s.tolerance_min, s.color
         FROM shift_cycle_slots scs
         LEFT JOIN shifts s ON scs.shift_id = s.id
         WHERE scs.cycle_id = {$cycle['id']} AND scs.day_offset = {$offset}"
    )->fetch_assoc();
    if (!$slot) return null;
    if (!$slot['shift_id']) return ['shift' => null, 'day_off' => true, 'source' => 'cycle', 'cycle_name' => $cycle['name']];
    return [
        'shift'      => [
            'id'            => $slot['shift_id'],
            'name'          => $slot['name'],
            'start_time'    => $slot['start_time'],
            'end_time'      => $slot['end_time'],
            'tolerance_min' => $slot['tolerance_min'],
            'color'         => $slot['color'],
        ],
        'day_off'    => false,
        'source'     => 'cycle',
        'cycle_name' => $cycle['name'],
    ];
}

// ─── Helpers ─────────────────────────────────────────────────────────────────
function getMonthRange(string $from, string $to): array {
    $months = [];
    $start = new DateTime($from);
    $start->modify('first day of this month');
    $end = new DateTime($to);
    $end->modify('first day of this month');
    while ($start <= $end) {
        $months[] = $start->format('Ym');
        $start->modify('+1 month');
    }
    return $months;
}

function getVerifiedTables(array $months, $conn): array {
    $existing = [];
    foreach ($months as $ym) {
        $table = 't_lg' . $ym;
        $r = $conn->query("SHOW TABLES LIKE '$table'");
        if ($r && $r->num_rows > 0) $existing[] = $table;
    }
    return $existing;
}

// ─── Determinar tablas ────────────────────────────────────────────────────────
$months = getMonthRange($from, $to);
$tables = getVerifiedTables($months, $conn);

if (empty($tables)) {
    echo json_encode(['data' => [], 'total_records' => 0, 'from' => $from, 'to' => $to]);
    exit;
}

// ─── UNION ALL ────────────────────────────────────────────────────────────────
$parts = [];
foreach ($tables as $tbl) {
    $where  = "EVT IN ($evt_in)";
    $where .= " AND FROM_UNIXTIME(DEVDT) >= '$from 00:00:00'";
    $where .= " AND FROM_UNIXTIME(DEVDT) <= '$to 23:59:59'";
    if ($user) $where .= " AND USRID = '$user'";
    if ($allowed_usrids !== null) {
        $ids_escaped = implode(',', array_map(function($id) use ($conn) {
            return "'" . $conn->real_escape_string($id) . "'";
        }, $allowed_usrids));
        $where .= " AND USRID IN ($ids_escaped)";
    }
    $parts[] = "SELECT USRID, DEVDT FROM `$tbl` WHERE $where";
}
$union = implode(' UNION ALL ', $parts);

// ─── Consulta principal ───────────────────────────────────────────────────────
$sql = "
    SELECT
        sub.USRID                                                          AS usrid,
        u.NM                                                               AS nm,
        DATE(CONVERT_TZ(FROM_UNIXTIME(sub.DEVDT), '+00:00', '-04:00'))    AS day,
        FROM_UNIXTIME(MIN(sub.DEVDT))     AS entry_time,
        FROM_UNIXTIME(MAX(sub.DEVDT))     AS exit_time,
        ROUND((MAX(sub.DEVDT) - MIN(sub.DEVDT)) / 3600.0, 2)             AS hours_worked,
        COUNT(*)                                                           AS events_count
    FROM ($union) sub
    LEFT JOIN t_usr u ON sub.USRID = u.USRID
    GROUP BY sub.USRID, day
    ORDER BY day DESC, nm ASC
";

$result = $conn->query($sql);

$data = [];
if ($result) {
    while ($row = $result->fetch_assoc()) {
        $entry    = $row['entry_time'];
        $exit     = $row['exit_time'];
        $same     = ($entry === $exit);
        $entry_hms = $entry ? date('H:i:s', strtotime($entry)) : null;
        $exit_hms  = (!$same && $exit) ? date('H:i:s', strtotime($exit)) : null;

        $shift_info   = resolve_shift($cbn, $row['usrid'], $row['day']);
        $status       = 'no_shift';
        $minutes_late = null;

        if ($shift_info) {
            if ($shift_info['day_off']) {
                $status = 'day_off';
            } elseif (!$shift_info['shift']) {
                $status = 'no_shift';
            } elseif (!$entry_hms) {
                $status = 'absent';
            } else {
                $tol      = (int)$shift_info['shift']['tolerance_min'];
                $deadline = strtotime($row['day'] . ' ' . $shift_info['shift']['start_time']) + $tol * 60;
                $entry_ts = strtotime($row['day'] . ' ' . $entry_hms);
                if ($entry_ts <= $deadline) {
                    $status = 'on_time';
                } else {
                    $status       = 'late';
                    $minutes_late = max(0, (int)round(($entry_ts - $deadline) / 60));
                }
            }
        }

        $data[] = [
            'usrid'         => $row['usrid'],
            'nm'            => $row['nm'] ?? 'Desconocido',
            'date'          => $row['day'],
            'entry_time'    => $entry_hms,
            'exit_time'     => $exit_hms,
            'hours_worked'  => $same ? 0 : (float)$row['hours_worked'],
            'events_count'  => (int)$row['events_count'],
            'shift_name'    => $shift_info['shift']['name']       ?? null,
            'shift_start'   => $shift_info['shift']['start_time'] ?? null,
            'shift_end'     => $shift_info['shift']['end_time']   ?? null,
            'shift_color'   => $shift_info['shift']['color']      ?? null,
            'shift_source'  => $shift_info['source']              ?? null,
            'status'        => $status,
            'minutes_late'  => $minutes_late,
        ];
    }
}

$conn->close();
$cbn->close();

echo json_encode([
    'data'          => $data,
    'total_records' => count($data),
    'from'          => $from,
    'to'            => $to,
]);
