<?php

ob_start();

require_once __DIR__ . '/../../includes/auth.php';
require_once __DIR__ . '/../../config/db.php';
require_once __DIR__ . '/../../includes/csrf.php';

header('Content-Type: application/json; charset=utf-8');

mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);

function saveEquipmentResponse(bool $success, string $message): void
{
    /*
     * Remove accidental warnings, spaces, or output produced by an
     * included PHP file so the browser receives valid JSON only.
     */
    if (ob_get_length()) {
        ob_clean();
    }

    echo json_encode(
        [
            'success' => $success,
            'message' => $message
        ],
        JSON_UNESCAPED_UNICODE
    );

    exit();
}

if (($_SESSION['role'] ?? '') !== 'admin') {
    saveEquipmentResponse(false, 'Access denied.');
}

if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    saveEquipmentResponse(false, 'Invalid request method.');
}

if (
    !hash_equals(
        $_SESSION['csrf_token'] ?? '',
        $_POST['csrf_token'] ?? ''
    )
) {
    saveEquipmentResponse(false, 'Invalid security token. Please refresh the page.');
}

/*
|--------------------------------------------------------------------------
| Validate submitted values
|--------------------------------------------------------------------------
*/

$rawId = trim((string)($_POST['id'] ?? ''));

$id = $rawId === ''
    ? 0
    : filter_var(
        $rawId,
        FILTER_VALIDATE_INT,
        ['options' => ['min_range' => 1]]
    );

$equipmentName = trim((string)($_POST['equipment_name'] ?? ''));

$requestedOrder = filter_var(
    $_POST['display_order'] ?? null,
    FILTER_VALIDATE_INT,
    ['options' => ['min_range' => 1]]
);

$status = $_POST['status'] ?? '';

$submittedUnitIds = $_POST['unit_ids'] ?? [];

if (
    $id === false ||
    $equipmentName === '' ||
    mb_strlen($equipmentName) > 100 ||
    $requestedOrder === false ||
    !in_array($status, ['Active', 'Inactive'], true) ||
    !is_array($submittedUnitIds)
) {
    saveEquipmentResponse(false, 'Please provide valid equipment details.');
}

/*
|--------------------------------------------------------------------------
| Validate and remove duplicate unit IDs
|--------------------------------------------------------------------------
*/

$unitIds = [];

foreach ($submittedUnitIds as $submittedUnitId) {
    $unitId = filter_var(
        $submittedUnitId,
        FILTER_VALIDATE_INT,
        ['options' => ['min_range' => 1]]
    );

    if ($unitId === false) {
        saveEquipmentResponse(false, 'Invalid unit selection.');
    }

    $unitIds[] = $unitId;
}

$unitIds = array_values(array_unique($unitIds));

$transactionStarted = false;

