<?php

declare(strict_types=1);

namespace Dealerdirect\Agreements\Tests\Utils;

use Dealerdirect\Agreements\Tests\TestCase;
use Dealerdirect\Agreements\Tests\Traits\DataObjectFixtures;
use Dealerdirect\Agreements\Utils\GeneralUtils;
use DealerDirect\Generic\Category\Country;
use DealerDirect\Generic\Category\Gender;
use DealerDirect\Generic\Category\Locale;
use DealerDirect\Generic\Category\Site;
use DealerDirect\Generic\Category\VehicleType;

/**
 * @covers \Dealerdirect\Agreements\Utils\GeneralUtils
 * @uses \Dealerdirect\Agreements\DataObjects\Conditions
 */
final class GeneralUtilsTest extends TestCase
{
    use DataObjectFixtures;

    public function test_sanitize_phone_number_returns_sanitized_phone_number(): void
    {
        $countryId = Country::NETHERLANDS;
        $phone = '+31 6 12345678';
        $expected = '+31612345678';

        $actual = GeneralUtils::sanitizePhoneNumber($countryId, $phone);

        $this->assertSame($expected, $actual);
    }

    public function test_combine_phone_numbers_combines_phone_numbers_with_separator(): void
    {
        $phone1 = '+31612345678';
        $phone2 = '+31698765432';
        $countryId = Country::NETHERLANDS;
        $expected = '+31612345678 / +31698765432';

        $actual = GeneralUtils::combinePhoneNumbers($phone1, $phone2, $countryId);

        $this->assertSame($expected, $actual);
    }

    /**
     * @dataProvider provideYesNoValues
     */
    public function test_translate_yes_no_translates_boolean_value_to_string_based_on_locale(
        bool $value,
        string $locale,
        string $expected
    ): void {
        $actual = GeneralUtils::translateYesNo($value, $locale);

        $this->assertSame($expected, $actual);
    }

    public function test_is_motor_returns_true_for_motor_vehicle_type(): void
    {
        $vehicleType = VehicleType::MOTOR;

        $actual = GeneralUtils::isMotor($vehicleType);

        $this->assertTrue($actual);
    }

    public function test_is_car_returns_true_for_car_vehicle_type(): void
    {
        $vehicleType = VehicleType::CAR;

        $actual = GeneralUtils::isCar($vehicleType);

        $this->assertTrue($actual);
    }

    public function test_is_bicycle_returns_true_for_bicycle_vehicle_type(): void
    {
        $vehicleType = VehicleType::BICYCLE;

        $actual = GeneralUtils::isBicycle($vehicleType);

        $this->assertTrue($actual);
    }

    public function test_get_locale_by_company_lang_returns_locale_based_on_language(): void
    {
        $lang = 1;
        $expected = Locale::NL_NL;

        $actual = GeneralUtils::getLocaleByCompanyLang($lang);

        $this->assertSame($expected, $actual);
    }

    public function test_get_site_data_by_reference_returns_site_data_based_on_reference_and_vehicle_type(): void
    {
        $reference = Site::REF_CAR_NL;
        $vehicleType = VehicleType::CAR;
        $expected = [
            'locale' => Locale::NL_NL,
            'vehicleType' => VehicleType::CAR,
            'labelName' => 'Ikwilvanmijnautoaf.nl',
        ];

        $actual = GeneralUtils::getSiteDataByReference($reference, $vehicleType);

        $this->assertSame($expected, $actual);
    }

    public function test_get_agent_phone_by_reference_returns_agent_phone_number_based_on_reference(): void
    {
        $reference = Site::REF_MOTO_NL;
        $expected = '053 - 20 844 49';

        $actual = GeneralUtils::getAgentPhoneByReference($reference);

        $this->assertSame($expected, $actual);
    }

    public function test_format_date_or_default_formats_date(): void
    {
        $date = '2022-01-01';
        $format = 'd-m-Y';
        $default = '-';
        $expected = '01-01-2022';

        $actual = GeneralUtils::formatDateOrDefault($date, $format, $default);

        $this->assertSame($expected, $actual);
    }

    public function test_format_date_or_default_returns_default(): void
    {
        $date = '';
        $format = 'd-m-Y';
        $default = '-';
        $expected = '-';

        $actual = GeneralUtils::formatDateOrDefault($date, $format, $default);

        $this->assertSame($expected, $actual);
    }

