<?php

namespace Tests\Feature\User;

use App\Models\Members\User;
use App\Models\Members\UserTenant;
use App\Models\NotificationSetting;
use App\Models\Tenants\Tenant;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Tests\TestCase;

class NotificationSettingApiTest extends TestCase
{
    use DatabaseTransactions;

    private Tenant $tenant;

    private User $user;

    private string $apiKey;

    private string $token;

    protected function setUp(): void
    {
        parent::setUp();

        // 테스트용 API Key 생성
        $this->apiKey = 'test-api-key-'.uniqid();
        \DB::table('api_keys')->insert([
            'key' => $this->apiKey,
            'description' => 'Test API Key',
            'is_active' => true,
            'created_at' => now(),
            'updated_at' => now(),
        ]);

        // Tenant 생성 또는 기존 사용
        $this->tenant = Tenant::first() ?? Tenant::withoutEvents(function () {
            return Tenant::create([
                'company_name' => 'Test Company',
                'code' => 'TEST'.uniqid(),
                'email' => 'test@example.com',
                'phone' => '010-1234-5678',
            ]);
        });

        // User 생성
        $testUserId = 'testuser'.uniqid();
        $this->user = User::create([
            'user_id' => $testUserId,
            'name' => 'Test User',
            'email' => $testUserId.'@example.com',
            'password' => bcrypt('password123'),
        ]);

        // UserTenant 관계 생성
        UserTenant::create([
            'user_id' => $this->user->id,
            'tenant_id' => $this->tenant->id,
            'is_active' => true,
            'is_default' => true,
        ]);

        // 로그인 및 토큰 획득
        $this->loginAndGetToken();
    }

    protected function loginAndGetToken(): void
    {
        $response = $this->withHeaders([
            'X-API-KEY' => $this->apiKey,
            'Accept' => 'application/json',
        ])->postJson('/api/v1/login', [
            'user_id' => $this->user->user_id,
            'user_pwd' => 'password123',
        ]);

        $response->assertStatus(200);
        $this->token = $response->json('access_token');
    }

    protected function authenticatedRequest(string $method, string $uri, array $data = [])
    {
        return $this->withHeaders([
            'X-API-KEY' => $this->apiKey,
            'Authorization' => 'Bearer '.$this->token,
            'Accept' => 'application/json',
        ])->{$method.'Json'}($uri, $data);
    }

    // ==================== Get Settings Tests ====================

    public function test_can_get_notification_settings(): void
    {
        $response = $this->authenticatedRequest('get', '/api/v1/users/me/notification-settings');

        $response->assertStatus(200)
            ->assertJsonStructure([
                'success',
                'message',
                'data',
            ]);
    }

    public function test_notification_settings_returns_all_types(): void
    {
        // 기존 설정 생성
        foreach (NotificationSetting::getAllTypes() as $type) {
            NotificationSetting::updateOrCreate(
                [
                    'tenant_id' => $this->tenant->id,
                    'user_id' => $this->user->id,
                    'notification_type' => $type,
                ],
                NotificationSetting::getDefaultSettings($type)
            );
        }

        $response = $this->authenticatedRequest('get', '/api/v1/users/me/notification-settings');

        $response->assertStatus(200);

        $data = $response->json('data');
        $this->assertIsArray($data);
    }

    // ==================== Update Single Setting Tests ====================

    public function test_can_update_single_notification_setting(): void
    {
        $response = $this->authenticatedRequest('put', '/api/v1/users/me/notification-settings', [
            'notification_type' => NotificationSetting::TYPE_ORDER,
            'push_enabled' => true,
            'email_enabled' => true,
            'sms_enabled' => false,
            'in_app_enabled' => true,
            'kakao_enabled' => false,
        ]);

        $response->assertStatus(200);

        $this->assertDatabaseHas('notification_settings', [
            'tenant_id' => $this->tenant->id,
            'user_id' => $this->user->id,
            'notification_type' => NotificationSetting::TYPE_ORDER,
            'push_enabled' => true,
            'email_enabled' => true,
        ]);
    }

