<?php

namespace Tests\Feature\BadDebt;

use App\Models\BadDebts\BadDebt;
use App\Models\BadDebts\BadDebtDocument;
use App\Models\BadDebts\BadDebtMemo;
use App\Models\Members\User;
use App\Models\Members\UserTenant;
use App\Models\Orders\Client;
use App\Models\Tenants\Tenant;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Tests\TestCase;

class BadDebtApiTest extends TestCase
{
    use DatabaseTransactions;

    private Tenant $tenant;

    private User $user;

    private Client $client;

    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,
        ]);

        // Client 생성
        $this->client = Client::create([
            'tenant_id' => $this->tenant->id,
            'name' => 'Test Client',
            'client_code' => 'CLI'.uniqid(),
            'created_by' => $this->user->id,
        ]);

        // 로그인 및 토큰 획득
        $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);
    }

    // ==================== BadDebt CRUD Tests ====================

    public function test_can_list_bad_debts(): void
    {
        BadDebt::create([
            'tenant_id' => $this->tenant->id,
            'client_id' => $this->client->id,
            'debt_amount' => 1000000,
            'status' => BadDebt::STATUS_COLLECTING,
            'overdue_days' => 30,
            'is_active' => true,
            'created_by' => $this->user->id,
            'updated_by' => $this->user->id,
        ]);

        $response = $this->authenticatedRequest('get', '/api/v1/bad-debts');

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

    public function test_can_get_bad_debt_summary(): void
    {
        // 상태별 악성채권 생성
        BadDebt::create([
            'tenant_id' => $this->tenant->id,
            'client_id' => $this->client->id,
            'debt_amount' => 1000000,
            'status' => BadDebt::STATUS_COLLECTING,
            'is_active' => true,
            'created_by' => $this->user->id,
            'updated_by' => $this->user->id,
        ]);

        BadDebt::create([
            'tenant_id' => $this->tenant->id,
            'client_id' => $this->client->id,
            'debt_amount' => 500000,
            'status' => BadDebt::STATUS_RECOVERED,
            'is_active' => true,
            'created_by' => $this->user->id,
            'updated_by' => $this->user->id,
        ]);

        $response = $this->authenticatedRequest('get', '/api/v1/bad-debts/summary');

        $response->assertStatus(200)
            ->assertJsonStructure([
                'success',
                'message',
                'data' => [
                    'total_amount',
                    'collecting_amount',
                    'legal_action_amount',
                    'recovered_amount',
                    'bad_debt_amount',
                ],
            ]);

        $data = $response->json('data');
        $this->assertEquals(1500000, $data['total_amount']);
        $this->assertEquals(1000000, $data['collecting_amount']);
        $this->assertEquals(500000, $data['recovered_amount']);
    }

    public function test_can_create_bad_debt(): void
    {
        $response = $this->authenticatedRequest('post', '/api/v1/bad-debts', [
            'client_id' => $this->client->id,
            'debt_amount' => 2000000,
            'status' => BadDebt::STATUS_COLLECTING,
            'overdue_days' => 45,
            'occurred_at' => now()->subDays(45)->format('Y-m-d'),
        ]);

        $response->assertStatus(201)
            ->assertJsonStructure([
                'success',
                'message',
                'data' => [
                    'id',
                    'client_id',
                    'debt_amount',
                    'status',
                ],
            ]);

        $this->assertDatabaseHas('bad_debts', [
            'client_id' => $this->client->id,
            'debt_amount' => 2000000,
            'status' => BadDebt::STATUS_COLLECTING,
            'tenant_id' => $this->tenant->id,
        ]);
    }

    public function test_can_show_bad_debt(): void
    {
        $badDebt = BadDebt::create([
            'tenant_id' => $this->tenant->id,
            'client_id' => $this->client->id,
            'debt_amount' => 1500000,
            'status' => BadDebt::STATUS_LEGAL_ACTION,
            'is_active' => true,
            'created_by' => $this->user->id,
            'updated_by' => $this->user->id,
        ]);

        $response = $this->authenticatedRequest('get', "/api/v1/bad-debts/{$badDebt->id}");

        $response->assertStatus(200)
            ->assertJsonStructure([
                'success',
                'message',
                'data' => [
                    'id',
                    'client_id',
                    'debt_amount',
                    'status',
                    'client',
                ],
            ])
            ->assertJson([
                'data' => [
                    'debt_amount' => '1500000.00',
                    'status' => BadDebt::STATUS_LEGAL_ACTION,
                ],
            ]);
    }

    public function test_can_update_bad_debt(): void
    {
        $badDebt = BadDebt::create([
            'tenant_id' => $this->tenant->id,
            'client_id' => $this->client->id,
            'debt_amount' => 1000000,
            'status' => BadDebt::STATUS_COLLECTING,
            'is_active' => true,
            'created_by' => $this->user->id,
            'updated_by' => $this->user->id,
        ]);

        $response = $this->authenticatedRequest('put', "/api/v1/bad-debts/{$badDebt->id}", [
            'status' => BadDebt::STATUS_LEGAL_ACTION,
            'debt_amount' => 1200000,
        ]);

        $response->assertStatus(200);

        $this->assertDatabaseHas('bad_debts', [
            'id' => $badDebt->id,
            'status' => BadDebt::STATUS_LEGAL_ACTION,
            'debt_amount' => 1200000,
        ]);
    }

    public function test_can_delete_bad_debt(): void
    {
        $badDebt = BadDebt::create([
            'tenant_id' => $this->tenant->id,
            'client_id' => $this->client->id,
            'debt_amount' => 500000,
            'status' => BadDebt::STATUS_COLLECTING,
            'is_active' => true,
            'created_by' => $this->user->id,
            'updated_by' => $this->user->id,
        ]);

        $response = $this->authenticatedRequest('delete', "/api/v1/bad-debts/{$badDebt->id}");

        $response->assertStatus(200);

        $this->assertSoftDeleted('bad_debts', [
            'id' => $badDebt->id,
        ]);
    }

    public function test_can_toggle_bad_debt_active(): void
    {
        $badDebt = BadDebt::create([
            'tenant_id' => $this->tenant->id,
            'client_id' => $this->client->id,
            'debt_amount' => 500000,
            'status' => BadDebt::STATUS_COLLECTING,
            'is_active' => true,
            'created_by' => $this->user->id,
            'updated_by' => $this->user->id,
        ]);

        $response = $this->authenticatedRequest('patch', "/api/v1/bad-debts/{$badDebt->id}/toggle");

        $response->assertStatus(200);

        $this->assertDatabaseHas('bad_debts', [
            'id' => $badDebt->id,
            'is_active' => false,
        ]);

        // 다시 토글
        $response = $this->authenticatedRequest('patch', "/api/v1/bad-debts/{$badDebt->id}/toggle");

        $response->assertStatus(200);

        $this->assertDatabaseHas('bad_debts', [
            'id' => $badDebt->id,
            'is_active' => true,
        ]);
    }

    // ==================== Document Tests ====================

    public function test_can_add_document_to_bad_debt(): void
    {
        $badDebt = BadDebt::create([
            'tenant_id' => $this->tenant->id,
            'client_id' => $this->client->id,
            'debt_amount' => 500000,
            'status' => BadDebt::STATUS_COLLECTING,
            'is_active' => true,
            'created_by' => $this->user->id,
            'updated_by' => $this->user->id,
        ]);

        // 테스트용 파일 생성 (files 테이블에)
        $fileId = \DB::table('files')->insertGetId([
            'tenant_id' => $this->tenant->id,
            'original_name' => 'test.pdf',
            'display_name' => 'test.pdf',
            'stored_name' => 'test_'.uniqid().'.pdf',
            'file_name' => 'test.pdf',
            'mime_type' => 'application/pdf',
            'file_size' => 1024,
            'file_path' => 'uploads/test.pdf',
            'created_by' => $this->user->id,
            'created_at' => now(),
            'updated_at' => now(),
        ]);

        $response = $this->authenticatedRequest('post', "/api/v1/bad-debts/{$badDebt->id}/documents", [
            'document_type' => 'tax_invoice',
            'file_id' => $fileId,
        ]);

        $response->assertStatus(201);

        $this->assertDatabaseHas('bad_debt_documents', [
            'bad_debt_id' => $badDebt->id,
            'document_type' => 'tax_invoice',
            'file_id' => $fileId,
        ]);
    }

    public function test_can_remove_document_from_bad_debt(): void
    {
        $badDebt = BadDebt::create([
            'tenant_id' => $this->tenant->id,
            'client_id' => $this->client->id,
            'debt_amount' => 500000,
            'status' => BadDebt::STATUS_COLLECTING,
            'is_active' => true,
            'created_by' => $this->user->id,
            'updated_by' => $this->user->id,
        ]);

        $document = BadDebtDocument::create([
            'bad_debt_id' => $badDebt->id,
            'document_type' => 'business_license',
            'file_id' => 1,
        ]);

        $response = $this->authenticatedRequest('delete', "/api/v1/bad-debts/{$badDebt->id}/documents/{$document->id}");

        $response->assertStatus(200);

        $this->assertDatabaseMissing('bad_debt_documents', [
            'id' => $document->id,
        ]);
    }

    // ==================== Memo Tests ====================

    public function test_can_add_memo_to_bad_debt(): void
    {
        $badDebt = BadDebt::create([
            'tenant_id' => $this->tenant->id,
            'client_id' => $this->client->id,
            'debt_amount' => 500000,
            'status' => BadDebt::STATUS_COLLECTING,
            'is_active' => true,
            'created_by' => $this->user->id,
            'updated_by' => $this->user->id,
        ]);

        $response = $this->authenticatedRequest('post', "/api/v1/bad-debts/{$badDebt->id}/memos", [
            'content' => '첫 번째 추심 시도 - 연락 안됨',
        ]);

        $response->assertStatus(201);

        $this->assertDatabaseHas('bad_debt_memos', [
            'bad_debt_id' => $badDebt->id,
            'content' => '첫 번째 추심 시도 - 연락 안됨',
            'created_by' => $this->user->id,
        ]);
    }

    public function test_can_remove_memo_from_bad_debt(): void
    {
        $badDebt = BadDebt::create([
            'tenant_id' => $this->tenant->id,
            'client_id' => $this->client->id,
            'debt_amount' => 500000,
            'status' => BadDebt::STATUS_COLLECTING,
            'is_active' => true,
            'created_by' => $this->user->id,
            'updated_by' => $this->user->id,
        ]);

        $memo = BadDebtMemo::create([
            'bad_debt_id' => $badDebt->id,
            'content' => '삭제할 메모',
            'created_by' => $this->user->id,
        ]);

        $response = $this->authenticatedRequest('delete', "/api/v1/bad-debts/{$badDebt->id}/memos/{$memo->id}");

        $response->assertStatus(200);

        $this->assertDatabaseMissing('bad_debt_memos', [
            'id' => $memo->id,
        ]);
    }

    // ==================== Filter Tests ====================

    public function test_can_filter_bad_debts_by_status(): void
    {
        BadDebt::create([
            'tenant_id' => $this->tenant->id,
            'client_id' => $this->client->id,
            'debt_amount' => 1000000,
            'status' => BadDebt::STATUS_COLLECTING,
            'is_active' => true,
            'created_by' => $this->user->id,
            'updated_by' => $this->user->id,
        ]);

        BadDebt::create([
            'tenant_id' => $this->tenant->id,
            'client_id' => $this->client->id,
            'debt_amount' => 500000,
            'status' => BadDebt::STATUS_RECOVERED,
            'is_active' => true,
            'created_by' => $this->user->id,
            'updated_by' => $this->user->id,
        ]);

        $response = $this->authenticatedRequest('get', '/api/v1/bad-debts?status='.BadDebt::STATUS_COLLECTING);

        $response->assertStatus(200);

        $data = $response->json('data.data');
        $this->assertCount(1, $data);
        $this->assertEquals(BadDebt::STATUS_COLLECTING, $data[0]['status']);
    }

    public function test_can_filter_bad_debts_by_client(): void
    {
        $client2 = Client::create([
            'tenant_id' => $this->tenant->id,
            'name' => 'Another Client',
            'client_code' => 'CLI2'.uniqid(),
            'created_by' => $this->user->id,
        ]);

        BadDebt::create([
            'tenant_id' => $this->tenant->id,
            'client_id' => $this->client->id,
            'debt_amount' => 1000000,
            'status' => BadDebt::STATUS_COLLECTING,
            'is_active' => true,
            'created_by' => $this->user->id,
            'updated_by' => $this->user->id,
        ]);

        BadDebt::create([
            'tenant_id' => $this->tenant->id,
            'client_id' => $client2->id,
            'debt_amount' => 500000,
            'status' => BadDebt::STATUS_COLLECTING,
            'is_active' => true,
            'created_by' => $this->user->id,
            'updated_by' => $this->user->id,
        ]);

        $response = $this->authenticatedRequest('get', '/api/v1/bad-debts?client_id='.$this->client->id);

        $response->assertStatus(200);

        $data = $response->json('data.data');
        $this->assertCount(1, $data);
        $this->assertEquals($this->client->id, $data[0]['client_id']);
    }

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

    public function test_cannot_access_bad_debts_without_authentication(): void
    {
        $response = $this->withHeaders([
            'X-API-KEY' => $this->apiKey,
            'Accept' => 'application/json',
        ])->getJson('/api/v1/bad-debts');

        $response->assertStatus(401);
    }
}
