<?php

declare(strict_types=1);

/*
|--------------------------------------------------------------------------
| SMARTAPPLY
| UNILAK DATABASE → FORM MAPPING TEST
|--------------------------------------------------------------------------
|
| This test:
|
| 1. Connects to SmartApply database
| 2. Loads one real application from applications table
| 3. Converts database columns into MappingEngine source fields
| 4. Loads UNILAK mappings
| 5. Generates the UNILAK form payload
| 6. Shows which fields have database data
| 7. Shows which required fields are still empty
|
|--------------------------------------------------------------------------
*/

require_once __DIR__ . '/Core/Database.php';
require_once __DIR__ . '/Core/MappingEngine.php';


/*
|--------------------------------------------------------------------------
| DISPLAY HELPERS
|--------------------------------------------------------------------------
*/

function line(string $char = '=', int $length = 70): void
{
    echo str_repeat($char, $length) . PHP_EOL;
}

function title(string $text): void
{
    line('=');
    echo $text . PHP_EOL;
    line('=');
}

function section(string $text): void
{
    echo PHP_EOL;
    line('-');
    echo $text . PHP_EOL;
    line('-');
}


/*
|--------------------------------------------------------------------------
| START
|--------------------------------------------------------------------------
*/

title('SMARTAPPLY - UNILAK DATABASE → FORM MAPPING TEST');

echo 'Project : SmartApply' . PHP_EOL;
echo 'Folder  : ' . __DIR__ . PHP_EOL;
echo 'PHP     : ' . PHP_VERSION . PHP_EOL;


/*
|--------------------------------------------------------------------------
| 1. DATABASE
|--------------------------------------------------------------------------
*/

section('1. DATABASE CONNECTION');

try {

    $pdo = Database::connection();

    echo '[OK] PDO connection established.' . PHP_EOL;

} catch (Throwable $e) {

    echo '[ERROR] Database connection failed.' . PHP_EOL;
    echo 'Message: ' . $e->getMessage() . PHP_EOL;

    exit(1);
}


/*
|--------------------------------------------------------------------------
| 2. LOAD APPLICATION
|--------------------------------------------------------------------------
|
| We deliberately use Application ID = 2 because that is the real
| application you already tested.
|
|--------------------------------------------------------------------------
*/

section('2. LOAD APPLICATION');

$applicationId = 2;

