<?php

date_default_timezone_set('Asia/Colombo');

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

mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);

function redirectWithSurveyError(string $message): void
{
    $_SESSION['error'] = $message;

    header('Location: add_survey.php');
    exit();
}

function postValue(string $key, int $maxLength = 255): string
{
    $value = trim((string)($_POST[$key] ?? ''));

    if (mb_strlen($value) > $maxLength) {
        throw new RuntimeException('One or more submitted fields are too long.');
    }

    return $value;
}

function validateQuantity(mixed $value): int
{
    $quantity = filter_var(
        $value,
        FILTER_VALIDATE_INT,
        ['options' => ['min_range' => 0]]
    );

    if ($quantity === false) {
        throw new RuntimeException(
            'Equipment quantities must be whole numbers equal to or greater than zero.'
        );
    }

    return $quantity;
}

/*
|--------------------------------------------------------------------------
| Request and CSRF validation
|--------------------------------------------------------------------------
*/

if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    header('Location: add_survey.php');
    exit();
}

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

/*
|--------------------------------------------------------------------------
| Basic submitted data
|--------------------------------------------------------------------------
*/

$censusNo = trim((string)($_POST['census_no'] ?? ''));

if ($censusNo === '' || mb_strlen($censusNo) > 50) {
    redirectWithSurveyError('Please select a valid school.');
}

$detailsJson = (string)($_POST['survey_details'] ?? '');

try {
    $surveyDetails = json_decode(
        $detailsJson,
        true,
        512,
        JSON_THROW_ON_ERROR
    );
} catch (JsonException $exception) {
    redirectWithSurveyError('Invalid survey equipment data.');
}

if (!is_array($surveyDetails) || count($surveyDetails) === 0) {
    redirectWithSurveyError(
        'At least one equipment record is required.'
    );
}

/*
|--------------------------------------------------------------------------
| Load authoritative school details
|--------------------------------------------------------------------------
*/

$school = null;

try {
    $schoolStatement = mysqli_prepare(
        $conn,
        'SELECT
            census_no,
            district,
            zone_name,
            division_name,
            school_name,
            school_category,
            school_type
         FROM schools
         WHERE census_no = ?
         LIMIT 1'
    );

    mysqli_stmt_bind_param(
        $schoolStatement,
        's',
        $censusNo
    );

    mysqli_stmt_execute($schoolStatement);

    $schoolResult = mysqli_stmt_get_result($schoolStatement);

    if ($schoolResult) {
        $school = mysqli_fetch_assoc($schoolResult);
    }

    mysqli_stmt_close($schoolStatement);

    if (!is_array($school)) {
        redirectWithSurveyError(
            'The selected census number does not belong to a valid school.'
        );
    }

    if (
        ($_SESSION['role'] ?? '') === 'zonal_director' &&
        trim((string)($_SESSION['zone_name'] ?? '')) !==
        trim((string)$school['zone_name'])
    ) {
        redirectWithSurveyError(
            'You cannot submit a survey for a school outside your zone.'
        );
    }
} catch (Throwable $exception) {
    error_log(
        'School validation error: ' .
        $exception->getMessage()
    );

    redirectWithSurveyError(
        'Unable to validate the selected school.'
    );
}

/*
|--------------------------------------------------------------------------
| Load valid standard units and their assigned equipment
|--------------------------------------------------------------------------
|
| This prevents users from changing section names or equipment IDs in the
| browser before submitting the form.
|
*/

$allowedStandardEquipment = [];

