<?php
/**
 * REST API for personalliggare (mobile clock in/out).
 *
 * @package Maca_Menu_List
 */

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

add_action('rest_api_init', 'maca_menulist_register_attendance_rest_routes');

/**
 * Register attendance REST routes.
 *
 * @return void
 */
function maca_menulist_register_attendance_rest_routes() {
    register_rest_route(
        'maca-menulist/v1',
        '/attendance',
        array(
            'methods'             => 'POST',
            'callback'            => 'maca_menulist_rest_attendance_handler',
            'permission_callback' => '__return_true',
        )
    );
}

/**
 * Copy REST request params into $_POST for shared handlers.
 *
 * @param WP_REST_Request $request Request.
 * @return void
 */
function maca_menulist_rest_attendance_merge_request_params(WP_REST_Request $request) {
    foreach ($request->get_params() as $key => $value) {
        if (!is_scalar($value)) {
            continue;
        }

        $_POST[$key] = wp_unslash((string) $value);
    }
}

/**
 * Build REST response.
 *
 * @param array<string, mixed> $result Dispatch result.
 * @return WP_REST_Response
 */
function maca_menulist_rest_attendance_response(array $result) {
    $success = !empty($result['success']);
    $status = isset($result['status']) ? (int) $result['status'] : ($success ? 200 : 403);

    return new WP_REST_Response(
        array(
            'success' => $success,
            'data'    => isset($result['data']) && is_array($result['data']) ? $result['data'] : array(),
        ),
        $status
    );
}

/**
 * Read attendance session token from request.
 *
 * @return string
 */
function maca_menulist_get_attendance_session_from_request() {
    // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Session-bound attendance API.
    if (isset($_POST['attendance_session'])) {
        return sanitize_text_field(wp_unslash($_POST['attendance_session']));
    }

    // phpcs:ignore WordPress.Security.NonceVerification.Missing
    if (isset($_POST['session'])) {
        return sanitize_text_field(wp_unslash($_POST['session']));
    }

    return '';
}

/**
 * Dispatch attendance API action.
 *
 * @param string $action Action name.
 * @return array<string, mixed>
 */
function maca_menulist_attendance_api_dispatch($action) {
    if (!maca_menulist_attendance_enabled()) {
        return array(
            'success' => false,
            'status'  => 403,
            'data'    => array(
                'message' => maca_menulist_attendance_ui_string('Personalliggare is disabled.'),
            ),
        );
    }

    $action = sanitize_key($action);

    switch ($action) {
        case 'verify_pin':
            return maca_menulist_attendance_api_verify_pin();
        case 'status':
            return maca_menulist_attendance_api_status();
        case 'clock':
            return maca_menulist_attendance_api_clock();
        case 'logout':
            return maca_menulist_attendance_api_logout();
        case 'verify_staff_pin':
            return maca_menulist_attendance_api_verify_staff_pin();
        case 'control_report':
            return maca_menulist_attendance_api_control_report();
        default:
            return array(
                'success' => false,
                'status'  => 400,
                'data'    => array(
                    'message' => maca_menulist_attendance_ui_string('Unknown attendance action.'),
                ),
            );
    }
}

/**
 * Verify employee PIN and create session.
 *
 * @return array<string, mixed>
 */
function maca_menulist_attendance_api_verify_pin() {
    if (function_exists('maca_menulist_attendance_request_has_employee_id_param')
        && maca_menulist_attendance_request_has_employee_id_param()) {
        return array(
            'success' => false,
            'status'  => 403,
            'data'    => array(
                'message' => maca_menulist_attendance_ui_string('You can only clock in/out with your own personal code.'),
            ),
        );
    }

    $feedback = maca_menulist_get_attendance_pin_feedback();
    if ($feedback['is_locked']) {
        return array(
            'success' => false,
            'status'  => 403,
            'data'    => array_merge(
                $feedback,
                array(
                    'message' => maca_menulist_attendance_ui_string('PIN locked. Try again later.'),
                )
            ),
        );
    }

    // phpcs:ignore WordPress.Security.NonceVerification.Missing
    $pin = isset($_POST['pin']) ? preg_replace('/\D/', '', (string) wp_unslash($_POST['pin'])) : '';

    if ($pin === '') {
        return array(
            'success' => false,
            'status'  => 400,
            'data'    => array(
                'message' => maca_menulist_attendance_ui_string('Enter your personal code.'),
            ),
        );
    }

    $employee = maca_menulist_find_employee_by_pin($pin);
    if (!$employee) {
        maca_menulist_register_attendance_pin_failed_attempt();

        return array(
            'success' => false,
            'status'  => 403,
            'data'    => array_merge(
                maca_menulist_get_attendance_pin_feedback(),
                array(
                    'message' => maca_menulist_attendance_ui_string('Invalid code.'),
                )
            ),
        );
    }

    maca_menulist_clear_attendance_pin_lockout();

    $session = maca_menulist_create_employee_session((int) $employee->id);
    $status = maca_menulist_get_employee_attendance_status((int) $employee->id);

    return array(
        'success' => true,
        'status'  => 200,
        'data'    => array(
            'attendance_session' => $session,
            'employee' => array(
                'id' => (int) $employee->id,
                'name' => (string) $employee->name,
            ),
            'status' => array(
                'is_clocked_in' => $status['is_clocked_in'],
                'last_occurred_at' => $status['last_occurred_at'],
                'last_occurred_at_label' => maca_menulist_format_attendance_time($status['last_occurred_at']),
            ),
        ),
    );
}

