<?php
declare(strict_types=1);

ini_set('display_errors', '0');
error_reporting(0);

header('Content-Type: application/json; charset=utf-8');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type, Accept');

ob_start();

function respond(int $status_code, array $payload): void
{
    while (ob_get_level() > 0) {
        ob_end_clean();
    }

    http_response_code($status_code);
    echo json_encode($payload);
    exit;
}

if (($_SERVER['REQUEST_METHOD'] ?? '') === 'OPTIONS') {
    respond(204, []);
}

if (($_SERVER['REQUEST_METHOD'] ?? '') !== 'POST') {
    respond(405, [
        'success' => false,
        'message' => 'Method tidak dibenarkan.',
    ]);
}

require_once __DIR__ . '/../db.php';
require_once __DIR__ . '/../includes/push_service.php';

$raw = file_get_contents('php://input');
$payload = json_decode($raw ?: '', true);
if (!is_array($payload)) {
    $payload = $_POST;
}

$user_id = (int) ($payload['user_id'] ?? 0);
if ($user_id <= 0) {
    respond(422, [
        'success' => false,
        'message' => 'User tidak sah.',
    ]);
}

$user_stmt = mysqli_prepare($conn, 'SELECT id FROM users WHERE id = ? AND status = "approved" LIMIT 1');
if (!$user_stmt) {
    respond(500, [
        'success' => false,
        'message' => 'Ralat sistem semasa membaca pengguna.',
    ]);
}

mysqli_stmt_bind_param($user_stmt, 'i', $user_id);
mysqli_stmt_execute($user_stmt);
$user_result = mysqli_stmt_get_result($user_stmt);
if (!$user_result || !mysqli_fetch_assoc($user_result)) {
    respond(403, [
        'success' => false,
        'message' => 'Akaun tidak dibenarkan.',
    ]);
}

$action = strtolower(trim((string) ($payload['action'] ?? 'list')));

if ($action === 'register_device' || $action === 'register_push' || $action === 'register') {
    $token = trim((string) ($payload['token'] ?? ''));
    $platform = substr(strtolower(trim((string) ($payload['platform'] ?? 'unknown'))), 0, 20);
    $device_name = substr(trim((string) ($payload['device_name'] ?? '')), 0, 120);

    if ($token !== '' && strlen($token) <= 512) {
        $stmt = mysqli_prepare($conn, 'INSERT INTO push_devices (user_id, token, platform, device_name, enabled, updated_at) VALUES (?, ?, ?, ?, 1, NOW()) ON DUPLICATE KEY UPDATE platform = VALUES(platform), device_name = VALUES(device_name), enabled = 1, updated_at = NOW()');
        if ($stmt) {
            mysqli_stmt_bind_param($stmt, 'isss', $user_id, $token, $platform, $device_name);
            mysqli_stmt_execute($stmt);
        }
    }
    respond(200, ['success' => true, 'message' => 'Peranti sedia menerima notifikasi.']);
}

if ($action === 'send_push' || $action === 'push_send' || $action === 'send' || $action === 'notify') {
    $title = trim((string) ($payload['title'] ?? 'Notifikasi'));
    $body = trim((string) ($payload['body'] ?? $payload['message'] ?? ''));
    $data = is_array($payload['data'] ?? null) ? $payload['data'] : [];
    $target_ids_raw = $payload['target_user_ids'] ?? $payload['recipient_ids'] ?? $payload['user_ids'] ?? [];
    if (!is_array($target_ids_raw)) $target_ids_raw = [$payload['target_user_id'] ?? 0];

    require_once __DIR__ . '/../includes/push_service.php';
    $sent = 0;
    foreach ($target_ids_raw as $tid) {
        $id = (int) $tid;
        if ($id > 0) {
            $res = sendMainppPush($conn, $id, $title, $body, $data);
            $sent += (int) ($res['sent'] ?? 0);
        }
    }
    respond(200, ['success' => true, 'message' => "Notifikasi dihantar kepada $sent peranti.", 'sent' => $sent]);
}

function normalizeCalendarType(string $type): string
{
    $value = strtolower(trim($type));
    $value = str_replace('-', '_', $value);
    $allowed = ['task', 'meeting', 'event', 'leave', 'reminder', 'time_off'];
    return in_array($value, $allowed, true) ? $value : 'event';
}

