<?php

namespace Tests\Feature;

use App\Models\GmailSale;
use App\Models\GmailSellSetting;
use App\Models\User;
use App\Services\GmailSaleStatusService;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
use Tests\TestCase;

class GmailSaleStatusServiceTest extends TestCase
{
    protected function setUp(): void
    {
        parent::setUp();

        $this->createTables();
    }

    public function test_completed_sale_can_be_rejected_and_recompleted_without_double_credit(): void
    {
        GmailSellSetting::create([
            'price' => 12.50,
            'admin_price' => 4.25,
            'upline_commissions' => [0.50, 0.25],
        ]);

        $level2 = User::factory()->create([
            'referral_code' => 'UP-2',
            'balance' => 0,
        ]);

        $level1 = User::factory()->create([
            'referral_code' => 'UP-1',
            'referred_by' => 'UP-2',
            'balance' => 0,
        ]);

        $seller = User::factory()->create([
            'referral_code' => 'SELL-1',
            'referred_by' => 'UP-1',
            'balance' => 0,
        ]);

        $sale = GmailSale::create([
            'user_id' => $seller->id,
            'gmail' => 'seller@example.com',
            'gmail_password' => 'pass123',
            'rate' => 7.75,
            'admin_price' => 3.50,
            'upline_commissions_snapshot' => [1.10, 0.90],
            'status' => 'checked',
        ]);

        $service = app(GmailSaleStatusService::class);

        $service->transition($sale, 'completed');

        $this->assertSame(7.75, (float) $seller->fresh()->balance);
        $this->assertSame(1.1, (float) $level1->fresh()->balance);
        $this->assertSame(0.9, (float) $level2->fresh()->balance);

        $this->assertDatabaseHas('balance_logs', [
            'user_id' => $seller->id,
            'amount' => 7.75,
            'type' => 'gmail_sale_reward:' . $sale->id,
        ]);

        $this->assertDatabaseHas('balance_logs', [
            'user_id' => $level1->id,
            'amount' => 1.10,
            'type' => 'gmail_sale_referral:' . $sale->id . ':1',
        ]);

        $this->assertDatabaseHas('income_histories', [
            'user_id' => $seller->id,
            'source' => 'gmail_sale',
            'amount' => 7.75,
        ]);

        $service->transition($sale->fresh(['user']), 'rejected');

        $this->assertSame(0.0, (float) $seller->fresh()->balance);
        $this->assertSame(0.0, (float) $level1->fresh()->balance);
        $this->assertSame(0.0, (float) $level2->fresh()->balance);

        $this->assertDatabaseHas('income_histories', [
            'user_id' => $seller->id,
            'source' => 'gmail_sale_reversal',
            'amount' => -7.75,
        ]);

        $this->assertDatabaseHas('income_histories', [
            'user_id' => $level1->id,
            'source' => 'gmail_sale_referral_reversal',
            'amount' => -1.10,
        ]);

        $service->transition($sale->fresh(['user']), 'completed');
        $service->transition($sale->fresh(['user']), 'rejected');

        $this->assertSame(0.0, (float) $seller->fresh()->balance);
        $this->assertSame(0.0, (float) $level1->fresh()->balance);
        $this->assertSame(0.0, (float) $level2->fresh()->balance);

        $this->assertSame(
            0.0,
            (float) \App\Models\BalanceLog::query()
                ->where('user_id', $seller->id)
                ->where('type', 'gmail_sale_reward:' . $sale->id)
                ->sum('amount')
        );
    }

    private function createTables(): void
    {
        Schema::dropIfExists('income_histories');
        Schema::dropIfExists('balance_logs');
        Schema::dropIfExists('gmail_sales');
        Schema::dropIfExists('gmail_sell_settings');
        Schema::dropIfExists('users');

        Schema::create('users', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->string('email')->unique();
            $table->timestamp('email_verified_at')->nullable();
            $table->string('password');
            $table->rememberToken();
            $table->string('mobile')->nullable();
            $table->string('referred_by')->nullable();
            $table->string('referral_code')->nullable();
            $table->decimal('balance', 12, 2)->default(0);
            $table->decimal('voucher_balance', 12, 2)->default(0);
            $table->timestamps();
        });

        Schema::create('gmail_sell_settings', function (Blueprint $table) {
            $table->id();
            $table->decimal('price', 12, 2)->default(0);
            $table->decimal('admin_price', 12, 2)->default(0);
            $table->json('upline_commissions')->nullable();
            $table->timestamps();
        });

        Schema::create('gmail_sales', function (Blueprint $table) {
            $table->id();
            $table->foreignId('user_id');
            $table->string('gmail');
            $table->string('gmail_password');
            $table->string('recovery_email')->nullable();
            $table->decimal('rate', 12, 2)->nullable();
            $table->decimal('admin_price', 12, 2)->nullable();
            $table->json('upline_commissions_snapshot')->nullable();
            $table->string('status')->default('pending');
            $table->timestamps();
        });

        Schema::create('balance_logs', function (Blueprint $table) {
            $table->id();
            $table->foreignId('user_id');
            $table->decimal('amount', 12, 2)->default(0);
            $table->string('type')->nullable();
            $table->timestamps();
        });

        Schema::create('income_histories', function (Blueprint $table) {
            $table->id();
            $table->foreignId('user_id');
            $table->string('source');
            $table->decimal('amount', 12, 2)->default(0);
            $table->text('description')->nullable();
            $table->timestamps();
        });
    }
}