/**
 * Return current status for an active session.
 *
 * @return array<string, mixed>
 */
function maca_menulist_attendance_api_status() {
    if (function_exists('maca_menulist_attendance_request_has_employee_id_param')
        && maca_menulist_attendance_request_has_employee_id_param()) {
        return array(
            'success' => false,
            'status'  => 403,
            'data'    => array(
                'message' => maca_menulist_attendance_ui_string('You can only clock in/out with your own personal code.'),
            ),
        );
    }

    $employee_id = maca_menulist_attendance_api_require_session();
    if (is_array($employee_id)) {
        return $employee_id;
    }

    $employee = maca_menulist_db_get_employee($employee_id);
    if (!$employee) {
        return array(
            'success' => false,
            'status'  => 403,
            'data'    => array(
                'message' => maca_menulist_attendance_ui_string('Session expired.'),
            ),
        );
    }

    $status = maca_menulist_get_employee_attendance_status($employee_id);

    return array(
        'success' => true,
        'status'  => 200,
        'data'    => array(
            'employee' => array(
                'id' => (int) $employee->id,
                'name' => (string) $employee->name,
            ),
            'status' => array(
                'is_clocked_in' => $status['is_clocked_in'],
                'last_occurred_at' => $status['last_occurred_at'],
                'last_occurred_at_label' => maca_menulist_format_attendance_time($status['last_occurred_at']),
            ),
        ),
    );
}

/**
 * Clock in or out for session employee.
 *
 * @return array<string, mixed>
 */
function maca_menulist_attendance_api_clock() {
    if (function_exists('maca_menulist_attendance_request_has_employee_id_param')
        && maca_menulist_attendance_request_has_employee_id_param()) {
        return array(
            'success' => false,
            'status'  => 403,
            'data'    => array(
                'message' => maca_menulist_attendance_ui_string('You can only clock in/out with your own personal code.'),
            ),
        );
    }

    $employee_id = maca_menulist_attendance_api_require_session();
    if (is_array($employee_id)) {
        return $employee_id;
    }

    // phpcs:ignore WordPress.Security.NonceVerification.Missing
    $clock_action = isset($_POST['clock_action']) ? sanitize_key(wp_unslash($_POST['clock_action'])) : '';
    if ($clock_action === '') {
        // phpcs:ignore WordPress.Security.NonceVerification.Missing
        $clock_action = isset($_POST['action_type']) ? sanitize_key(wp_unslash($_POST['action_type'])) : '';
    }

    if ($clock_action === 'in') {
        $clock_action = 'clock_in';
    } elseif ($clock_action === 'out') {
        $clock_action = 'clock_out';
    }

    $result = maca_menulist_attendance_clock($employee_id, $clock_action);
    if (!$result['success']) {
        return array(
            'success' => false,
            'status'  => 400,
            'data'    => array(
                'message' => $result['message'],
            ),
        );
    }

    $status = maca_menulist_get_employee_attendance_status($employee_id);

    return array(
        'success' => true,
        'status'  => 200,
        'data'    => array(
            'message' => $result['message'],
            'event_id' => (int) ($result['event_id'] ?? 0),
            'status' => array(
                'is_clocked_in' => $status['is_clocked_in'],
                'last_occurred_at' => $status['last_occurred_at'],
                'last_occurred_at_label' => maca_menulist_format_attendance_time($status['last_occurred_at']),
            ),
        ),
    );
}

/**
 * End attendance session.
 *
 * @return array<string, mixed>
 */
function maca_menulist_attendance_api_logout() {
    $session = maca_menulist_get_attendance_session_from_request();
    $key = maca_menulist_employee_session_storage_key($session);
    if ($key !== '') {
        delete_transient($key);
    }

    return array(
        'success' => true,
        'status'  => 200,
        'data'    => array(
            'logged_out' => true,
        ),
    );
}

/**
 * Read control session token from request.
 *
 * @return string
 */
function maca_menulist_get_attendance_control_session_from_request() {
    // phpcs:ignore WordPress.Security.NonceVerification.Missing
    if (isset($_POST['control_session'])) {
        return sanitize_text_field(wp_unslash($_POST['control_session']));
    }

    return '';
}