function normalizeCalendarStatus(string $status, string $type): string
{
    $value = trim($status);
    if ($value !== '') {
        return substr($value, 0, 50);
    }

    return match ($type) {
        'task' => 'Pending',
        'meeting' => 'Confirmed',
        'leave', 'time_off' => 'Pending',
        'reminder' => 'Pending',
        default => 'Scheduled',
    };
}

function normalizeCalendarDateTime(string $value): ?string
{
    $trimmed = trim($value);
    if ($trimmed === '') {
        return null;
    }

    try {
        $date = new DateTime($trimmed);
        return $date->format('Y-m-d H:i:s');
    } catch (Throwable $exception) {
        return null;
    }
}

function calendarTimeLabel(array $row): string
{
    if ((int) ($row['is_full_day'] ?? 0) === 1) {
        return 'Full Day';
    }

    $start = trim((string) ($row['start_at'] ?? ''));
    $end = trim((string) ($row['end_at'] ?? ''));
    if ($start === '') {
        return '';
    }

    try {
        $start_date = new DateTime($start);
        if ($end !== '') {
            $end_date = new DateTime($end);
            if ($start_date->format('Y-m-d') === $end_date->format('Y-m-d')) {
                return $start_date->format('g:i A') . ' - ' . $end_date->format('g:i A');
            }
        }

        return $start_date->format('g:i A');
    } catch (Throwable $exception) {
        return $start;
    }
}

function calendarDateLabel(array $row): string
{
    $start = trim((string) ($row['start_at'] ?? ''));
    if ($start === '') {
        return '';
    }

    try {
        return (new DateTime($start))->format('Y-m-d');
    } catch (Throwable $exception) {
        return $start;
    }
}

function notifyLeaveRecipientsAndCreateEvents(
    mysqli $conn,
    int $sender_user_id,
    string $type,
    string $title,
    string $reason,
    string $start_at,
    string $end_at,
    bool $is_full_day,
    array $raw_recipient_ids,
    bool $notify_all_dept
): void {
    $sender_name = 'Rakan Sepasukan';
    $sender_dept = '';
    $sender_q = mysqli_prepare($conn, "SELECT fullname, short_name, department FROM users WHERE id = ? LIMIT 1");
    if ($sender_q) {
        mysqli_stmt_bind_param($sender_q, 'i', $sender_user_id);
        mysqli_stmt_execute($sender_q);
        $res = mysqli_stmt_get_result($sender_q);
        if ($res && $row = mysqli_fetch_assoc($res)) {
            $sender_name = !empty($row['fullname']) ? $row['fullname'] : (!empty($row['short_name']) ? $row['short_name'] : 'Rakan Sepasukan');
            $sender_dept = trim((string) ($row['department'] ?? ''));
        }
    }

    $recipient_ids = [];
    foreach ($raw_recipient_ids as $id) {
        $int_id = (int) $id;
        if ($int_id > 0 && $int_id !== $sender_user_id) {
            $recipient_ids[$int_id] = true;
        }
    }

    if ($notify_all_dept || empty($recipient_ids)) {
        if ($sender_dept !== '') {
            $dept_stmt = mysqli_prepare($conn, "SELECT id FROM users WHERE LOWER(TRIM(department)) = LOWER(TRIM(?)) AND id <> ? AND status = 'approved'");
            if ($dept_stmt) {
                mysqli_stmt_bind_param($dept_stmt, 'si', $sender_dept, $sender_user_id);
                mysqli_stmt_execute($dept_stmt);
                $dept_res = mysqli_stmt_get_result($dept_stmt);
                if ($dept_res) {
                    while ($r = mysqli_fetch_assoc($dept_res)) {
                        $recipient_ids[(int) $r['id']] = true;
                    }
                }
            }
        }
    }

    $target_ids = array_keys($recipient_ids);
    if (empty($target_ids)) return;

    $doc_type = ($type === 'leave' || str_contains($type, 'cuti')) ? 'Cuti Rehat' : 'Time Off';
    $date_str = date('d/m/Y', strtotime($start_at));
    $reason_str = trim($reason) !== '' ? trim($reason) : 'Tiada alasan';
    $event_title = "$doc_type ($sender_name)";
    $event_desc = "$sender_name mendaftar $doc_type pada $date_str ($reason_str).";

    $ins_stmt = mysqli_prepare(
        $conn,
        'INSERT INTO calendar_events
            (user_id, event_type, title, description, location, start_at, end_at, due_date, manday,
             is_full_day, priority, status, reason, participants, created_by, updated_by)
         VALUES (?, ?, ?, ?, "department_member", ?, ?, NULL, 0, ?, "Normal", "Approved", ?, ?, ?, ?)'
    );

    $push_title = "Makluman $doc_type Bahagian";
    $push_body = "$sender_name mendaftar $doc_type pada $date_str ($reason_str). Sila semak jadual pasukan.";
    $push_data = [
        'type' => 'leave_department_notify',
        'doc_type' => $doc_type,
        'applicant_id' => (string) $sender_user_id,
        'start_at' => $start_at,
    ];

    $participants_json = json_encode([$sender_name], JSON_UNESCAPED_UNICODE);
    $full_day_int = $is_full_day ? 1 : 0;

    foreach ($target_ids as $target_id) {
        try {
            if ($ins_stmt) {
                mysqli_stmt_bind_param(
                    $ins_stmt,
                    'isssssissii',
                    $target_id,
                    $type,
                    $event_title,
                    $event_desc,
                    $start_at,
                    $end_at,
                    $full_day_int,
                    $reason_str,
                    $participants_json,
                    $sender_user_id,
                    $sender_user_id
                );
                mysqli_stmt_execute($ins_stmt);
            }

            sendMainppPush($conn, (int) $target_id, $push_title, $push_body, $push_data);
        } catch (Throwable $e) {}
    }
}