    /**
     * @dataProvider provideSalutations
     */
    public function test_get_salutation_by_gender_returns_salutation_based_on_locale_and_gender(
        string $locale,
        int $gender,
        string $expected
    ): void {
        $actual = GeneralUtils::getSalutationByGender($locale, $gender);

        $this->assertSame($expected, $actual);
    }

    /**
     * @dataProvider provideSurveyAnswers
     *
     * @param array<string,string|int>|string|null $answer
     */
    public function test_format_survey_answer_formats_survey_answer_array(
        array|string|null $answer,
        string $expected
    ): void {
        $actual = GeneralUtils::formatSurveyAnswer($answer);

        $this->assertSame($expected, $actual);
    }

    /**
     * @dataProvider provideVehicleTypesAndReferences
     */
    public function test_get_vehicle_type_by_site_reference(string $vehicleType, int $reference): void
    {
        $actual = GeneralUtils::getVehicleTypeBySiteReference($reference);

        $this->assertSame($vehicleType, $actual);
    }

    public function test_encrypt_value(): void
    {
        $key = 'EmsbBUFwIbL2Sq2vBj519AyE8Gazb2Z6nUOPHPQPnX4';
        $value = 'some value';

        $actual = GeneralUtils::encrypt($key, $value);

        $this->assertNotSame($value, $actual);
    }

    /**
     * @runInSeparateProcess
     *
     * @uses \Dealerdirect\Agreements\Utils\Translator
     * @uses \Dealerdirect\Agreements\DataObjects\Contact
     * @uses \Dealerdirect\Agreements\Enums\Locale
     * @uses \Dealerdirect\Agreements\DataObjects\Vehicle
     */
    public function test_get_translator(): void
    {
        $actual = GeneralUtils::getTranslator(
            self::fixtureSalesAgreement()
        );

        $this->assertInstanceOf(\Dealerdirect\Agreements\Utils\Translator::class, $actual);
    }

    public function test_method_get_consumer_price(): void
    {
        $this->assertSame(7500, GeneralUtils::getConsumerPrice(8000, 500));
    }

    /**
     * @return array<int,array{0:bool,1:string,2:string}>
     */
    public static function provideYesNoValues(): array
    {
        return [
            0 => [
                false,
                Locale::DE_DE,
                'nein',
            ],
            1 => [
                false,
                Locale::FR_BE,
                'non',
            ],
            2 => [
                true,
                Locale::NL_NL,
                'ja',
            ],
        ];
    }

    /**
     * @return array<int,array{0:string,1:int,2:string}>
     */
    public static function provideSalutations(): array
    {
        return [
            0 => [
                Locale::DE_DE,
                Gender::FEMALE,
                'Sehr geehrte Frau',
            ],
            1 => [
                Locale::FR_BE,
                Gender::MALE,
                'Cher monsieur',
            ],
            2 => [
                Locale::NL_NL,
                Gender::UNKNOWN,
                '',
            ],
            3 => [
                Locale::FR_FR,
                Gender::FEMALE,
                'Chère madame',
            ],
        ];
    }

    /**
     * @return array<int,array<int,string|array<string,string>|null>>
     */
    public static function provideSurveyAnswers(): array
    {
        return [
            0 => [
                [
                    'answer' => 'Yes',
                    'comment' => 'Some comment',
                ],
                'Yes: Some comment',
            ],
            1 => [
                [
                    'answer' => 'No',
                    'comment' => '',
                ],
                'No',
            ],
            2 => [
                'Yes',
                'Yes',
            ],
            3 => [
                null,
                '',
            ],
        ];
    }

    /**
     * @return array<int,array{0:string,1:int}>
     */
    public static function provideVehicleTypesAndReferences(): array
    {
        return [
            0 => [
                VehicleType::CAR,
                Site::REF_CAR_NL,
            ],
            1 => [
                VehicleType::MOTOR,
                Site::REF_MOTO_DE,
            ],
            2 => [
                VehicleType::BICYCLE,
                Site::REF_BICYCLE_NL,
            ],
            3 => [
                VehicleType::SCOOTER,
                Site::REF_SCOOTER_NL,
            ]
        ];
    }
}