/**
 * Verify staff PIN for control view.
 *
 * @return array<string, mixed>
 */
function maca_menulist_attendance_api_verify_staff_pin() {
    if (maca_menulist_get_table_order_staff_pin() === '') {
        return array(
            'success' => false,
            'status'  => 403,
            'data'    => array(
                'message' => maca_menulist_attendance_ui_string('Staff PIN is not configured. Set it in maca Restu settings.'),
            ),
        );
    }

    // phpcs:ignore WordPress.Security.NonceVerification.Missing
    $pin = isset($_POST['staff_pin']) ? trim((string) wp_unslash($_POST['staff_pin'])) : '';
    if ($pin === '') {
        // phpcs:ignore WordPress.Security.NonceVerification.Missing
        $pin = isset($_POST['pin']) ? trim((string) wp_unslash($_POST['pin'])) : '';
    }

    if ($pin === '') {
        return array(
            'success' => false,
            'status'  => 400,
            'data'    => array(
                'message' => maca_menulist_attendance_ui_string('Enter staff PIN.'),
            ),
        );
    }

    if (!function_exists('maca_menulist_verify_table_order_staff_pin') || !maca_menulist_verify_table_order_staff_pin($pin)) {
        $feedback = function_exists('maca_menulist_get_staff_pin_attempt_feedback')
            ? maca_menulist_get_staff_pin_attempt_feedback()
            : array();

        return array(
            'success' => false,
            'status'  => 403,
            'data'    => array_merge(
                $feedback,
                array(
                    'message' => maca_menulist_attendance_ui_string('Incorrect PIN.'),
                )
            ),
        );
    }

    $session = maca_menulist_create_attendance_control_session();

    return array(
        'success' => true,
        'status'  => 200,
        'data'    => array(
            'control_session' => $session,
        ),
    );
}

/**
 * Control view report (no personal numbers).
 *
 * @return array<string, mixed>
 */
function maca_menulist_attendance_api_control_report() {
    $session = maca_menulist_get_attendance_control_session_from_request();
    if ($session === '' || !maca_menulist_validate_attendance_control_session($session)) {
        return array(
            'success' => false,
            'status'  => 403,
            'data'    => array(
                'message' => maca_menulist_attendance_ui_string('Session expired. Enter staff PIN again.'),
            ),
        );
    }

    // phpcs:ignore WordPress.Security.NonceVerification.Missing
    $date = isset($_POST['date']) ? sanitize_text_field(wp_unslash($_POST['date'])) : '';
    $date = maca_menulist_attendance_normalize_date($date);
    $rows = maca_menulist_build_attendance_report(
        $date,
        $date,
        array(
            'only_with_activity' => false,
        )
    );

    $payload = array();
    foreach ($rows as $row) {
        $payload[] = array(
            'name' => (string) $row['name'],
            'clock_in' => (string) $row['clock_in'],
            'clock_out' => (string) $row['clock_out'],
            'is_clocked_in' => !empty($row['is_clocked_in']),
        );
    }

    return array(
        'success' => true,
        'status'  => 200,
        'data'    => array(
            'date' => $date,
            'date_label' => maca_menulist_attendance_format_date_label($date),
            'rows' => $payload,
        ),
    );
}

/**
 * Require valid session; return employee ID or error array.
 *
 * @return int|array<string, mixed>
 */
function maca_menulist_attendance_api_require_session() {
    $session = maca_menulist_get_attendance_session_from_request();
    $employee_id = maca_menulist_validate_employee_session($session);

    if ($employee_id <= 0) {
        return array(
            'success' => false,
            'status'  => 403,
            'data'    => array(
                'message' => maca_menulist_attendance_ui_string('Session expired. Enter your code again.'),
            ),
        );
    }

    return $employee_id;
}

/**
 * REST callback for attendance actions.
 *
 * @param WP_REST_Request $request Request.
 * @return WP_REST_Response
 */
function maca_menulist_rest_attendance_handler(WP_REST_Request $request) {
    maca_menulist_rest_attendance_merge_request_params($request);

    // phpcs:ignore WordPress.Security.NonceVerification.Missing
    $action = isset($_POST['attendance_action']) ? sanitize_key(wp_unslash($_POST['attendance_action'])) : '';
    if ($action === '') {
        // phpcs:ignore WordPress.Security.NonceVerification.Missing
        $action = isset($_POST['action']) ? sanitize_key(wp_unslash($_POST['action'])) : '';
    }

    if ($action === '') {
        return maca_menulist_rest_attendance_response(
            array(
                'success' => false,
                'status'  => 400,
                'data'    => array(
                    'message' => maca_menulist_attendance_ui_string('Missing attendance action.'),
                ),
            )
        );
    }

    return maca_menulist_rest_attendance_response(maca_menulist_attendance_api_dispatch($action));
}