function mapCalendarEvent(array $row): array
{
    $participants = [];
    $raw_participants = trim((string) ($row['participants'] ?? ''));
    if ($raw_participants !== '') {
        $decoded = json_decode($raw_participants, true);
        if (is_array($decoded)) {
            $participants = array_values(array_map('strval', $decoded));
        }
    }

    return [
        'id' => (int) ($row['id'] ?? 0),
        'userId' => (int) ($row['user_id'] ?? 0),
        'type' => (string) ($row['event_type'] ?? 'event'),
        'title' => (string) ($row['title'] ?? ''),
        'description' => (string) ($row['description'] ?? ''),
        'location' => (string) ($row['location'] ?? ''),
        'startAt' => (string) ($row['start_at'] ?? ''),
        'endAt' => (string) ($row['end_at'] ?? ''),
        'isFullDay' => ((int) ($row['is_full_day'] ?? 0)) === 1,
        'priority' => (string) ($row['priority'] ?? ''),
        'status' => (string) ($row['status'] ?? ''),
        'reason' => (string) ($row['reason'] ?? ''),
        'participants' => $participants,
        'dateLabel' => calendarDateLabel($row),
        'timeLabel' => calendarTimeLabel($row),
        'dueDate' => (string) ($row['due_date'] ?? ''),
        'manday' => (int) ($row['manday'] ?? 0),
        'createdAt' => (string) ($row['created_at'] ?? ''),
    ];
}

if ($action === 'participants') {
    $participants_stmt = mysqli_prepare(
        $conn,
        'SELECT id, fullname, short_name, email, department, position, profile_photo
         FROM users
         WHERE status = "approved"
         ORDER BY fullname ASC, short_name ASC'
    );

    if (!$participants_stmt) {
        respond(500, [
            'success' => false,
            'message' => 'Senarai pengguna tidak dapat dimuatkan.',
        ]);
    }

    mysqli_stmt_execute($participants_stmt);
    $participants_result = mysqli_stmt_get_result($participants_stmt);
    $participants = [];

    if ($participants_result) {
        while ($participant = mysqli_fetch_assoc($participants_result)) {
            $participants[] = [
                'id' => (int) ($participant['id'] ?? 0),
                'fullname' => (string) ($participant['fullname'] ?? ''),
                'short_name' => (string) ($participant['short_name'] ?? ''),
                'email' => (string) ($participant['email'] ?? ''),
                'department' => (string) ($participant['department'] ?? ''),
                'position' => (string) ($participant['position'] ?? ''),
                'profile_photo' => (string) ($participant['profile_photo'] ?? ''),
            ];
        }
    }

    respond(200, [
        'success' => true,
        'participants' => $participants,
    ]);
}