    public function test_cannot_update_setting_without_type(): void
    {
        $response = $this->authenticatedRequest('put', '/api/v1/users/me/notification-settings', [
            'push_enabled' => true,
        ]);

        $response->assertStatus(422);
    }

    public function test_cannot_update_setting_with_invalid_type(): void
    {
        $response = $this->authenticatedRequest('put', '/api/v1/users/me/notification-settings', [
            'notification_type' => 'invalid_type',
            'push_enabled' => true,
        ]);

        $response->assertStatus(422);
    }

    // ==================== Bulk Update Tests ====================

    public function test_can_bulk_update_notification_settings(): void
    {
        $response = $this->authenticatedRequest('put', '/api/v1/users/me/notification-settings/bulk', [
            'settings' => [
                [
                    'notification_type' => NotificationSetting::TYPE_ORDER,
                    'push_enabled' => true,
                    'email_enabled' => false,
                    'sms_enabled' => false,
                    'in_app_enabled' => true,
                    'kakao_enabled' => false,
                ],
                [
                    'notification_type' => NotificationSetting::TYPE_NOTICE,
                    'push_enabled' => true,
                    'email_enabled' => true,
                    'sms_enabled' => false,
                    'in_app_enabled' => true,
                    'kakao_enabled' => false,
                ],
            ],
        ]);

        $response->assertStatus(200);

        $this->assertDatabaseHas('notification_settings', [
            'tenant_id' => $this->tenant->id,
            'user_id' => $this->user->id,
            'notification_type' => NotificationSetting::TYPE_ORDER,
            'push_enabled' => true,
        ]);

        $this->assertDatabaseHas('notification_settings', [
            'tenant_id' => $this->tenant->id,
            'user_id' => $this->user->id,
            'notification_type' => NotificationSetting::TYPE_NOTICE,
            'email_enabled' => true,
        ]);
    }

    public function test_cannot_bulk_update_with_empty_settings(): void
    {
        $response = $this->authenticatedRequest('put', '/api/v1/users/me/notification-settings/bulk', [
            'settings' => [],
        ]);

        $response->assertStatus(422);
    }

    public function test_cannot_bulk_update_with_invalid_type_in_array(): void
    {
        $response = $this->authenticatedRequest('put', '/api/v1/users/me/notification-settings/bulk', [
            'settings' => [
                [
                    'notification_type' => 'invalid_type',
                    'push_enabled' => true,
                ],
            ],
        ]);

        $response->assertStatus(422);
    }

    // ==================== Security Default Settings Tests ====================

    public function test_security_type_has_email_enabled_by_default(): void
    {
        $defaults = NotificationSetting::getDefaultSettings(NotificationSetting::TYPE_SECURITY);

        $this->assertTrue($defaults['email_enabled']);
        $this->assertTrue($defaults['push_enabled']);
    }

    public function test_marketing_type_has_all_disabled_by_default(): void
    {
        $defaults = NotificationSetting::getDefaultSettings(NotificationSetting::TYPE_MARKETING);

        $this->assertFalse($defaults['email_enabled']);
        $this->assertFalse($defaults['push_enabled']);
        $this->assertFalse($defaults['sms_enabled']);
        $this->assertFalse($defaults['in_app_enabled']);
        $this->assertFalse($defaults['kakao_enabled']);
    }

    // ==================== Authentication Tests ====================

    public function test_cannot_access_settings_without_authentication(): void
    {
        $response = $this->withHeaders([
            'X-API-KEY' => $this->apiKey,
            'Accept' => 'application/json',
        ])->getJson('/api/v1/users/me/notification-settings');

        $response->assertStatus(401);
    }

    public function test_cannot_update_settings_without_authentication(): void
    {
        $response = $this->withHeaders([
            'X-API-KEY' => $this->apiKey,
            'Accept' => 'application/json',
        ])->putJson('/api/v1/users/me/notification-settings', [
            'notification_type' => NotificationSetting::TYPE_ORDER,
            'push_enabled' => true,
        ]);

        $response->assertStatus(401);
    }
}
