<?php

namespace Tests\Feature;

use App\Models\Profile;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class SettingsApiTest extends TestCase
{
    use RefreshDatabase;

    public function test_authenticated_user_can_get_settings(): void
    {
        $user = User::factory()->create();
        Profile::factory()->create(['user_id' => $user->id, 'settings' => null]);

        $response = $this->actingAs($user)->getJson('/api/v1/settings');

        $response->assertOk();
        $response->assertJsonStructure([
            'data' => [
                'language',
                'ui_mode',
                'notifications' => [
                    'push_enabled',
                ],
            ],
        ]);
        $response->assertJsonPath('data.language', 'en');
        $response->assertJsonPath('data.ui_mode', 'system');
        $response->assertJsonPath('data.notifications.push_enabled', true);
    }

    public function test_authenticated_user_can_get_existing_settings(): void
    {
        $user = User::factory()->create();
        Profile::factory()->create([
            'user_id' => $user->id,
            'settings' => [
                'language' => 'ar',
                'ui_mode' => 'dark',
                'notifications' => [
                    'push_enabled' => false,
                ],
            ],
        ]);

        $response = $this->actingAs($user)->getJson('/api/v1/settings');

        $response->assertOk();
        $response->assertJsonPath('data.language', 'ar');
        $response->assertJsonPath('data.ui_mode', 'dark');
        $response->assertJsonPath('data.notifications.push_enabled', false);
    }

    public function test_authenticated_user_can_update_all_settings(): void
    {
        $user = User::factory()->create();
        Profile::factory()->create(['user_id' => $user->id]);

        $response = $this->actingAs($user)->putJson('/api/v1/settings', [
            'language' => 'fr',
            'ui_mode' => 'light',
            'notifications' => [
                'push_enabled' => false,
            ],
        ]);

        $response->assertOk();
        $response->assertJsonPath('data.language', 'fr');
        $response->assertJsonPath('data.ui_mode', 'light');
        $response->assertJsonPath('data.notifications.push_enabled', false);

        $this->assertDatabaseHas('profiles', [
            'user_id' => $user->id,
        ]);
    }

    public function test_authenticated_user_can_partially_update_settings(): void
    {
        $user = User::factory()->create();
        Profile::factory()->create([
            'user_id' => $user->id,
            'settings' => [
                'language' => 'en',
                'ui_mode' => 'system',
                'notifications' => [
                    'push_enabled' => true,
                ],
            ],
        ]);

        $response = $this->actingAs($user)->patchJson('/api/v1/settings', [
            'ui_mode' => 'dark',
        ]);

        $response->assertOk();
        $response->assertJsonPath('data.language', 'en');
        $response->assertJsonPath('data.ui_mode', 'dark');
        $response->assertJsonPath('data.notifications.push_enabled', true);
    }

    public function test_patch_preserves_unspecified_fields(): void
    {
        $user = User::factory()->create();
        Profile::factory()->create([
            'user_id' => $user->id,
            'settings' => [
                'language' => 'ar',
                'ui_mode' => 'dark',
                'notifications' => [
                    'push_enabled' => false,
                ],
            ],
        ]);

        $response = $this->actingAs($user)->patchJson('/api/v1/settings', [
            'notifications' => [
                'push_enabled' => true,
            ],
        ]);

        $response->assertOk();
        $response->assertJsonPath('data.language', 'ar');
        $response->assertJsonPath('data.ui_mode', 'dark');
        $response->assertJsonPath('data.notifications.push_enabled', true);
    }

    public function test_validates_language_enum(): void
    {
        $user = User::factory()->create();
        Profile::factory()->create(['user_id' => $user->id]);

        $response = $this->actingAs($user)->putJson('/api/v1/settings', [
            'language' => 'xyz',
            'ui_mode' => 'dark',
        ]);

        $response->assertStatus(422);
        $response->assertJsonValidationErrors(['language']);
    }

    public function test_validates_ui_mode_enum(): void
    {
        $user = User::factory()->create();
        Profile::factory()->create(['user_id' => $user->id]);

        $response = $this->actingAs($user)->putJson('/api/v1/settings', [
            'language' => 'en',
            'ui_mode' => 'invalid',
        ]);

        $response->assertStatus(422);
        $response->assertJsonValidationErrors(['ui_mode']);
    }

    public function test_validates_notification_booleans(): void
    {
        $user = User::factory()->create();
        Profile::factory()->create(['user_id' => $user->id]);

        $response = $this->actingAs($user)->putJson('/api/v1/settings', [
            'notifications' => [
                'push_enabled' => 'not-a-boolean',
            ],
        ]);

        $response->assertStatus(422);
        $response->assertJsonValidationErrors(['notifications.push_enabled']);
    }

    public function test_unauthenticated_user_cannot_get_settings(): void
    {
        $response = $this->getJson('/api/v1/settings');

        $response->assertStatus(401);
    }

    public function test_unauthenticated_user_cannot_update_settings(): void
    {
        $response = $this->putJson('/api/v1/settings', [
            'language' => 'en',
        ]);

        $response->assertStatus(401);
    }

    public function test_settings_work_with_no_profile(): void
    {
        $user = User::factory()->create();

        $response = $this->actingAs($user)->getJson('/api/v1/settings');

        $response->assertOk();
        $response->assertJsonPath('data.language', 'en');
        $response->assertJsonPath('data.ui_mode', 'system');
    }

    public function test_update_requires_profile(): void
    {
        $user = User::factory()->create();

        $response = $this->actingAs($user)->putJson('/api/v1/settings', [
            'language' => 'en',
        ]);

        $response->assertStatus(422);
    }
}
