<?php

namespace App\Services;

use App\Models\Franchise;
use App\Models\FranchiseTransaction;
use App\Models\Order;
use Illuminate\Support\Facades\DB;

class FranchiseCommissionService
{
    public function __construct(private readonly FranchiseNotificationService $notificationService)
    {
    }

    public function creditForOrder(Franchise $franchise, Order $order): ?FranchiseTransaction
    {
        $existing = FranchiseTransaction::query()
            ->where('franchise_id', $franchise->id)
            ->where('order_id', $order->id)
            ->where('transaction_type', 'commission_credit')
            ->exists();

        if ($existing) {
            return null;
        }

        $percent = (float) ($franchise->commission_percent ?? 0);
        $amount = round(((float) $order->total) * $percent / 100, 2);

        if ($amount <= 0) {
            return null;
        }

        return DB::transaction(function () use ($franchise, $order, $amount): FranchiseTransaction {
            $locked = Franchise::query()->whereKey($franchise->id)->lockForUpdate()->first();
            $locked->wallet_balance = round(((float) $locked->wallet_balance) + $amount, 2);
            $locked->save();

            $transaction = FranchiseTransaction::query()->create([
                'franchise_id' => $franchise->id,
                'order_id' => $order->id,
                'transaction_type' => 'commission_credit',
                'amount' => $amount,
                'bv' => 0,
                'quantity' => 0,
                'reference' => $order->order_number,
                'narration' => 'Commission credited',
                'transacted_at' => now(),
                'created_by' => $order->approved_by,
            ]);

            $this->notificationService->notify(
                $franchise,
                'Commission credited',
                "Commission of INR {$amount} credited for order {$order->order_number}.",
                route('franchise.commission')
            );

            return $transaction;
        });
    }

    public function reverseForOrder(Franchise $franchise, Order $order): ?FranchiseTransaction
    {
        $existing = FranchiseTransaction::query()
            ->where('franchise_id', $franchise->id)
            ->where('order_id', $order->id)
            ->where('transaction_type', 'commission_debit')
            ->exists();

        if ($existing) {
            return null;
        }

        $percent = (float) ($franchise->commission_percent ?? 0);
        $amount = round(((float) $order->total) * $percent / 100, 2);

        if ($amount <= 0) {
            return null;
        }

        return DB::transaction(function () use ($franchise, $order, $amount): FranchiseTransaction {
            $locked = Franchise::query()->whereKey($franchise->id)->lockForUpdate()->first();
            $locked->wallet_balance = max(0, round(((float) $locked->wallet_balance) - $amount, 2));
            $locked->save();

            return FranchiseTransaction::query()->create([
                'franchise_id' => $franchise->id,
                'order_id' => $order->id,
                'transaction_type' => 'commission_debit',
                'amount' => $amount,
                'bv' => 0,
                'quantity' => 0,
                'reference' => $order->order_number,
                'narration' => 'Commission reversal',
                'transacted_at' => now(),
                'created_by' => $order->approved_by,
            ]);
        });
    }
}

