<?php

namespace Tests\Feature\Unit;

use App\Models\BinaryLedger;
use App\Models\Franchise;
use App\Models\FranchiseCommissionRule;
use App\Models\Order;
use App\Models\PaymentTransaction;
use App\Models\User;
use App\Services\PaymentVerificationService;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class PaymentVerificationServiceTest extends TestCase
{
    use RefreshDatabase;

    public function test_order_status_is_not_downgraded_when_payment_is_verified(): void
    {
        $user = User::query()->create([
            'member_code' => 'AKRPVS001',
            'referral_code' => 'REFPVS001',
            'name' => 'Payment User',
            'email' => 'payment-user@example.com',
            'mobile' => '9300000101',
            'password' => 'password',
            'role' => 'user',
            'status' => 'active',
        ]);

        $order = Order::query()->create([
            'order_number' => 'ODRPVS001',
            'user_id' => $user->id,
            'order_type' => 'user',
            'status' => 'approved',
            'payment_status' => 'unpaid',
            'subtotal' => 100,
            'total' => 100,
            'total_bv' => 10,
            'payment_method' => 'upi',
        ]);

        $payment = PaymentTransaction::query()->create([
            'user_id' => $user->id,
            'order_id' => $order->id,
            'gateway' => 'upi',
            'merchant_order_ref' => $order->order_number,
            'amount' => 100,
            'payment_for' => 'order',
            'status' => 'pending',
        ]);

        app(PaymentVerificationService::class)->markPaymentSuccess($payment, ['source' => 'test']);

        $order->refresh();
        $payment->refresh();

        $this->assertSame('success', $payment->status);
        $this->assertSame('paid', $order->payment_status);
        $this->assertSame('approved', $order->status);
    }

    public function test_joining_payment_for_already_joined_user_does_not_repost_joining_ledger(): void
    {
        $sponsor = User::query()->create([
            'member_code' => 'AKRPVSSP1',
            'referral_code' => 'REFPVSSP1',
            'name' => 'Sponsor',
            'email' => 'payment-sponsor@example.com',
            'mobile' => '9300000102',
            'password' => 'password',
            'role' => 'user',
            'status' => 'active',
            'joined_at' => now(),
        ]);

        $member = User::query()->create([
            'member_code' => 'AKRPVSMB1',
            'referral_code' => 'REFPVSMB1',
            'name' => 'Joined Member',
            'email' => 'payment-member@example.com',
            'mobile' => '9300000103',
            'password' => 'password',
            'role' => 'user',
            'status' => 'active',
            'sponsor_id' => $sponsor->id,
            'placement_parent_id' => $sponsor->id,
            'placement_leg' => 'left',
            'joined_at' => now(),
        ]);

        $payment = PaymentTransaction::query()->create([
            'user_id' => $member->id,
            'gateway' => 'upi',
            'merchant_order_ref' => 'JOINPVS001',
            'amount' => 999,
            'payment_for' => 'joining',
            'status' => 'pending',
        ]);

        app(PaymentVerificationService::class)->markPaymentSuccess($payment, ['source' => 'test']);

        $this->assertSame(0, BinaryLedger::query()->where('source_user_id', $member->id)->count());
    }

    public function test_franchise_activation_commission_is_credited_only_after_joining_payment_success(): void
    {
        $franchiseUser = User::query()->create([
            'member_code' => 'AKRPVSFR1',
            'referral_code' => 'REFPVSFR1',
            'name' => 'Franchise Owner',
            'email' => 'payment-franchise@example.com',
            'mobile' => '9300000104',
            'password' => 'password',
            'role' => 'franchise',
            'status' => 'active',
        ]);

        $franchise = Franchise::query()->create([
            'code' => 'FRPVS001',
            'name' => 'PVS Franchise',
            'owner_name' => 'Franchise Owner',
            'mobile' => '9300000105',
            'email' => 'pvs-franchise@example.com',
            'wallet_balance' => 0,
            'commission_percent' => 10,
            'is_active' => true,
            'created_by' => $franchiseUser->id,
        ]);

        FranchiseCommissionRule::query()->create([
            'franchise_id' => $franchise->id,
            'rule_type' => 'id_activation',
            'calc_type' => 'fixed',
            'value' => 75,
            'is_active' => true,
        ]);

        $sponsor = User::query()->create([
            'member_code' => 'AKRPVSSP2',
            'referral_code' => 'REFPVSSP2',
            'name' => 'Sponsor Two',
            'email' => 'payment-sponsor2@example.com',
            'mobile' => '9300000106',
            'password' => 'password',
            'role' => 'user',
            'status' => 'active',
            'joined_at' => now(),
        ]);

        $member = User::query()->create([
            'member_code' => 'AKRPVSMB2',
            'referral_code' => 'REFPVSMB2',
            'name' => 'Pending Member',
            'email' => 'payment-member2@example.com',
            'mobile' => '9300000107',
            'password' => 'password',
            'role' => 'user',
            'status' => 'pending',
            'sponsor_id' => $sponsor->id,
            'placement_parent_id' => $sponsor->id,
            'placement_leg' => 'right',
            'package_amount' => 999,
        ]);

        \DB::table('franchise_member_creations')->insert([
            'franchise_id' => $franchise->id,
            'user_id' => $member->id,
            'created_by' => $franchiseUser->id,
            'created_at' => now(),
            'updated_at' => now(),
        ]);

        $payment = PaymentTransaction::query()->create([
            'user_id' => $member->id,
            'gateway' => 'upi',
            'merchant_order_ref' => 'JOINPVS002',
            'amount' => 999,
            'payment_for' => 'joining',
            'status' => 'pending',
        ]);

        $franchise->refresh();
        $this->assertSame(0.0, (float) $franchise->wallet_balance);

        app(PaymentVerificationService::class)->markPaymentSuccess($payment, ['source' => 'test']);

        $franchise->refresh();
        $this->assertSame(75.0, (float) $franchise->wallet_balance);
        $this->assertDatabaseHas('franchise_transactions', [
            'franchise_id' => $franchise->id,
            'user_id' => $member->id,
            'transaction_type' => 'commission_credit',
            'reference' => 'ACT-'.$member->member_code,
        ]);
    }
}