try {
    $allowedStatement = mysqli_prepare(
        $conn,
        "SELECT
            um.unit_name,
            em.id AS equipment_id
         FROM unit_master um
         INNER JOIN unit_equipment ue
            ON ue.unit_id = um.id
           AND ue.status = 'Active'
         INNER JOIN equipment_master em
            ON em.id = ue.equipment_id
           AND em.status = 'Active'
         WHERE um.status = 'Active'
           AND um.is_required = 'Yes'"
    );

    mysqli_stmt_execute($allowedStatement);

    $allowedResult = mysqli_stmt_get_result($allowedStatement);

    while ($row = mysqli_fetch_assoc($allowedResult)) {
        $unitName = trim((string)$row['unit_name']);
        $equipmentId = (int)$row['equipment_id'];

        if (!isset($allowedStandardEquipment[$unitName])) {
            $allowedStandardEquipment[$unitName] = [];
        }

        $allowedStandardEquipment[$unitName][$equipmentId] = true;
    }

    mysqli_stmt_close($allowedStatement);
} catch (Throwable $exception) {
    error_log(
        'Standard equipment loading error: ' .
        $exception->getMessage()
    );

    redirectWithSurveyError(
        'Unable to load the standard survey equipment.'
    );
}

/*
|--------------------------------------------------------------------------
| Contact details
|--------------------------------------------------------------------------
*/

try {
    $principalName = postValue('principal_name');
    $principalPhone = postValue('principal_phone', 20);
    $schoolPhone = postValue('school_phone', 20);
    $itTeacherName = postValue('it_teacher_name');
    $itTeacherPhone = postValue('it_teacher_phone', 20);
} catch (Throwable $exception) {
    redirectWithSurveyError($exception->getMessage());
}

/*
|--------------------------------------------------------------------------
| Transactional save
|--------------------------------------------------------------------------
*/

$transactionStarted = false;

