<?php

namespace Tests\Feature\Call;

use App\Enums\CallEvents;
use App\Models\Call;
use App\Models\Category;
use App\Models\Permission;
use App\Models\User;
use Database\Seeders\EventSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Tests\TestCase;

class UpdateTest extends TestCase
{
    use RefreshDatabase, WithFaker;

    public function test_operator_is_not_authenticated(): void
    {
        $response = $this->postJson(route('calls.update', ['call' => 1]));

        $response->assertUnauthorized();
    }

    public function test_operator_without_unappropriated_permission_is_forbidden_to_access_calls_data(): void
    {
        $telephoneId = 'tel-' . $this->faker->unique()->numerify('###');

        $user = User::factory()
            ->create([
                'telephone_id' => $telephoneId,
            ]);

        $call = Call::factory()->create([
            'telephone_id' => $telephoneId,
        ]);

        $response = $this->actingAs($user)->postJson(route('calls.update', ['call' => $call->id]));

        $response->assertForbidden();
    }

    public function test_operator_can_not_access_to_other_operators_calls(): void
    {

        $telephoneId = 'tel-' . $this->faker->unique()->numerify('###');

        $user = User::factory()
            ->create([
                'telephone_id' => $telephoneId,
            ]);

        $another_operator = User::factory([
            'id' => $this->faker->randomNumber(2, true)
        ])->create();

        $call = Call::factory([
            'telephone_id' => $another_operator->telephone_id
        ])->create();

        $response = $this->actingAs($user)->postJson(route('calls.update', ['call' => $call->id]));

        $response->assertForbidden();
    }


    public function test_non_owner_user_cannot_update_call(): void
    {
        $callOwner = User::factory()->create([
            'telephone_id' => 'tel-' . $this->faker->unique()->numerify('###'),
        ]);

        $call = Call::factory()->create([
            'telephone_id' => $callOwner->telephone_id,
        ]);

        $user = User::factory()->create();

        $response = $this->actingAs($user)->postJson(route('calls.update', $call->id), [
            'category_id' => $this->faker->randomNumber(),
            'subcategory_id' =>  $this->faker->randomNumber(),
            'description' => $this->faker->sentence
        ]);

        $response->assertForbidden();
    }

    public function test_validation_fails_when_required_fields_are_missing(): void
    {
        $telephoneId = 'tel-' . $this->faker->unique()->numerify('###');

        $user = User::factory()
            ->has(Permission::factory([
                'name' => 'manage_calls',
                'name_fa' => 'مدیریت تماس‌ها',
            ]))
            ->create([
                'telephone_id' => $telephoneId,
            ]);

        $call = Call::factory()->create([
            'telephone_id' => $telephoneId,
        ]);

        $response = $this->actingAs($user)->postJson(route('calls.update', $call->id), []);

        $response->assertUnprocessable()
            ->assertInvalid([
                'category_id' => __('validation.required', ['attribute' => 'موضوع']),
                'subcategory_id' => __('validation.required', ['attribute' => 'زیر موضوع']),
            ]);
    }

    public function test_category_id_and_subcategory_id_must_be_integers(): void
    {
        $telephoneId = 'tel-' . $this->faker->unique()->numerify('###');

        $user = User::factory()
            ->has(Permission::factory([
                'name' => 'manage_calls',
                'name_fa' => 'مدیریت تماس‌ها',
            ]))
            ->create([
                'telephone_id' => $telephoneId,
            ]);

        $call = Call::factory()->create([
            'telephone_id' =>$user->telephone_id,
        ]);

        $response =  $this->actingAs($user)->postJson(route('calls.update', $call->id), [
            'category_id' =>$this->faker->sentence(3),
            'subcategory_id' =>  $this->faker->sentence(3),
            'description' => $this->faker->sentence,
        ]);

        $response->assertUnprocessable()
            ->assertInvalid([
                'category_id' => __('validation.integer', ['attribute' => 'موضوع']),
                'subcategory_id' => __('validation.integer', ['attribute' => 'زیر موضوع']),
            ]);
    }

    public function test_description_field_must_be_string(): void
    {
        $telephoneId = 'tel-' . $this->faker->unique()->numerify('###');

        $user = User::factory()
            ->has(Permission::factory([
                'name' => 'manage_calls',
                'name_fa' => 'مدیریت تماس‌ها',
            ]))
            ->create([
                'telephone_id' => $telephoneId,
            ]);

        $call = Call::factory()->create([
            'telephone_id' => $telephoneId,
        ]);



        $response = $this->actingAs($user)->postJson(route('calls.update', $call->id), [
            'category_id' => $this->faker->randomNumber(),
            'subcategory_id' =>  $this->faker->randomNumber(),
            'description' => $this->faker->randomNumber(),
        ]);

        $response->assertUnprocessable()
            ->assertInvalid([
                'description' => __('validation.string', ['attribute' => 'توضیحات']),
            ]);
    }

    public function test_combination_of_category_and_subcategory_must_exist(): void
    {
        $telephoneId = 'tel-' . $this->faker->unique()->numerify('###');

        $user = User::factory()
            ->has(Permission::factory([
                'name' => 'manage_calls',
                'name_fa' => 'مدیریت تماس‌ها',
            ]))
            ->create([
                'telephone_id' => $telephoneId,
            ]);

        $call = Call::factory()->create([
            'telephone_id' => $telephoneId,
        ]);



        $response =  $this->actingAs($user)->postJson(route('calls.update', $call->id), [
            'category_id' => $this->faker->randomNumber(),
            'subcategory_id' =>  $this->faker->randomNumber(),
            'description' => $this->faker->sentence,
        ]);

        $response->assertUnprocessable()
            ->assertInvalid([
                'category' => __('messages.combination_of_category_and_subcategory_does_not_exist'),
            ]);
    }

    public function test_operator_can_update_call_successfully(): void
    {
        $telephoneId = 'tel-' . $this->faker->unique()->numerify('###');

        $user = User::factory()
            ->has(Permission::factory([
                'name' => 'manage_calls',
                'name_fa' => 'مدیریت تماس‌ها',
            ]))
            ->create([
                'telephone_id' => $telephoneId,
            ]);

        $call = Call::factory()->create([
            'telephone_id' => $telephoneId,
        ]);

        $this->seed(EventSeeder::class);

        $category = Category::factory()->create();
        $description = $this->faker->sentence;

        $response = $this->actingAs($user)->postJson(route('calls.update', $call->id), [
            'category_id' => $category->category_id,
            'subcategory_id' => $category->subcategory_id,
            'description' => $description,
            ]);

        $response->assertOk()
            ->assertJson([
                'message' => __('messages.successful'),
            ]);

        $this->assertDatabaseHas('calls', [
            'id' => $call->id,
            'category_id' => $category->category_id,
            'subcategory_id' => $category->subcategory_id,
            'description' => $description,
            ]);

        $this->assertDatabaseHas('call_histories', [
            'call_id' => $call->id,
            'event_id' => CallEvents::OPERATOR_STORED_CALL_DATA,
        ]);
    }
}