try {
    /*
    |--------------------------------------------------------------------------
    | Prevent duplicate equipment names
    |--------------------------------------------------------------------------
    */

    $duplicateStatement = mysqli_prepare(
        $conn,
        'SELECT id
         FROM equipment_master
         WHERE equipment_name = ?
           AND id <> ?
         LIMIT 1'
    );

    mysqli_stmt_bind_param(
        $duplicateStatement,
        'si',
        $equipmentName,
        $id
    );

    mysqli_stmt_execute($duplicateStatement);
    mysqli_stmt_store_result($duplicateStatement);

    $duplicateExists =
        mysqli_stmt_num_rows($duplicateStatement) > 0;

    mysqli_stmt_close($duplicateStatement);

    if ($duplicateExists) {
        saveEquipmentResponse(
            false,
            'An equipment item with this name already exists.'
        );
    }

    /*
    |--------------------------------------------------------------------------
    | Validate all selected units before changing equipment
    |--------------------------------------------------------------------------
    */

    if ($unitIds) {
        $unitValidationStatement = mysqli_prepare(
            $conn,
            'SELECT id
             FROM unit_master
             WHERE id = ?
               AND status = ?'
        );

        $activeStatus = 'Active';

        foreach ($unitIds as $unitId) {
            mysqli_stmt_bind_param(
                $unitValidationStatement,
                'is',
                $unitId,
                $activeStatus
            );

            mysqli_stmt_execute($unitValidationStatement);
            mysqli_stmt_store_result($unitValidationStatement);

            $unitIsValid =
                mysqli_stmt_num_rows($unitValidationStatement) === 1;

            /*
             * Important when reusing the same prepared statement.
             */
            mysqli_stmt_free_result($unitValidationStatement);

            if (!$unitIsValid) {
                mysqli_stmt_close($unitValidationStatement);

                saveEquipmentResponse(
                    false,
                    'One or more selected units are invalid or inactive.'
                );
            }
        }

        mysqli_stmt_close($unitValidationStatement);
    }

    mysqli_begin_transaction($conn);
    $transactionStarted = true;

    /*
    |--------------------------------------------------------------------------
    | Count equipment records
    |--------------------------------------------------------------------------
    */

    $countStatement = mysqli_prepare(
        $conn,
        'SELECT COUNT(*) AS total
         FROM equipment_master'
    );

    mysqli_stmt_execute($countStatement);

    $countResult = mysqli_stmt_get_result($countStatement);
    $countRow = mysqli_fetch_assoc($countResult);

    $equipmentCount = (int)($countRow['total'] ?? 0);

    mysqli_stmt_close($countStatement);

    if ($id > 0) {
        /*
        |--------------------------------------------------------------------------
        | Load the equipment's current display order
        |--------------------------------------------------------------------------
        */

        $existingStatement = mysqli_prepare(
            $conn,
            'SELECT display_order
             FROM equipment_master
             WHERE id = ?
             LIMIT 1'
        );

        mysqli_stmt_bind_param($existingStatement, 'i', $id);
        mysqli_stmt_execute($existingStatement);

        $existingResult = mysqli_stmt_get_result($existingStatement);
        $existingEquipment = mysqli_fetch_assoc($existingResult);

        mysqli_stmt_close($existingStatement);

        if (!$existingEquipment) {
            throw new RuntimeException('Equipment not found.');
        }

        $oldOrder = max(
            1,
            (int)$existingEquipment['display_order']
        );

        /*
         * Existing equipment can only use positions 1 to total count.
         */
        $newOrder = min(
            max(1, $requestedOrder),
            max(1, $equipmentCount)
        );

        /*
        |--------------------------------------------------------------------------
        | Rearrange surrounding records when position changes
        |--------------------------------------------------------------------------
        */

        if ($newOrder < $oldOrder) {
            $shiftStatement = mysqli_prepare(
                $conn,
                'UPDATE equipment_master
                 SET display_order = display_order + 1
                 WHERE id <> ?
                   AND display_order >= ?
                   AND display_order < ?'
            );

            mysqli_stmt_bind_param(
                $shiftStatement,
                'iii',
                $id,
                $newOrder,
                $oldOrder
            );

            mysqli_stmt_execute($shiftStatement);
            mysqli_stmt_close($shiftStatement);
        } elseif ($newOrder > $oldOrder) {
            $shiftStatement = mysqli_prepare(
                $conn,
                'UPDATE equipment_master
                 SET display_order = display_order - 1
                 WHERE id <> ?
                   AND display_order > ?
                   AND display_order <= ?'
            );

            mysqli_stmt_bind_param(
                $shiftStatement,
                'iii',
                $id,
                $oldOrder,
                $newOrder
            );

            mysqli_stmt_execute($shiftStatement);
            mysqli_stmt_close($shiftStatement);
        }

        /*
        |--------------------------------------------------------------------------
        | Update equipment
        |--------------------------------------------------------------------------
        */

        $equipmentStatement = mysqli_prepare(
            $conn,
            'UPDATE equipment_master
             SET equipment_name = ?,
                 display_order = ?,
                 status = ?
             WHERE id = ?'
        );

        mysqli_stmt_bind_param(
            $equipmentStatement,
            'sisi',
            $equipmentName,
            $newOrder,
            $status,
            $id
        );

        mysqli_stmt_execute($equipmentStatement);
        mysqli_stmt_close($equipmentStatement);

        /*
         * Replace previous unit assignments.
         */
        $deleteAssignmentsStatement = mysqli_prepare(
            $conn,
            'DELETE FROM unit_equipment
             WHERE equipment_id = ?'
        );

        mysqli_stmt_bind_param(
            $deleteAssignmentsStatement,
            'i',
            $id
        );

        mysqli_stmt_execute($deleteAssignmentsStatement);
        mysqli_stmt_close($deleteAssignmentsStatement);
    } else {
        /*
         * A new item can only be inserted from position 1 through
         * count + 1. Entering 15 when there are 10 items becomes 11.
         */
        $newOrder = min(
            max(1, $requestedOrder),
            $equipmentCount + 1
        );

        /*
         * Make room at the selected position.
         */
        $shiftStatement = mysqli_prepare(
            $conn,
            'UPDATE equipment_master
             SET display_order = display_order + 1
             WHERE display_order >= ?'
        );

        mysqli_stmt_bind_param(
            $shiftStatement,
            'i',
            $newOrder
        );

        mysqli_stmt_execute($shiftStatement);
        mysqli_stmt_close($shiftStatement);

        /*
        |--------------------------------------------------------------------------
        | Insert equipment
        |--------------------------------------------------------------------------
        */

        $equipmentStatement = mysqli_prepare(
            $conn,
            'INSERT INTO equipment_master
                (
                    equipment_name,
                    display_order,
                    status
                )
             VALUES (?, ?, ?)'
        );

        mysqli_stmt_bind_param(
            $equipmentStatement,
            'sis',
            $equipmentName,
            $newOrder,
            $status
        );

        mysqli_stmt_execute($equipmentStatement);

        $id = mysqli_insert_id($conn);

        mysqli_stmt_close($equipmentStatement);
    }

    /*
    |--------------------------------------------------------------------------
    | Insert selected unit assignments
    |--------------------------------------------------------------------------
    */

    if ($unitIds) {
        $assignmentStatement = mysqli_prepare(
            $conn,
            'INSERT INTO unit_equipment
                (
                    unit_id,
                    equipment_id,
                    display_order,
                    status
                )
             VALUES (?, ?, ?, ?)'
        );

        $assignmentOrder = 1;
        $activeStatus = 'Active';

        foreach ($unitIds as $unitId) {
            mysqli_stmt_bind_param(
                $assignmentStatement,
                'iiis',
                $unitId,
                $id,
                $assignmentOrder,
                $activeStatus
            );

            mysqli_stmt_execute($assignmentStatement);

            $assignmentOrder++;
        }

        mysqli_stmt_close($assignmentStatement);
    }

    mysqli_commit($conn);
    $transactionStarted = false;

    saveEquipmentResponse(
        true,
        'Equipment saved successfully.'
    );
} catch (Throwable $exception) {
    if ($transactionStarted) {
        mysqli_rollback($conn);
    }

    error_log(
        'Equipment save error: ' .
        $exception->getMessage()
    );

    if ($exception->getMessage() === 'Equipment not found.') {
        saveEquipmentResponse(
            false,
            'Equipment not found.'
        );
    }

    saveEquipmentResponse(
        false,
        'Unable to save equipment. Please contact the administrator.'
    );
}