if ($action === 'update_status') {
    $event_id = (int) ($payload['event_id'] ?? $payload['eventId'] ?? 0);
    $status = strtolower(trim((string) ($payload['status'] ?? '')));
    $allowed_statuses = ['dump', 'ongoing', 'completed'];

    if ($event_id <= 0 || !in_array($status, $allowed_statuses, true)) {
        respond(422, [
            'success' => false,
            'message' => 'Status task tidak sah.',
        ]);
    }

    $stmt = mysqli_prepare(
        $conn,
        'UPDATE calendar_events
         SET status = ?, updated_by = ?, updated_at = NOW()
         WHERE id = ? AND user_id = ? AND event_type = "task" AND deleted_at IS NULL'
    );
    mysqli_stmt_bind_param($stmt, 'siii', $status, $user_id, $event_id, $user_id);
    mysqli_stmt_execute($stmt);

    if (mysqli_stmt_affected_rows($stmt) < 1) {
        respond(404, [
            'success' => false,
            'message' => 'Task tidak ditemui atau status telah dikemas kini.',
        ]);
    }

    respond(200, [
        'success' => true,
        'message' => 'Status task berjaya dikemas kini.',
    ]);
}

if ($action === 'update') {
    $event_id = (int) ($payload['event_id'] ?? $payload['eventId'] ?? 0);
    $title = trim((string) ($payload['title'] ?? ''));
    $description = trim((string) ($payload['description'] ?? ''));
    $reason = trim((string) ($payload['reason'] ?? ''));
    $location = trim((string) ($payload['location'] ?? ''));
    $start_at = normalizeCalendarDateTime((string) ($payload['start_at'] ?? $payload['startAt'] ?? ''));
    $end_at = normalizeCalendarDateTime((string) ($payload['end_at'] ?? $payload['endAt'] ?? ''));
    $priority = strtolower(trim((string) ($payload['priority'] ?? '')));
    $priority = in_array($priority, ['low', 'medium', 'high'], true) ? $priority : null;
    $due_date = normalizeCalendarDateTime((string) ($payload['due_date'] ?? $payload['dueDate'] ?? ''));
    $due_date = $due_date !== null ? substr($due_date, 0, 10) : null;
    $manday = max(0, (int) ($payload['manday'] ?? 0));
    $is_full_day = isset($payload['is_full_day']) ? (((bool) $payload['is_full_day']) ? 1 : 0) : null;

    $participants = null;
    if (isset($payload['participants']) && is_array($payload['participants'])) {
        $participants = json_encode(array_values(array_map('strval', $payload['participants'])), JSON_UNESCAPED_UNICODE);
    }

    if ($event_id <= 0) {
        respond(422, [
            'success' => false,
            'message' => 'Maklumat aktiviti tidak lengkap.',
        ]);
    }

    $stmt = mysqli_prepare(
        $conn,
        'UPDATE calendar_events
         SET title = IF(? = "", title, ?),
             description = IF(? = "", description, ?),
             reason = IF(? = "", reason, ?),
             location = IF(? = "", location, ?),
             start_at = IF(? IS NULL, start_at, ?),
             end_at = IF(? IS NULL, end_at, ?),
             due_date = IF(? IS NULL, due_date, ?),
             manday = IF(? = 0, manday, ?),
             priority = IF(? IS NULL, priority, ?),
             is_full_day = IF(? IS NULL, is_full_day, ?),
             participants = IF(? IS NULL, participants, ?),
             updated_by = ?, updated_at = NOW()
         WHERE id = ? AND user_id = ? AND deleted_at IS NULL'
    );
    mysqli_stmt_bind_param(
        $stmt,
        'sssssssssssssissssssiii',
        $title, $title,
        $description, $description,
        $reason, $reason,
        $location, $location,
        $start_at, $start_at,
        $end_at, $end_at,
        $due_date, $due_date,
        $manday, $manday,
        $priority, $priority,
        $is_full_day, $is_full_day,
        $participants, $participants,
        $user_id,
        $event_id,
        $user_id
    );
    mysqli_stmt_execute($stmt);

    $fetch = mysqli_prepare(
        $conn,
        'SELECT * FROM calendar_events
         WHERE id = ? AND user_id = ? AND deleted_at IS NULL
         LIMIT 1'
    );
    mysqli_stmt_bind_param($fetch, 'ii', $event_id, $user_id);
    mysqli_stmt_execute($fetch);
    $result = mysqli_stmt_get_result($fetch);
    $row = $result ? mysqli_fetch_assoc($result) : null;

    if (!$row) {
        respond(404, [
            'success' => false,
            'message' => 'Aktiviti tidak ditemui.',
        ]);
    }

    respond(200, [
        'success' => true,
        'message' => 'Aktiviti berjaya dikemas kini.',
        'event' => mapCalendarEvent($row),
    ]);
}

