<?php

namespace Tests\Feature\Patients;

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

class PatientUpdateTest extends CIUnitTestCase
{
    use FeatureTestTrait;
    protected $endpoint = 'api/patient';

    protected function setUp(): void
    {
        parent::setUp();
    }
    /**
     * 400 - Validation Fail
     * Coba update tanpa field wajib → harus gagal validasi.
     */
    public function testUpdatePatientValidationFail()
    {
        $payload = [ 'InternalPID' => null, 'NameFirst' => '' ]; // Tidak valid
        $result = $this->withBodyFormat('json')->call('patch', $this->endpoint . '/1', $payload);

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

    /**
     * 404 / 500 - Update Nonexistent Patient
     * Coba update InternalPID yang tidak ada.
     */
    public function testUpdateNonexistentPatientShouldFail()
    {
        $faker = Factory::create('id_ID');

        $payload = [
            "PatientID"     => "SMAJ1",
            "EmailAddress1" => 'asaas7890@gmail.com',
            "Phone"          => $faker->numerify('08##########'),
            "MobilePhone"    => $faker->numerify('08##########'),
            'NameFirst'     => $faker->firstName,
            'NameLast'      => $faker->lastName,
            'Sex'        => '1',
            'Birthdate'     => $faker->date('Y-m-d'),
            'PatIdt'        => [ 'IdentifierType' => 'KTP', 'Identifier' => $faker->nik() ],
            'PatCom'        => $faker->sentence,
            'PatAtt'        => [
                [ 'Address' => '/api/upload/' . $faker->uuid . '.jpg' ],
            ],
        ];

        $result = $this->withBodyFormat('json')->call('patch', $this->endpoint . '/999999', $payload);

        $result->assertStatus(404);
    }

    /**
     * 201 - Update Success
     * Pastikan bisa update data yang valid (gunakan dummy data dari database).
     */
    public function testUpdatePatientSuccess()
    {
        $faker = Factory::create('id_ID');

        // NOTE: Sebaiknya ambil InternalPID yang sudah ada (mock atau dari DB fixture)
        // Untuk contoh ini kita asumsikan ada ID 1
        $payload = [
            "PatientID"     => "SMAJ1",
            'NameFirst'      => $faker->firstName,
            'NameMiddle'     => $faker->firstName,
            'NameLast'       => $faker->lastName,
            'Sex'         => '1',
            'Birthdate'      => $faker->date('Y-m-d'),
            'EmailAddress1'  => 'update_' . $faker->numberBetween(1,999) . '@gmail.com',
            "Phone"          => $faker->numerify('08##########'),
            "MobilePhone"    => $faker->numerify('08##########'),

            'PlaceOfBirth'   => $faker->city,
            'LinkTo'         => null,
            'PatIdt'         => [
                'IdentifierType' => 'KTP',
                'Identifier'     => $faker->nik(),
            ],
            "isDead" => (string) $faker->numberBetween(0, 1),
            'PatCom'         => 'Update be',
            'PatAtt'         => [
                [ 'Address' => '/api/upload/' . $faker->uuid . '.jpg' ],
            ],
        ];
            if($payload['isDead'] == '1') {
            $payload['DeathDateTime'] = $faker->date('Y-m-d H:i:s');
        } else {
            $payload['DeathDateTime'] = null;
        }

        $result = $this->withBodyFormat('json')->call('patch', $this->endpoint . '/1', $payload);
        $result->assertStatus(200);
        $json = $result->getJSON();
        $data = json_decode($json, true);
        $this->assertEquals('success', $data['status']);
    }

    /**
     * 201 - Update dengan PatCom kosong
     */
    public function testUpdateWithoutPatCom()
    {
        $faker = Factory::create('id_ID');

        $payload = [
            "PatientID"     => "SMAJ1",
            'NameFirst'      => $faker->firstName,
            'NameMiddle'     => $faker->firstName,
            'NameLast'       => $faker->lastName,
            'Sex'         => '1',
            'Birthdate'      => $faker->date('Y-m-d'),
            'EmailAddress1'  => 'update_' . $faker->numberBetween(1,999) . '@gmail.com',
            "Phone"          => $faker->numerify('08##########'),
            "MobilePhone"    => $faker->numerify('08##########'),
            'PlaceOfBirth'   => $faker->city,
            'LinkTo'         => null,
            'PatIdt'         => [
                'IdentifierType' => 'KTP',
                'Identifier'     => $faker->nik(),
            ],
            "isDead" => (string) $faker->numberBetween(0, 1),
            'PatCom'         => null,
            'PatAtt'         => [
                [ 'Address' => '/api/upload/' . $faker->uuid . '.jpg' ],
            ],
        ];
        if($payload['isDead'] == '1') {
            $payload['DeathDateTime'] = $faker->date('Y-m-d H:i:s');
        } else {
            $payload['DeathDateTime'] = null;
        }

        $result = $this->withBodyFormat('json')->call('patch', $this->endpoint . '/1', $payload);
        $result->assertStatus(200);
    }

    /**
     * 201 - Update tanpa PatAtt
     */
    public function testUpdateWithoutAttachments()
    {
        $faker = Factory::create('id_ID');

        $payload = [
            "PatientID"     => "SMAJ1",
            'NameFirst'      => $faker->firstName,
            'NameMiddle'     => $faker->firstName,
            'NameLast'       => $faker->lastName,
            'Sex'         => '1',
            'Birthdate'      => $faker->date('Y-m-d'),
            'EmailAddress1'  => 'update_' . $faker->numberBetween(1,999) . '@gmail.com',
            "Phone"          => $faker->numerify('08##########'),
            "MobilePhone"    => $faker->numerify('08##########'),
            'PlaceOfBirth'   => $faker->city,
            'LinkTo'         => null,
            'PatIdt'         => [
                'IdentifierType' => 'KTP',
                'Identifier'     => $faker->nik(),
            ],
            "isDead" => (string) $faker->numberBetween(0, 1),
            'PatCom'         => null,
            'PatAtt'         => [],
        ];
        if($payload['isDead'] == '1') {
            $payload['DeathDateTime'] = $faker->date('Y-m-d H:i:s');
        } else {
            $payload['DeathDateTime'] = null;
        }

        $result = $this->withBodyFormat('json')->call('patch', $this->endpoint . '/1', $payload);
        $result->assertStatus(200);
    }

    /**
     * 201 - Update tanpa PatAtt
     */
    public function testUpdateWithAttachments()
    {
        $faker = Factory::create('id_ID');

        $payload = [
            "PatientID"     => "SMAJ1",
            'NameFirst'      => $faker->firstName,
            'NameMiddle'     => $faker->firstName,
            'NameLast'       => $faker->lastName,
            'Sex'         => '1',
            'Birthdate'      => $faker->date('Y-m-d'),
            'EmailAddress1'  => 'update_' . $faker->numberBetween(1,999) . '@gmail.com',
            "Phone"          => $faker->numerify('08##########'),
            "MobilePhone"    => $faker->numerify('08##########'),
            'PlaceOfBirth'   => $faker->city,
            'LinkTo'         => null,
            'PatIdt'         => [
                'IdentifierType' => 'KTP',
                'Identifier'     => $faker->nik(),
            ],
            "isDead" => (string) $faker->numberBetween(0, 1),
            'PatCom'         => null,
            'PatAtt'         => [
                [ 'Address' => '/api/upload/' . $faker->uuid . '.jpg' ],
            ],
        ];
        if($payload['isDead'] == '1') {
            $payload['DeathDateTime'] = $faker->date('Y-m-d H:i:s');
        } else {
            $payload['DeathDateTime'] = null;
        }

        $result = $this->withBodyFormat('json')->call('patch', $this->endpoint . '/1', $payload);
        $result->assertStatus(200);
    }

    public function testUpdatePatientWithSimIdentifierSuccess()
    {
        $faker = Factory::create('id_ID');

        $payload = [
            'PatientID'     => 'SMAJ1',
            'NameFirst'     => $faker->firstName,
            'NameMiddle'    => $faker->firstName,
            'NameLast'      => $faker->lastName,
            'Sex'           => '1',
            'Birthdate'     => $faker->date('Y-m-d'),
            'EmailAddress1' => 'update_' . $faker->numberBetween(1, 999) . '@gmail.com',
            'Phone'         => $faker->numerify('08##########'),
            'MobilePhone'   => $faker->numerify('08##########'),
            'PlaceOfBirth'  => $faker->city,
            'PatIdt'        => [
                'IdentifierType' => 'SIM',
                'Identifier'     => '12345321323213232132',
            ],
        ];

        $result = $this->withBodyFormat('json')->call('patch', $this->endpoint . '/1', $payload);
        $result->assertStatus(200);
    }

    public function testPatchSingleFieldSuccess()
    {
        $faker = Factory::create('id_ID');

        $payload = [
            'NameFirst' => $faker->firstName,
        ];

        $result = $this->withBodyFormat('json')->call('patch', $this->endpoint . '/1', $payload);
        $result->assertStatus(200);
    }

    public function testPatchEmptyPayloadShouldFail()
    {
        $result = $this->withBodyFormat('json')->call('patch', $this->endpoint . '/1', []);
        $result->assertStatus(400);
    }

    public function testUpdatePatientWithSimIdentifierInvalidShouldFail()
    {
        $faker = Factory::create('id_ID');

        $payload = [
            'PatientID'     => 'SMAJ1',
            'NameFirst'     => $faker->firstName,
            'NameMiddle'    => $faker->firstName,
            'NameLast'      => $faker->lastName,
            'Sex'           => '1',
            'Birthdate'     => $faker->date('Y-m-d'),
            'EmailAddress1' => 'update_' . $faker->numberBetween(1, 999) . '@gmail.com',
            'Phone'         => $faker->numerify('08##########'),
            'MobilePhone'   => $faker->numerify('08##########'),
            'PlaceOfBirth'  => $faker->city,
            'PatIdt'        => [
                'IdentifierType' => 'SIM',
                'Identifier'     => '123456789012345678',
            ],
        ];

        $result = $this->withBodyFormat('json')->call('patch', $this->endpoint . '/1', $payload);
        $result->assertStatus(400);

        $json = $result->getJSON();
        $data = json_decode($json, true);
        $this->assertArrayHasKey('messages', $data);
        $this->assertArrayHasKey('PatIdt.Identifier', $data['messages']);
    }

    // /**
    //  * 500 - Invalid PatIdt
    //  */
    public function testUpdatePatIdtInvalid()
    {
        $faker = Factory::create('id_ID');

        $payload = [
            "PatientID"     => "SMAJ1",
            'NameFirst'      => $faker->firstName,
            'NameMiddle'     => $faker->firstName,
            'NameLast'       => $faker->lastName,
            'Sex'         => '1',
            'Birthdate'      => $faker->date('Y-m-d'),
            'EmailAddress1'  => 'update_' . $faker->numberBetween(1,999) . '@gmail.com',
            "Phone"          => $faker->numerify('08##########'),
            "MobilePhone"    => $faker->numerify('08##########'),
            'PlaceOfBirth'   => $faker->city,
            'LinkTo'         => null,
            'PatIdt'         => [
                'IdentifierType' => [],
                'Identifier'     => $faker->nik(),
            ],
            "isDead" => (string) $faker->numberBetween(0, 1),
            'PatCom'         => null,
            'PatAtt'         => [
                [ 'Address' => '/api/upload/' . $faker->uuid . '.jpg' ],
            ],
        ];
        if($payload['isDead'] == '1') {
            $payload['DeathDateTime'] = $faker->date('Y-m-d H:i:s');
        } else {
            $payload['DeathDateTime'] = null;
        }

        $result = $this->withBodyFormat('json')->call('patch', $this->endpoint . '/1', $payload);

        $result->assertStatus(400);
        $json = $result->getJSON();
        $data = json_decode($json, true);
        $this->assertArrayHasKey('messages', $data);
        $this->assertArrayHasKey('PatIdt.IdentifierType', $data['messages']);
    }

}
