<?php

namespace Tests\Feature;

use App\Models\Marriage;
use App\Models\ShopItem;
use App\Models\User;
use App\Models\UserPurchase;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Event;
use Tests\TestCase;

class MarriageControllerTest extends TestCase
{
    use RefreshDatabase;

    private function createLegacyMarriageData()
    {
        return [
            'hyname' => 'test',
            'hyname1' => 'test1',
            'hytime' => now(),
            'hygb' => 'test',
            'hyjb' => 'test',
            'i' => 0,
        ];
    }

    public function test_can_get_divorce_config()
    {
        /** @var \App\Models\User $user */
        $user = User::factory()->create();

        $response = $this->actingAs($user)->getJson(route('marriage.divorce-config'));

        $response->assertStatus(200);
        $response->assertJsonStructure([
            'mutual_charm_penalty',
            'forced_charm_penalty',
            'mutual_cooldown_days',
            'forced_cooldown_days',
        ]);
    }

    public function test_can_get_status_unmarried()
    {
        /** @var \App\Models\User $user */
        $user = User::factory()->create();

        $response = $this->actingAs($user)->getJson(route('marriage.status'));

        $response->assertStatus(200);
        $response->assertJson(['married' => false]);
    }

    public function test_can_get_status_married()
    {
        /** @var \App\Models\User $user */
        $user = User::factory()->create();
        /** @var \App\Models\User $partner */
        $partner = User::factory()->create();

        $marriage = Marriage::create(array_merge([
            'user_id' => $user->id,
            'partner_id' => $partner->id,
            'status' => 'married',
            'married_at' => now(),
            'intimacy' => 100,
        ], $this->createLegacyMarriageData()));

        $response = $this->actingAs($user)->getJson(route('marriage.status'));

        $response->assertStatus(200);
        $response->assertJson([
            'married' => true,
            'status' => 'married',
        ]);
        $response->assertJsonPath('marriage.partner.id', $partner->id);
    }

    public function test_can_get_target_status()
    {
        /** @var \App\Models\User $user */
        $user = User::factory()->create();
        /** @var \App\Models\User $target */
        $target = User::factory()->create();
        /** @var \App\Models\User $partner */
        $partner = User::factory()->create();

        Marriage::create(array_merge([
            'user_id' => $target->id,
            'partner_id' => $partner->id,
            'status' => 'married',
            'married_at' => now(),
        ], $this->createLegacyMarriageData()));

        $response = $this->actingAs($user)->getJson(route('marriage.target-status', [
            'username' => $target->username,
        ]));

        $response->assertStatus(200);
        $response->assertJson([
            'married' => true,
        ]);
        $response->assertJsonPath('marriage.partner_name', $partner->username);
    }

    public function test_can_get_my_rings()
    {
        /** @var \App\Models\User $user */
        $user = User::factory()->create();

        $ring = ShopItem::create([
            'name' => 'Diamond Ring',
            'slug' => 'diamond_ring',
            'type' => 'ring',
            'price' => 1000,
            'currency' => 'gold',
            'use_type' => 'permanent',
        ]);

        $purchase = UserPurchase::create([
            'user_id' => $user->id,
            'shop_item_id' => $ring->id,
            'status' => 'active',
            'number' => 1,
            'amount' => 1000,
            'currency' => 'gold',
        ]);

        $response = $this->actingAs($user)->getJson(route('marriage.rings'));

        $response->assertStatus(200);
        $response->assertJsonStructure(['status', 'rings']);
        $this->assertCount(1, $response->json('rings'));
        $this->assertEquals($purchase->id, $response->json('rings.0.purchase_id'));
    }

    public function test_can_propose()
    {
        Event::fake();

        /** @var \App\Models\User $user */
        $user = User::factory()->create(['jjb' => 10000, 'sex' => 1]);
        /** @var \App\Models\User $target */
        $target = User::factory()->create(['sex' => 2]);

        $ring = ShopItem::create([
            'name' => 'Diamond Ring',
            'slug' => 'diamond_ring',
            'type' => 'ring',
            'price' => 1000,
            'currency' => 'gold',
            'use_type' => 'permanent',
        ]);

        $purchase = UserPurchase::create([
            'user_id' => $user->id,
            'shop_item_id' => $ring->id,
            'status' => 'active',
            'number' => 1,
            'amount' => 1000,
            'currency' => 'gold',
        ]);

        $response = $this->actingAs($user)->postJson(route('marriage.propose'), [
            'target_username' => $target->username,
            'ring_purchase_id' => $purchase->id,
        ]);

        $response->assertStatus(200);
        $response->assertJson(['ok' => true]);

        Event::assertDispatched(\App\Events\MarriageProposed::class);
    }

    public function test_can_accept_proposal()
    {
        Event::fake();

        /** @var \App\Models\User $user */
        $user = User::factory()->create();
        /** @var \App\Models\User $partner */
        $partner = User::factory()->create();

        $ring = ShopItem::create([
            'name' => 'Diamond',
            'slug' => 'diamond',
            'type' => 'ring',
            'price' => 1000,
            'currency' => 'gold',
            'use_type' => 'permanent',
        ]);

        $purchase = UserPurchase::create([
            'user_id' => $partner->id,
            'shop_item_id' => $ring->id,
            'status' => 'active',
            'number' => 1,
            'amount' => 1000,
            'currency' => 'gold',
        ]);

        $marriage = Marriage::create(array_merge([
            'user_id' => $partner->id,
            'partner_id' => $user->id,
            'status' => 'pending',
            'ring_purchase_id' => $purchase->id,
            'proposed_at' => now(),
        ], $this->createLegacyMarriageData()));

        $response = $this->actingAs($user)->postJson(route('marriage.accept', ['marriage' => $marriage->id]));

        $response->assertStatus(200);
        $response->assertJson(['ok' => true]);

        Event::assertDispatched(\App\Events\MarriageAccepted::class);
    }

    public function test_can_reject_proposal()
    {
        Event::fake();

        /** @var \App\Models\User $user */
        $user = User::factory()->create();
        /** @var \App\Models\User $partner */
        $partner = User::factory()->create();

        $marriage = Marriage::create(array_merge([
            'user_id' => $partner->id,
            'partner_id' => $user->id,
            'status' => 'pending',
            'proposed_at' => now(),
        ], $this->createLegacyMarriageData()));

        $response = $this->actingAs($user)->postJson(route('marriage.reject', ['marriage' => $marriage->id]));

        $response->assertStatus(200);
        $response->assertJson(['ok' => true]);

        Event::assertDispatched(\App\Events\MarriageRejected::class);
    }

    public function test_can_divorce_mutual()
    {
        Event::fake();

        /** @var \App\Models\User $user */
        $user = User::factory()->create();
        /** @var \App\Models\User $partner */
        $partner = User::factory()->create();

        $marriage = Marriage::create(array_merge([
            'user_id' => $user->id,
            'partner_id' => $partner->id,
            'status' => 'married',
            'married_at' => now()->subDays(10), // Needs to have marriage age
        ], $this->createLegacyMarriageData()));

        $response = $this->actingAs($user)->postJson(route('marriage.divorce', ['marriage' => $marriage->id]), [
            'type' => 'mutual',
        ]);

        $response->assertStatus(200);
        $response->assertJson(['ok' => true]);

        Event::assertDispatched(\App\Events\MarriageDivorceRequested::class);
    }
}