try {

    $stmt = $pdo->prepare("
        SELECT *
        FROM applications
        WHERE id = :id
        LIMIT 1
    ");

    $stmt->execute([
        ':id' => $applicationId
    ]);

    $application = $stmt->fetch(PDO::FETCH_ASSOC);

    if (!$application) {

        echo '[ERROR] Application ID ' .
             $applicationId .
             ' was not found.' .
             PHP_EOL;

        exit(1);
    }

    echo '[OK] Application found.' . PHP_EOL;
    echo 'Application ID: ' .
         ($application['id'] ?? $applicationId) .
         PHP_EOL;

} catch (Throwable $e) {

    echo '[ERROR] Could not load application.' . PHP_EOL;
    echo 'Message: ' . $e->getMessage() . PHP_EOL;

    exit(1);
}


/*
|--------------------------------------------------------------------------
| 3. SHOW DATABASE DATA
|--------------------------------------------------------------------------
*/

section('3. APPLICATION DATA FROM DATABASE');

foreach ($application as $field => $value) {

    if ($value === null || $value === '') {

        echo str_pad(
            $field,
            32
        ) . ': [EMPTY]' . PHP_EOL;

        continue;
    }

    echo str_pad(
        $field,
        32
    ) . ': ' . $value . PHP_EOL;
}


/*
|--------------------------------------------------------------------------
| 4. INITIALIZE MAPPING ENGINE
|--------------------------------------------------------------------------
*/

section('4. MAPPING ENGINE');

try {

    $engine = new MappingEngine($pdo);

    echo '[OK] MappingEngine initialized.' . PHP_EOL;

} catch (Throwable $e) {

    echo '[ERROR] MappingEngine initialization failed.' . PHP_EOL;
    echo 'Message: ' . $e->getMessage() . PHP_EOL;

    exit(1);
}


/*
|--------------------------------------------------------------------------
| 5. UNILAK MAPPINGS
|--------------------------------------------------------------------------
*/

section('5. UNILAK MAPPINGS');

try {

    $mappings = $engine->getMappings(
        'UNILAK',
        true
    );

    echo '[INFO] Total active UNILAK mappings: ' .
         count($mappings) .
         PHP_EOL;

    if (!$mappings) {

        echo '[ERROR] No UNILAK mappings found.' . PHP_EOL;

        exit(1);
    }

} catch (Throwable $e) {

    echo '[ERROR] Could not load UNILAK mappings.' . PHP_EOL;
    echo 'Message: ' . $e->getMessage() . PHP_EOL;

    exit(1);
}


/*
|--------------------------------------------------------------------------
| 6. CONVERT DATABASE DATA TO MAPPING SOURCE DATA
|--------------------------------------------------------------------------
|
| IMPORTANT:
|
| Your applications table uses names such as:
|
| full_name
| nid_passport
| education_school
| passport_photo
|
| The MappingEngine uses source_field values configured inside
| application_mappings.
|
| We therefore create a source-data array using ONLY information
| that exists in the application record.
|
|--------------------------------------------------------------------------
*/

section('6. DATABASE → MAPPING SOURCE DATA');


$sourceData = [];


/*
|--------------------------------------------------------------------------
| DIRECT FIELD MAPPINGS
|--------------------------------------------------------------------------
*/

$fieldMap = [

    'full_name'              => 'full_name',

    'email'                  => 'email',

    'phone'                  => 'phone',

    'nid_passport'           => 'nid_passport',

    'father_name'            => 'father_name',

    'father_phone'           => 'father_phone',

    'mother_name'            => 'mother_name',

    'mother_phone'           => 'mother_phone',

    'province'               => 'province',

    'district'               => 'district',

    'sector'                 => 'sector',

    'cell'                   => 'cell',

    'village'                => 'village',

    'address'                => 'address',

    'education_school'       => 'education_school',

    'education_combination'  => 'education_combination',

    'education_year'         => 'education_year',

    'applicant_type'         => 'applicant_type',

    'application_price'      => 'application_price',

    'passport_photo'         => 'passport_photo',

    'nid_photo'              => 'nid_photo',

    'result_slip'            => 'result_slip',

    'application_number'     => 'application_number',

    'index_number'            => 'index_number',

    'status'                 => 'status',

    'university_id'          => 'university_id',

    'department_id'          => 'department_id',

    'program_id'             => 'program_id'
];


foreach ($fieldMap as $sourceField => $databaseField) {

    if (
        array_key_exists(
            $databaseField,
            $application
        )
    ) {

        $sourceData[$sourceField] =
            $application[$databaseField];
    }
}


/*
|--------------------------------------------------------------------------
| SPECIAL SMARTAPPLY → UNILAK SOURCE ALIASES
|--------------------------------------------------------------------------
|
| These aliases only use data that already exists in the database.
|
|--------------------------------------------------------------------------
*/


/*
|--------------------------------------------------------------------------
| nationality
|--------------------------------------------------------------------------
|
| Your current applications table does NOT contain nationality.
|
| Therefore we DO NOT invent it.
|
| It will remain empty unless it exists elsewhere in the database.
|--------------------------------------------------------------------------
*/


/*
|--------------------------------------------------------------------------
| residence_place
|--------------------------------------------------------------------------
|
| We can use address if needed by the mapping configuration.
|
| This is still information from the application database.
|--------------------------------------------------------------------------
*/

if (
    !isset($sourceData['residence_place']) ||
    trim((string)$sourceData['residence_place']) === ''
) {

    if (
        isset($application['address']) &&
        trim((string)$application['address']) !== ''
    ) {

        $sourceData['residence_place'] =
            $application['address'];
    }
}


/*
|--------------------------------------------------------------------------
| emergency_phone
|--------------------------------------------------------------------------
|
| Use father_phone only if an emergency_phone field does not exist
| and only because that value already exists in the application.
|
| If you don't want this assumption later, we can remove it.
|--------------------------------------------------------------------------
*/

if (
    !isset($sourceData['emergency_phone']) ||
    trim((string)$sourceData['emergency_phone']) === ''
) {

    if (
        isset($application['father_phone']) &&
        trim((string)$application['father_phone']) !== ''
    ) {

        $sourceData['emergency_phone'] =
            $application['father_phone'];
    }
}


/*
|--------------------------------------------------------------------------
| secondary_school
|--------------------------------------------------------------------------
*/

if (
    !isset($sourceData['secondary_school']) ||
    trim((string)$sourceData['secondary_school']) === ''
) {

    if (
        isset($application['education_school']) &&
        trim((string)$application['education_school']) !== ''
    ) {

        $sourceData['secondary_school'] =
            $application['education_school'];
    }
}


/*
|--------------------------------------------------------------------------
| combination
|--------------------------------------------------------------------------
*/

if (
    !isset($sourceData['combination']) ||
    trim((string)$sourceData['combination']) === ''
) {

    if (
        isset($application['education_combination']) &&
        trim((string)$application['education_combination']) !== ''
    ) {

        $sourceData['combination'] =
            $application['education_combination'];
    }
}


/*
|--------------------------------------------------------------------------
| year_of_passing
|--------------------------------------------------------------------------
*/

if (
    !isset($sourceData['year_of_passing']) ||
    trim((string)$sourceData['year_of_passing']) === ''
) {

    if (
        isset($application['education_year']) &&
        trim((string)$application['education_year']) !== ''
    ) {

        $sourceData['year_of_passing'] =
            $application['education_year'];
    }
}


/*
|--------------------------------------------------------------------------
| id_passport
|--------------------------------------------------------------------------
*/

if (
    !isset($sourceData['id_passport']) ||
    trim((string)$sourceData['id_passport']) === ''
) {

    if (
        isset($application['nid_passport']) &&
        trim((string)$application['nid_passport']) !== ''
    ) {

        $sourceData['id_passport'] =
            $application['nid_passport'];
    }
}


/*
|--------------------------------------------------------------------------
| degree_certificate_file
|--------------------------------------------------------------------------
|
| We only use an existing uploaded document.
|
| Your current applications table has:
|
| result_slip
|
| so we use it only as a source for testing the document mapping.
|--------------------------------------------------------------------------
*/

if (
    !isset($sourceData['degree_certificate_file']) ||
    trim((string)$sourceData['degree_certificate_file']) === ''
) {

    if (
        isset($application['result_slip']) &&
        trim((string)$application['result_slip']) !== ''
    ) {

        $sourceData['degree_certificate_file'] =
            $application['result_slip'];
    }
}


/*
|--------------------------------------------------------------------------
| transcript_file
|--------------------------------------------------------------------------
|
| Your current applications table does not have a transcript field.
|
| Therefore leave it empty.
|--------------------------------------------------------------------------
*/


/*
|--------------------------------------------------------------------------
| id_file
|--------------------------------------------------------------------------
*/

if (
    !isset($sourceData['id_file']) ||
    trim((string)$sourceData['id_file']) === ''
) {

    if (
        isset($application['nid_photo']) &&
        trim((string)$application['nid_photo']) !== ''
    ) {

        $sourceData['id_file'] =
            $application['nid_photo'];
    }
}


/*
|--------------------------------------------------------------------------
| passport_photo
|--------------------------------------------------------------------------
*/

if (
    isset($application['passport_photo']) &&
    trim((string)$application['passport_photo']) !== ''
) {

    $sourceData['passport_photo'] =
        $application['passport_photo'];
}


/*
|--------------------------------------------------------------------------
| SHOW SOURCE DATA
|--------------------------------------------------------------------------
*/

foreach ($sourceData as $field => $value) {

    if ($value === null || trim((string)$value) === '') {

        echo str_pad(
            $field,
            32
        ) . ': [EMPTY]' . PHP_EOL;

    } else {

        echo str_pad(
            $field,
            32
        ) . ': ' . $value . PHP_EOL;
    }
}


/*
|--------------------------------------------------------------------------
| 7. IMPORTANT UNILAK VALUES
|--------------------------------------------------------------------------
|
| UNILAK mappings may use fields such as:
|
| campus
| faculty
| programme
| option
| study_time
|
| These are NOT automatically invented.
|
| If they can be derived from existing IDs later, we will map them
| using the actual SmartApply programs/universities tables.
|
|--------------------------------------------------------------------------
*/


section('7. UNILAK FORM FIELD MAPPINGS');


foreach ($mappings as $mapping) {

    $sourceField =
        (string)$mapping['source_field'];

    $portalField =
        (string)$mapping['portal_field'];

    $portalType =
        (string)$mapping['portal_field_type'];

    $portalValue =
        $mapping['portal_value'];

    $hasSource =
        array_key_exists(
            $sourceField,
            $sourceData
        );

    $sourceValue =
        $hasSource
            ? $sourceData[$sourceField]
            : null;


    /*
    |--------------------------------------------------------------------------
    | APPLY TRANSFORMATION
    |--------------------------------------------------------------------------
    */

    if ($hasSource) {

        $mappedValue =
            $engine->transformValue(
                $sourceValue,
                (string)$mapping['transform_type']
            );

    } else {

        $mappedValue = null;
    }


    /*
    |--------------------------------------------------------------------------
    | SELECT / PORTAL VALUE
    |--------------------------------------------------------------------------
    */

    if (
        $mappedValue !== null &&
        $portalValue !== null &&
        $portalValue !== ''
    ) {

        $normalizedMapped =
            $engine->normalizeValue(
                $mappedValue,
                (string)$mapping['transform_type']
            );

        $normalizedPortal =
            $engine->normalizeValue(
                $portalValue,
                (string)$mapping['transform_type']
            );

        if (
            $normalizedMapped !== '' &&
            $normalizedMapped === $normalizedPortal
        ) {

            $mappedValue =
                $portalValue;
        }
    }


    echo PHP_EOL;

    echo 'Mapping ID   : ' .
         $mapping['id'] .
         PHP_EOL;

    echo 'Source Field : ' .
         $sourceField .
         PHP_EOL;

    echo 'Portal Field : ' .
         $portalField .
         PHP_EOL;

    echo 'Field Type   : ' .
         $portalType .
         PHP_EOL;

    if (
        $mappedValue === null ||
        trim((string)$mappedValue) === ''
    ) {

        echo 'DATABASE     : [EMPTY]' . PHP_EOL;

    } else {

        echo 'DATABASE     : ' .
             $mappedValue .
             PHP_EOL;
    }

    if (
        $portalValue !== null &&
        $portalValue !== ''
    ) {

        echo 'Portal Value : ' .
             $portalValue .
             PHP_EOL;
    }

    echo 'Required     : ' .
         (
             (int)$mapping['is_required'] === 1
                 ? 'YES'
                 : 'NO'
         ) .
         PHP_EOL;

    echo 'Postback     : ' .
         (
             (int)$mapping['requires_postback'] === 1
                 ? 'YES'
                 : 'NO'
         ) .
         PHP_EOL;
}


/*
|--------------------------------------------------------------------------
| 8. BUILD REAL PAYLOAD
|--------------------------------------------------------------------------
*/

section('8. BUILD UNILAK PAYLOAD');

try {

    $payload =
        $engine->buildPayload(
            'UNILAK',
            $sourceData
        );

    echo '[OK] UNILAK payload generated.' .
         PHP_EOL;

    echo 'Payload items: ' .
         count($payload) .
         PHP_EOL;

} catch (Throwable $e) {

    echo '[ERROR] Payload generation failed.' .
         PHP_EOL;

    echo 'Message: ' .
         $e->getMessage() .
         PHP_EOL;

    exit(1);
}


/*
|--------------------------------------------------------------------------
| 9. PAYLOAD TABLE
|--------------------------------------------------------------------------
*/

section('9. FINAL DATABASE → UNILAK PAYLOAD');


if (!$payload) {

    echo '[WARNING] Payload is empty.' . PHP_EOL;

} else {

    foreach ($payload as $item) {

        echo PHP_EOL;

        echo '#' .
             ($item['mapping_id'] ?? '?') .
             ' | ' .
             ($item['source_field'] ?? '') .
             ' → ' .
             ($item['portal_field'] ?? '') .
             PHP_EOL;

        echo 'VALUE: ' .
             (
                 $item['value'] === null ||
                 $item['value'] === ''
                     ? '[EMPTY]'
                     : $item['value']
             ) .
             PHP_EOL;

        echo 'TYPE: ' .
             ($item['portal_field_type'] ?? '') .
             PHP_EOL;

        echo 'REQUIRED: ' .
             (
                 !empty($item['is_required'])
                     ? 'YES'
                     : 'NO'
             ) .
             PHP_EOL;

        echo 'POSTBACK: ' .
             (
                 !empty($item['requires_postback'])
                     ? 'YES'
                     : 'NO'
             ) .
             PHP_EOL;
    }
}


/*
|--------------------------------------------------------------------------
| 10. VALIDATION
|--------------------------------------------------------------------------
*/

section('10. UNILAK VALIDATION');


try {

    $errors =
        $engine->validate(
            'UNILAK',
            $sourceData
        );

    if (!$errors) {

        echo '[OK] No required mapped fields are missing.' .
             PHP_EOL;

    } else {

        echo '[WARNING] Missing required fields: ' .
             count($errors) .
             PHP_EOL;

        foreach ($errors as $error) {

            echo '- ' .
                 $error['source_field'] .
                 ': ' .
                 $error['message'] .
                 PHP_EOL;
        }
    }

} catch (Throwable $e) {

    echo '[ERROR] Validation failed.' .
         PHP_EOL;

    echo 'Message: ' .
         $e->getMessage() .
         PHP_EOL;
}


/*
|--------------------------------------------------------------------------
| 11. SUMMARY
|--------------------------------------------------------------------------
*/

section('11. SUMMARY');

echo '[OK] Database connection works.' . PHP_EOL;

echo '[OK] Application ID ' .
     $applicationId .
     ' loaded.' .
     PHP_EOL;

echo '[OK] MappingEngine works.' .
     PHP_EOL;

echo '[OK] UNILAK mappings loaded: ' .
     count($mappings) .
     PHP_EOL;

echo '[OK] Database → Mapping source data prepared.' .
     PHP_EOL;

echo '[OK] UNILAK payload generation completed.' .
     PHP_EOL;

echo PHP_EOL;

line('=');

echo 'SMARTAPPLY UNILAK DATABASE MAPPING TEST COMPLETED.' .
     PHP_EOL;

line('=');
