<?php

namespace Tests\Feature\Patients;

use CodeIgniter\Test\FeatureTestTrait;
use CodeIgniter\Test\CIUnitTestCase;
use Faker\Factory;

/**
 * PatientDeleteTest
 * 
 * Test cases for Patient DELETE endpoint
 * Endpoint: DELETE api/patient
 * 
 * Test Cases:
 * 1. testDeleteWithoutInternalPID - 500 error when InternalPID not provided
 * 2. testDeleteWithNullInternalPID - 400 error when InternalPID is null
 * 3. testDeleteWithZeroInternalPID - 400 error when InternalPID is 0
 * 4. testDeleteWithEmptyStringInternalPID - 400 error when InternalPID is empty string
 * 5. testDeleteWithArrayInternalPID - 400 error when InternalPID is array
 * 6. testDeleteNotFound - 404 error when patient not found
 * 7. testDeleteSQLInjectionAttempt - 400 error when SQL injection attempted
 * 8. testDeleteSuccess - 200 success when valid delete (commented - requires DB setup)
 */
class PatientDeleteTest extends CIUnitTestCase
{
    use FeatureTestTrait;
    
    protected $endpoint = 'api/patient';

    protected function setUp(): void
    {
        parent::setUp();
    }

    /**
     * Test Case 1: Delete without InternalPID key
     * Expected: 500 Internal Server Error (Undefined array key)
     */
    public function testDeleteWithoutInternalPID() 
    {
        $result = $this->withBodyFormat('json')
                       ->delete($this->endpoint, []);

        $result->assertStatus(500);
        
        $json = $result->getJSON();
        $data = json_decode($json, true);
        
        $this->assertArrayHasKey('messages', $data);
    }

    /**
     * Test Case 2: Delete with null InternalPID
     * Expected: 400 Bad Request - Patient ID must be a valid integer
     */
    public function testDeleteWithNullInternalPID() 
    {
        $result = $this->withBodyFormat('json')
                       ->delete($this->endpoint, [
                            'InternalPID' => null,
                       ]);

        $result->assertStatus(400);
        $result->assertJSONFragment([
            'status' => 'error',
            'message' => 'Patient ID must be a valid integer.'
        ]);
    }

    /**
     * Test Case 3: Delete with zero InternalPID
     * Expected: 400 Bad Request - Patient ID must be a valid integer
     */
    public function testDeleteWithZeroInternalPID() 
    {
        $result = $this->withBodyFormat('json')
                       ->delete($this->endpoint, [
                            'InternalPID' => 0,
                       ]);

        $result->assertStatus(400);
        $result->assertJSONFragment([
            'status' => 'error',
            'message' => 'Patient ID must be a valid integer.'
        ]);
    }

    /**
     * Test Case 4: Delete with empty string InternalPID
     * Expected: 400 Bad Request - Patient ID must be a valid integer
     */
    public function testDeleteWithEmptyStringInternalPID() 
    {
        $result = $this->withBodyFormat('json')
                       ->delete($this->endpoint, [
                            'InternalPID' => '',
                       ]);

        $result->assertStatus(400);
        $result->assertJSONFragment([
            'status' => 'error',
            'message' => 'Patient ID must be a valid integer.'
        ]);
    }

    /**
     * Test Case 5: Delete with array InternalPID
     * Expected: 400 Bad Request - Patient ID must be a valid integer
     */
    public function testDeleteWithArrayInternalPID() 
    {
        $result = $this->withBodyFormat('json')
                       ->delete($this->endpoint, [
                            'InternalPID' => [],
                       ]);

        $result->assertStatus(400);
        $result->assertJSONFragment([
            'status' => 'error',
            'message' => 'Patient ID must be a valid integer.'
        ]);
    }

