<?php
/**
 * Audit log for personalliggare (attendance corrections and traceability).
 *
 * @package Maca_Menu_List
 */

if (!defined('ABSPATH')) {
    exit;
}

/**
 * Attendance log table name.
 *
 * @return string
 */
function maca_menulist_db_attendance_log_table() {
    global $wpdb;

    return $wpdb->prefix . 'maca_attendance_log';
}

/**
 * Create attendance log table.
 *
 * @return void
 */
function maca_menulist_db_create_attendance_log_table() {
    global $wpdb;

    if (!isset($wpdb) || empty($wpdb)) {
        return;
    }

    $table = maca_menulist_db_attendance_log_table();
    $charset_collate = $wpdb->get_charset_collate();

    $sql = "CREATE TABLE $table (
        id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
        event_id bigint(20) unsigned NOT NULL DEFAULT 0,
        employee_id bigint(20) unsigned NOT NULL DEFAULT 0,
        action varchar(32) NOT NULL DEFAULT 'created',
        summary text DEFAULT NULL,
        changes longtext DEFAULT NULL,
        actor_type varchar(16) NOT NULL DEFAULT 'system',
        actor_id bigint(20) unsigned NOT NULL DEFAULT 0,
        actor_label varchar(255) DEFAULT NULL,
        created_at datetime DEFAULT CURRENT_TIMESTAMP,
        PRIMARY KEY  (id),
        KEY event_id (event_id),
        KEY employee_id (employee_id),
        KEY created_at (created_at)
    ) $charset_collate;";

    require_once ABSPATH . 'wp-admin/includes/upgrade.php';
    dbDelta($sql);
}

/**
 * Ensure attendance log table exists.
 *
 * @return void
 */
function maca_menulist_db_ensure_attendance_log_table() {
    global $wpdb;

    static $ensured = false;
    if ($ensured) {
        return;
    }

    $table = maca_menulist_db_attendance_log_table();
    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    $exists = $wpdb->get_var($wpdb->prepare('SHOW TABLES LIKE %s', $table));
    if ($exists !== $table) {
        maca_menulist_db_create_attendance_log_table();
    }

    $ensured = true;
}

/**
 * Drop attendance log table.
 *
 * @return void
 */
function maca_menulist_db_drop_attendance_log_table() {
    global $wpdb;

    $table = maca_menulist_db_attendance_log_table();
    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange
    $wpdb->query("DROP TABLE IF EXISTS {$table}");
}

/**
 * Current actor for attendance log entries.
 *
 * @return array{type: string, id: int, label: string}
 */
function maca_menulist_attendance_log_current_actor() {
    if (is_user_logged_in()) {
        $user = wp_get_current_user();
        $label = $user->display_name !== '' ? $user->display_name : $user->user_login;

        return array(
            'type' => 'staff',
            'id' => (int) $user->ID,
            'label' => $label,
        );
    }

    return array(
        'type' => 'system',
        'id' => 0,
        'label' => __('System', 'maca-restu-pro'),
    );
}

/**
 * Insert an attendance log row.
 *
 * @param int                  $event_id    Event ID.
 * @param int                  $employee_id Employee ID.
 * @param string               $action      Action code.
 * @param array<string, mixed> $args        Optional summary, changes, actor.
 * @return bool
 */
function maca_menulist_attendance_log_add($event_id, $employee_id, $action, $args = array()) {
    global $wpdb;

    maca_menulist_db_ensure_attendance_log_table();

    $event_id = absint($event_id);
    $employee_id = absint($employee_id);
    $action = sanitize_key($action);

    if ($action === '' || $employee_id <= 0) {
        return false;
    }

    $actor = isset($args['actor']) && is_array($args['actor']) ? $args['actor'] : maca_menulist_attendance_log_current_actor();
    $summary = isset($args['summary']) ? sanitize_text_field((string) $args['summary']) : '';
    $changes = isset($args['changes']) && is_array($args['changes']) ? $args['changes'] : array();
    $changes_json = $changes !== array() ? wp_json_encode($changes, JSON_UNESCAPED_UNICODE) : null;

    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    $inserted = $wpdb->insert(
        maca_menulist_db_attendance_log_table(),
        array(
            'event_id' => $event_id,
            'employee_id' => $employee_id,
            'action' => $action,
            'summary' => $summary !== '' ? $summary : null,
            'changes' => $changes_json,
            'actor_type' => sanitize_key((string) ($actor['type'] ?? 'system')),
            'actor_id' => absint($actor['id'] ?? 0),
            'actor_label' => isset($actor['label']) ? sanitize_text_field((string) $actor['label']) : null,
            'created_at' => function_exists('maca_menulist_wp_now_mysql') ? maca_menulist_wp_now_mysql() : current_time('mysql'),
        ),
        array('%d', '%d', '%s', '%s', '%s', '%s', '%d', '%s', '%s')
    );

    return (bool) $inserted;
}

/**
 * Count attendance log entries.
 *
 * @param array<string, mixed> $args Optional employee_id filter.
 * @return int
 */
function maca_menulist_attendance_log_count($args = array()) {
    global $wpdb;

    maca_menulist_db_ensure_attendance_log_table();

    $employee_id = isset($args['employee_id']) ? absint($args['employee_id']) : 0;
    $table = maca_menulist_db_attendance_log_table();

    if ($employee_id > 0) {
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        return (int) $wpdb->get_var(
            $wpdb->prepare("SELECT COUNT(*) FROM $table WHERE employee_id = %d", $employee_id)
        );
    }

    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    return (int) $wpdb->get_var("SELECT COUNT(*) FROM $table");
}

/**
 * List attendance log entries.
 *
 * @param array<string, mixed> $args Query args.
 * @return array<int, object>
 */
function maca_menulist_attendance_log_list($args = array()) {
    global $wpdb;

    maca_menulist_db_ensure_attendance_log_table();

    $defaults = array(
        'employee_id' => 0,
        'per_page' => 100,
        'paged' => 1,
    );
    $args = wp_parse_args($args, $defaults);

    $per_page = max(1, min(500, absint($args['per_page'])));
    $paged = max(1, absint($args['paged']));
    $offset = ($paged - 1) * $per_page;
    $employee_id = absint($args['employee_id']);
    $table = maca_menulist_db_attendance_log_table();
    $employees_table = maca_menulist_db_employees_table();

    if ($employee_id > 0) {
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $rows = $wpdb->get_results(
            $wpdb->prepare(
                "SELECT l.*, e.name AS employee_name
                FROM $table l
                LEFT JOIN $employees_table e ON e.id = l.employee_id
                WHERE l.employee_id = %d
                ORDER BY l.created_at DESC, l.id DESC
                LIMIT %d OFFSET %d",
                $employee_id,
                $per_page,
                $offset
            )
        );
    } else {
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $rows = $wpdb->get_results(
            $wpdb->prepare(
                "SELECT l.*, e.name AS employee_name
                FROM $table l
                LEFT JOIN $employees_table e ON e.id = l.employee_id
                ORDER BY l.created_at DESC, l.id DESC
                LIMIT %d OFFSET %d",
                $per_page,
                $offset
            )
        );
    }

    return is_array($rows) ? $rows : array();
}

/**
 * Decode stored log changes JSON.
 *
 * @param string $json Stored JSON.
 * @return array<int, array<string, string>>
 */
function maca_menulist_attendance_log_decode_changes($json) {
    if ($json === '' || $json === null) {
        return array();
    }

    $decoded = json_decode((string) $json, true);

    return is_array($decoded) ? $decoded : array();
}
