<?php

use App\Services\ProfileService;
use CodeIgniter\Test\CIUnitTestCase;
use Config\Tieasy;

/**
 * @internal
 */
final class ProfileServiceTest extends CIUnitTestCase
{
    private ProfileService $profile;
    private Tieasy $config;

    protected function setUp(): void
    {
        parent::setUp();
        $this->profile = new ProfileService();
        $this->config  = new Tieasy();
    }

    public function testCollectIgnoresEmailAndUserId(): void
    {
        $raw = $this->profile->collect([
            'profile_name' => ' Ada Lovelace ',
            'email'        => 'attacker@evil.com',
            'user_id'      => '999',
            'age_group'    => '25–34',
            'gender'       => 'Female',
            'occupation'   => ' Engineer ',
            'phone'        => ' +1 (202) 555-0100 ',
        ]);

        $this->assertArrayNotHasKey('email', $raw);
        $this->assertArrayNotHasKey('user_id', $raw);
        $this->assertSame(' Ada Lovelace ', $raw['profile_name']);
        $this->assertSame([], $this->profile->validate($raw));

        $saved = $this->profile->normalized($raw);
        $this->assertSame('Ada Lovelace', $saved['profile_name']);
        $this->assertSame('Engineer', $saved['occupation']);
        $this->assertSame('+1 (202) 555-0100', $saved['phone']);
    }

    public function testBlankOptionalFieldsAreValid(): void
    {
        $raw = $this->profile->collect([
            'profile_name' => '',
            'age_group'    => '',
            'gender'       => '',
            'occupation'   => '',
            'phone'        => '',
        ]);
        $this->assertSame([], $this->profile->validate($raw));
        $norm = $this->profile->normalized($raw);
        $this->assertNull($norm['profile_name']);
        $this->assertNull($norm['age_group']);
        $this->assertNull($norm['gender']);
        $this->assertNull($norm['occupation']);
        $this->assertNull($norm['phone']);
    }

    public function testWhitespaceOnlyNameAndOccupationRejected(): void
    {
        $raw = $this->profile->collect([
            'profile_name' => '   ',
            'occupation'   => "\t  ",
            'age_group'    => '',
            'gender'       => '',
            'phone'        => '',
        ]);
        $errors = $this->profile->validate($raw);
        $this->assertSame(ProfileService::MSG_NAME_BLANK, $errors['profile_name']);
        $this->assertSame(ProfileService::MSG_OCC_BLANK, $errors['occupation']);
    }

    public function testNameAndOccupationMaxLength(): void
    {
        $tooLong = str_repeat('a', 101);
        $ok      = str_repeat('b', 100);

        $bad = $this->profile->collect([
            'profile_name' => $tooLong,
            'occupation'   => $tooLong,
            'age_group'    => '',
            'gender'       => '',
            'phone'        => '',
        ]);
        $errors = $this->profile->validate($bad);
        $this->assertSame(ProfileService::MSG_NAME_LENGTH, $errors['profile_name']);
        $this->assertSame(ProfileService::MSG_OCC_LENGTH, $errors['occupation']);

        $good = $this->profile->collect([
            'profile_name' => $ok,
            'occupation'   => 'O\'Neill & Co., Jr.',
            'age_group'    => '',
            'gender'       => '',
            'phone'        => '',
        ]);
        $this->assertSame([], $this->profile->validate($good));
    }

    public function testEveryValidAgeGroupIsAccepted(): void
    {
        foreach ($this->config->ageGroups as $group) {
            $raw    = $this->profile->collect(['age_group' => $group]);
            $errors = $this->profile->validate($raw);
            $this->assertArrayNotHasKey('age_group', $errors, $group);
            $this->assertSame($group, $this->profile->normalized($raw)['age_group']);
        }
    }

    public function testInvalidAgeGroupRejected(): void
    {
        foreach (['Under 16', '15-24', 'teen', '25-35'] as $invalid) {
            $raw    = $this->profile->collect(['age_group' => $invalid]);
            $errors = $this->profile->validate($raw);
            $this->assertSame(ProfileService::MSG_AGE, $errors['age_group'] ?? null, $invalid);
        }
    }

    public function testEveryValidGenderIsAccepted(): void
    {
        foreach ($this->config->genders as $gender) {
            $raw    = $this->profile->collect(['gender' => $gender]);
            $errors = $this->profile->validate($raw);
            $this->assertArrayNotHasKey('gender', $errors, $gender);
            $this->assertSame($gender, $this->profile->normalized($raw)['gender']);
        }
    }

    public function testInvalidGenderRejected(): void
    {
        $raw    = $this->profile->collect(['gender' => 'Unknown']);
        $errors = $this->profile->validate($raw);
        $this->assertSame(ProfileService::MSG_GENDER, $errors['gender']);
    }

    public function testInternationalPhoneAcceptedAndInvalidRejected(): void
    {
        $ok = $this->profile->collect(['phone' => '+91 (555) 555-0100']);
        $this->assertSame([], $this->profile->validate($ok));

        $long = $this->profile->collect(['phone' => '+123456789012345678901']);
        $this->assertSame(ProfileService::MSG_PHONE_LENGTH, $this->profile->validate($long)['phone']);

        $letters = $this->profile->collect(['phone' => 'call-me']);
        $this->assertSame(ProfileService::MSG_PHONE_INVALID, $this->profile->validate($letters)['phone']);
    }
}