if ($action === 'delete') {
    $event_id = (int) ($payload['event_id'] ?? $payload['eventId'] ?? 0);
    if ($event_id <= 0) {
        respond(422, [
            'success' => false,
            'message' => 'Aktiviti tidak sah.',
        ]);
    }

    $stmt = mysqli_prepare(
        $conn,
        'UPDATE calendar_events
         SET deleted_at = NOW(), updated_by = ?, updated_at = NOW()
         WHERE id = ? AND user_id = ? AND deleted_at IS NULL'
    );
    mysqli_stmt_bind_param($stmt, 'iii', $user_id, $event_id, $user_id);
    mysqli_stmt_execute($stmt);

    respond(200, [
        'success' => true,
        'message' => 'Aktiviti berjaya dipadamkan.',
    ]);
}

if ($action === 'create') {
    $type = normalizeCalendarType((string) ($payload['type'] ?? 'event'));
    $title = trim((string) ($payload['title'] ?? ''));
    $description = trim((string) ($payload['description'] ?? ''));
    $location = trim((string) ($payload['location'] ?? ''));
    $start_at = normalizeCalendarDateTime((string) ($payload['start_at'] ?? $payload['startAt'] ?? ''));
    $end_at = normalizeCalendarDateTime((string) ($payload['end_at'] ?? $payload['endAt'] ?? ''));
    $is_full_day = !empty($payload['is_full_day']) || !empty($payload['isFullDay']) ? 1 : 0;
    $priority = strtolower(trim((string) ($payload['priority'] ?? '')));
    $priority = in_array($priority, ['low', 'medium', 'high'], true) ? $priority : null;
    $due_date = normalizeCalendarDateTime((string) ($payload['due_date'] ?? $payload['dueDate'] ?? ''));
    $due_date = $due_date !== null ? substr($due_date, 0, 10) : null;
    $manday = max(0, (int) ($payload['manday'] ?? 0));
    $status = normalizeCalendarStatus((string) ($payload['status'] ?? ''), $type);
    $reason = trim((string) ($payload['reason'] ?? ''));
    $participants = $payload['participants'] ?? [];
    $participants_json = is_array($participants)
        ? json_encode(array_values(array_map('strval', $participants)))
        : null;

    if ($title === '') {
        respond(422, [
            'success' => false,
            'message' => 'Tajuk calendar diperlukan.',
        ]);
    }

    if ($start_at === null) {
        respond(422, [
            'success' => false,
            'message' => 'Tarikh mula tidak sah.',
        ]);
    }

    if ($type === 'task' && $due_date === null) {
        respond(422, [
            'success' => false,
            'message' => 'Due Date task diperlukan.',
        ]);
    }

    $stmt = mysqli_prepare(
        $conn,
        'INSERT INTO calendar_events
            (user_id, event_type, title, description, location, start_at, end_at, due_date, manday,
             is_full_day, priority, status, reason, participants, created_by, updated_by)
         VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)'
    );

    if (!$stmt) {
        respond(500, [
            'success' => false,
            'message' => 'Ralat sistem semasa menyediakan calendar.',
        ]);
    }

    mysqli_stmt_bind_param(
        $stmt,
        'isssssssiissssii',
        $user_id,
        $type,
        $title,
        $description,
        $location,
        $start_at,
        $end_at,
        $due_date,
        $manday,
        $is_full_day,
        $priority,
        $status,
        $reason,
        $participants_json,
        $user_id,
        $user_id
    );

    if (!mysqli_stmt_execute($stmt)) {
        respond(500, [
            'success' => false,
            'message' => 'Calendar gagal disimpan.',
        ]);
    }

    $event_id = (int) mysqli_insert_id($conn);

    if ($type === 'meeting' && is_array($participants) && !empty($participants)) {
        $date_label = date('d M Y, g:i A', strtotime((string) $start_at));
        sendMainppPushToParticipantLabels(
            $conn,
            $participants,
            $user_id,
            'Jemputan meeting baharu',
            $title . ' - ' . $date_label,
            [
                'type' => 'meeting',
                'event_id' => $event_id,
                'route' => 'calendar',
            ]
        );
    }

    if ($type === 'leave' || $type === 'time_off') {
        try {
            $recipient_ids_raw = $payload['recipient_ids'] ?? $payload['target_user_ids'] ?? $payload['user_ids'] ?? [];
            if (!is_array($recipient_ids_raw)) $recipient_ids_raw = [];
            $notify_all_dept = !empty($payload['notify_all_department']);

            notifyLeaveRecipientsAndCreateEvents(
                $conn,
                $user_id,
                $type,
                $title,
                $reason,
                (string) $start_at,
                (string) $end_at,
                $is_full_day === 1,
                $recipient_ids_raw,
                $notify_all_dept
            );
        } catch (Throwable $e) {}
    }

    $fetch = mysqli_prepare($conn, 'SELECT * FROM calendar_events WHERE id = ? AND user_id = ? LIMIT 1');
    mysqli_stmt_bind_param($fetch, 'ii', $event_id, $user_id);
    mysqli_stmt_execute($fetch);
    $result = mysqli_stmt_get_result($fetch);
    $row = $result ? mysqli_fetch_assoc($result) : null;

    respond(200, [
        'success' => true,
        'message' => 'Calendar berjaya disimpan.',
        'event' => $row ? mapCalendarEvent($row) : null,
    ]);
}