try {
    mysqli_begin_transaction($conn);
    $transactionStarted = true;

/*
|--------------------------------------------------------------------------
| Prevent duplicate survey for the same school
|--------------------------------------------------------------------------
*/

$duplicateStatement = mysqli_prepare(
    $conn,
    'SELECT id
     FROM surveys
     WHERE census_no = ?
     LIMIT 1
     FOR UPDATE'
);

mysqli_stmt_bind_param(
    $duplicateStatement,
    's',
    $censusNo
);

mysqli_stmt_execute($duplicateStatement);

$duplicateResult =
    mysqli_stmt_get_result($duplicateStatement);

$duplicateSurvey =
    mysqli_fetch_assoc($duplicateResult);

mysqli_stmt_close($duplicateStatement);

if ($duplicateSurvey) {
    throw new RuntimeException(
        'A survey has already been submitted for this school.'
    );
}

    /*
    |--------------------------------------------------------------------------
    | Insert the main survey
    |--------------------------------------------------------------------------
    */

    $enteredBy = trim(
        (string)($_SESSION['fullname'] ?? '')
    );

    if ($enteredBy === '') {
        throw new RuntimeException(
            'Your login session is invalid. Please sign in again.'
        );
    }

    $district = (string)$school['district'];
    $zoneName = (string)$school['zone_name'];
    $divisionName = (string)$school['division_name'];
    $schoolName = (string)$school['school_name'];
    $schoolCategory = (string)$school['school_category'];
    $schoolType = (string)$school['school_type'];

    $surveyStatement = mysqli_prepare(
        $conn,
        'INSERT INTO surveys
        (
            survey_date,
            entered_by,
            census_no,
            district,
            zone_name,
            division_name,
            school_name,
            school_category,
            school_type,
            principal_name,
            principal_phone,
            school_phone,
            it_teacher_name,
            it_teacher_phone
        )
        VALUES
        (
            NOW(),
            ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
        )'
    );

    mysqli_stmt_bind_param(
        $surveyStatement,
        'sssssssssssss',
        $enteredBy,
        $censusNo,
        $district,
        $zoneName,
        $divisionName,
        $schoolName,
        $schoolCategory,
        $schoolType,
        $principalName,
        $principalPhone,
        $schoolPhone,
        $itTeacherName,
        $itTeacherPhone
    );

    mysqli_stmt_execute($surveyStatement);
    mysqli_stmt_close($surveyStatement);

    $surveyId = mysqli_insert_id($conn);

    if ($surveyId <= 0) {
        throw new RuntimeException(
            'Unable to create the survey record.'
        );
    }

    /*
    |--------------------------------------------------------------------------
    | Prepare equipment insert statements
    |--------------------------------------------------------------------------
    */

    $standardInsertStatement = mysqli_prepare(
        $conn,
        'INSERT INTO survey_equipment_details
        (
            survey_id,
            section,
            equipment_id,
            working,
            not_working,
            repair
        )
        VALUES (?, ?, ?, ?, ?, ?)'
    );

    $otherUnitInsertStatement = mysqli_prepare(
        $conn,
        'INSERT INTO survey_other_units
        (
            survey_id,
            unit_name,
            details,
            display_order
        )
        VALUES (?, ?, ?, ?)'
    );

    $otherEquipmentInsertStatement = mysqli_prepare(
        $conn,
        'INSERT INTO survey_other_equipment
        (
            other_unit_id,
            equipment_name,
            working,
            not_working,
            repair,
            display_order
        )
        VALUES (?, ?, ?, ?, ?, ?)'
    );

    $savedRecordCount = 0;
    $otherUnitOrder = 1;
    $submittedStandardRecords = [];

    /*
    |--------------------------------------------------------------------------
    | Save standard and user-created units
    |--------------------------------------------------------------------------
    */

    foreach ($surveyDetails as $unit) {
        if (!is_array($unit)) {
            throw new RuntimeException('Invalid unit details.');
        }

        $section = trim(
            (string)($unit['section'] ?? '')
        );

        $isCustom =
            filter_var(
                $unit['is_custom'] ?? false,
                FILTER_VALIDATE_BOOLEAN
            );

        $equipmentItems = $unit['equipment'] ?? [];

        if (
            $section === '' ||
            mb_strlen($section) > 150 ||
            !is_array($equipmentItems)
        ) {
            throw new RuntimeException('Invalid unit details.');
        }

        /*
        |--------------------------------------------------------------------------
        | User-created Other Unit
        |--------------------------------------------------------------------------
        */

        if ($isCustom) {
            $otherUnitDetails = trim(
                (string)($unit['details'] ?? '')
            );

            if (mb_strlen($otherUnitDetails) > 5000) {
                throw new RuntimeException(
                    'Other-unit details are too long.'
                );
            }

            if (count($equipmentItems) === 0) {
                throw new RuntimeException(
                    'Please add equipment to ' . $section . '.'
                );
            }

            mysqli_stmt_bind_param(
                $otherUnitInsertStatement,
                'issi',
                $surveyId,
                $section,
                $otherUnitDetails,
                $otherUnitOrder
            );

            mysqli_stmt_execute(
                $otherUnitInsertStatement
            );

            $otherUnitId = mysqli_insert_id($conn);

            if ($otherUnitId <= 0) {
                throw new RuntimeException(
                    'Unable to save the unit ' . $section . '.'
                );
            }

            $otherEquipmentOrder = 1;
            $customEquipmentNames = [];

            foreach ($equipmentItems as $item) {
                if (!is_array($item)) {
                    throw new RuntimeException(
                        'Invalid equipment details in ' .
                        $section .
                        '.'
                    );
                }

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

                if (
                    $equipmentName === '' ||
                    mb_strlen($equipmentName) > 150
                ) {
                    throw new RuntimeException(
                        'Enter a valid equipment name in ' .
                        $section .
                        '.'
                    );
                }

                $normalizedEquipmentName =
                    mb_strtolower($equipmentName);

                if (
                    isset(
                        $customEquipmentNames[
                            $normalizedEquipmentName
                        ]
                    )
                ) {
                    throw new RuntimeException(
                        'Duplicate equipment "' .
                        $equipmentName .
                        '" in ' .
                        $section .
                        '.'
                    );
                }

                $customEquipmentNames[
                    $normalizedEquipmentName
                ] = true;

                $working = validateQuantity(
                    $item['working'] ?? null
                );

                $notWorking = validateQuantity(
                    $item['not_working'] ?? null
                );

                $repair = validateQuantity(
                    $item['repair'] ?? null
                );

                mysqli_stmt_bind_param(
                    $otherEquipmentInsertStatement,
                    'isiiii',
                    $otherUnitId,
                    $equipmentName,
                    $working,
                    $notWorking,
                    $repair,
                    $otherEquipmentOrder
                );

                mysqli_stmt_execute(
                    $otherEquipmentInsertStatement
                );

                $otherEquipmentOrder++;
                $savedRecordCount++;
            }

            $otherUnitOrder++;

            continue;
        }

        /*
        |--------------------------------------------------------------------------
        | Standard required unit
        |--------------------------------------------------------------------------
        */

        if (!isset($allowedStandardEquipment[$section])) {
            throw new RuntimeException(
                'Invalid standard unit: ' . $section . '.'
            );
        }

        foreach ($equipmentItems as $item) {
            if (!is_array($item)) {
                throw new RuntimeException(
                    'Invalid equipment details in ' .
                    $section .
                    '.'
                );
            }

            $equipmentId = filter_var(
                $item['equipment_id'] ?? null,
                FILTER_VALIDATE_INT,
                ['options' => ['min_range' => 1]]
            );

            if (
                $equipmentId === false ||
                !isset(
                    $allowedStandardEquipment[
                        $section
                    ][$equipmentId]
                )
            ) {
                throw new RuntimeException(
                    'Invalid equipment selection in ' .
                    $section .
                    '.'
                );
            }

            $standardKey =
                $section . ':' . $equipmentId;

            if (
                isset(
                    $submittedStandardRecords[
                        $standardKey
                    ]
                )
            ) {
                throw new RuntimeException(
                    'Duplicate standard equipment in ' .
                    $section .
                    '.'
                );
            }

            $submittedStandardRecords[
                $standardKey
            ] = true;

            $working = validateQuantity(
                $item['working'] ?? null
            );

            $notWorking = validateQuantity(
                $item['not_working'] ?? null
            );

            $repair = validateQuantity(
                $item['repair'] ?? null
            );

            mysqli_stmt_bind_param(
                $standardInsertStatement,
                'isiiii',
                $surveyId,
                $section,
                $equipmentId,
                $working,
                $notWorking,
                $repair
            );

            mysqli_stmt_execute(
                $standardInsertStatement
            );

            $savedRecordCount++;
        }
    }

    mysqli_stmt_close($standardInsertStatement);
    mysqli_stmt_close($otherUnitInsertStatement);
    mysqli_stmt_close($otherEquipmentInsertStatement);

    if ($savedRecordCount === 0) {
        throw new RuntimeException(
            'At least one equipment record is required.'
        );
    }

    mysqli_commit($conn);
    $transactionStarted = false;

    logActivity(
    $conn,
    'Survey Management',
    'Create Survey',
    'Survey submitted for "' .
    $schoolName .
    '" (Census No: ' .
    $censusNo .
    ')'
);

    $_SESSION['success'] =
        'Survey saved successfully.';

    /*
     * Clear any saved browser draft after the redirect by passing
     * a success flag that the destination page can use if needed.
     */
    header(
        'Location: view_surveys.php?saved=1'
    );
    exit();
} catch (Throwable $exception) {
    if ($transactionStarted) {
        mysqli_rollback($conn);
    }

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

    $safeMessages = [
        'A survey has already been submitted for this school today.',
        'Your login session is invalid. Please sign in again.',
        'At least one equipment record is required.'
    ];

    if (
        in_array(
            $exception->getMessage(),
            $safeMessages,
            true
        ) ||
        str_starts_with(
            $exception->getMessage(),
            'Invalid '
        ) ||
        str_starts_with(
            $exception->getMessage(),
            'Please '
        ) ||
        str_starts_with(
            $exception->getMessage(),
            'Enter '
        ) ||
        str_starts_with(
            $exception->getMessage(),
            'Duplicate '
        )
    ) {
        redirectWithSurveyError(
            $exception->getMessage()
        );
    }

    redirectWithSurveyError(
        'Unable to save the survey. Please contact the administrator.'
    );
}