    /**
     * Test Case 6: Delete non-existent patient
     * Expected: 404 Not Found (or 500 if database not configured)
     */
    public function testDeleteNotFound() 
    {
        $testId = 9999999;

        $result = $this->withBodyFormat('json')
                       ->delete($this->endpoint, [
                            'InternalPID' => $testId
                       ]);

        // May return 404 (not found), 500 (database error), or null (connection issue)
        $statusCode = $result->getStatusCode();
        $this->assertTrue(
            in_array($statusCode, [404, 500]) || $statusCode === null,
            "Expected status code 404, 500, or null but got: " . var_export($statusCode, true)
        );
        
        $json = $result->getJSON();
        $data = json_decode($json, true);
        
        $this->assertArrayHasKey('messages', $data);
    }

    /**
     * Test Case 7: Delete with SQL injection attempt
     * Expected: 400 Bad Request - should be sanitized
     */
    public function testDeleteSQLInjectionAttempt() 
    {
        $result = $this->withBodyFormat('json')
                       ->delete($this->endpoint, [
                            'InternalPID' => "' OR 1=1 --"
                       ]);
        
        $result->assertStatus(400);
        $result->assertJSONFragment([
            'status' => 'error',
            'message' => 'Patient ID must be a valid integer.'
        ]);
    }

    /**
     * Test Case 8: Delete with negative number
     * Expected: 400 Bad Request - should reject negative numbers
     */
    public function testDeleteWithNegativeInternalPID() 
    {
        $result = $this->withBodyFormat('json')
                       ->delete($this->endpoint, [
                            'InternalPID' => -1,
                       ]);

        $result->assertStatus(400);
        $result->assertJSONFragment([
            'status' => 'error',
            'message' => 'Patient ID must be a valid integer.'
        ]);
    }

    /**
     * Test Case 9: Delete with string number
     * Expected: Depends on implementation - may accept "123" as valid
     */
    public function testDeleteWithStringNumber() 
    {
        $testId = "9999998";

        $result = $this->withBodyFormat('json')
                       ->delete($this->endpoint, [
                            'InternalPID' => $testId
                       ]);

        // Should either be 404 (not found), 200 (deleted), 500 (db error), or null (connection issue)
        $statusCode = $result->getStatusCode();
        $this->assertTrue(
            in_array($statusCode, [200, 404, 500]) || $statusCode === null,
            "Expected status code 200, 404, 500, or null but got: " . var_export($statusCode, true)
        );
    }

    // =====================================================
    // SUCCESS TEST CASES
    // NOTE: Uncomment these when you have proper DB seeding
    // =====================================================

    // /**
    //  * Test Case: Delete success
    //  * Expected: 200 OK - Patient deleted successfully
    //  * 
    //  * IMPORTANT: This test modifies database state.
    //  * Make sure you have proper seeding or use DatabaseTestTrait
    //  */
    // public function testDeleteSuccess() 
    // {
    //     // First create a patient to delete
    //     $faker = Factory::create('id_ID');
    //     
    //     $createPayload = [
    //         "PatientID"      => "DELTEST" . $faker->numberBetween(10000, 99999),
    //         "AlternatePID"   => "DELALT" . $faker->numberBetween(10000, 99999),
    //         "Prefix"         => "Mr.",
    //         "NameFirst"      => "ToBeDeleted",
    //         "NameLast"       => "Patient",
    //         "Sex"         => "5",
    //         "Birthdate"      => "1990-01-01",
    //     ];
    //     
    //     // Create the patient
    //     $createResult = $this->withBodyFormat('json')->post($this->endpoint, $createPayload);
    //     $createResult->assertStatus(201);
    //     
    //     // Get the created patient ID from response or database
    //     // Then delete it
    //     $testId = 3; // Replace with actual ID
    //     
    //     $result = $this->withBodyFormat('json')
    //                    ->delete($this->endpoint, [
    //                         'InternalPID' => $testId
    //                    ]);
    //
    //     $result->assertStatus(200);
    //     $result->assertJSONFragment([
    //         'status' => 'success',
    //         'message' => 'Patient ID with '.$testId.' deleted successfully.'
    //     ]);
    // }
}