if ($action === 'notify_leave') {
    $sender_id = (int) ($payload['user_id'] ?? $payload['sender_user_id'] ?? 0);
    $type = strtolower(trim((string) ($payload['type'] ?? $payload['doc_type'] ?? 'leave')));
    $type = str_contains($type, 'time') ? 'time_off' : 'leave';
    $reason = trim((string) ($payload['reason'] ?? $payload['body'] ?? ''));
    $start_at = normalizeCalendarDateTime((string) ($payload['start_at'] ?? $payload['startAt'] ?? date('Y-m-d H:i:s')));
    $end_at = normalizeCalendarDateTime((string) ($payload['end_at'] ?? $payload['endAt'] ?? $start_at));
    $is_full_day = $type === 'leave';
    $recipient_ids_raw = $payload['recipient_ids'] ?? $payload['target_user_ids'] ?? $payload['user_ids'] ?? [];
    if (!is_array($recipient_ids_raw)) $recipient_ids_raw = [];
    $notify_all_dept = !empty($payload['notify_all_department']);

    if ($sender_id > 0) {
        notifyLeaveRecipientsAndCreateEvents(
            $conn,
            $sender_id,
            $type,
            $type === 'leave' ? 'Cuti Rehat' : 'Time Off',
            $reason,
            (string) $start_at,
            (string) $end_at,
            $is_full_day,
            $recipient_ids_raw,
            $notify_all_dept
        );
    }

    respond(200, [
        'success' => true,
        'message' => 'Notifikasi cuti berjaya dihantar kepada penerima.',
    ]);
}

$stmt = mysqli_prepare(
    $conn,
    'SELECT * FROM calendar_events
     WHERE user_id = ? AND deleted_at IS NULL
     ORDER BY start_at ASC, id ASC'
);
if (!$stmt) {
    respond(500, [
        'success' => false,
        'message' => 'Ralat sistem semasa membaca calendar.',
    ]);
}

mysqli_stmt_bind_param($stmt, 'i', $user_id);
mysqli_stmt_execute($stmt);
$result = mysqli_stmt_get_result($stmt);
$events = [];
while ($row = $result ? mysqli_fetch_assoc($result) : null) {
    $events[] = mapCalendarEvent($row);
}

respond(200, [
    'success' => true,
    'message' => 'Calendar berjaya dimuatkan.',
    'events' => $events,
]);
