<?php
namespace App\Services;

use App\Models\CommissionRule;
use App\Models\DealCommission;
use App\Repositories\CommissionRuleRepository;
use App\Repositories\DealCommissionRepository;
use App\Repositories\DealRepository;
use App\Repositories\ProductRepository;
use App\Repositories\UserRepository;
use App\Repositories\ActivityRepository;

class CommissionService
{
    private $ruleRepo;
    private $dealCommissionRepo;
    private $dealRepo;
    private $productRepo;
    private $userRepo;
    private $activityRepo;

    public function __construct(
        CommissionRuleRepository $ruleRepo,
        DealCommissionRepository $dealCommissionRepo,
        DealRepository $dealRepo,
        ProductRepository $productRepo,
        UserRepository $userRepo,
        ActivityRepository $activityRepo
    ) {
        $this->ruleRepo = $ruleRepo;
        $this->dealCommissionRepo = $dealCommissionRepo;
        $this->dealRepo = $dealRepo;
        $this->productRepo = $productRepo;
        $this->userRepo = $userRepo;
        $this->activityRepo = $activityRepo;
    }

    public function getRules(array $filters = []): array
    {
        return $this->ruleRepo->getAll($filters);
    }

    public function saveRule(array $data, int $actorUserId = 0): int
    {
        $salespersonUserId = (int)($data['salesperson_user_id'] ?? 0);
        $productId = (int)($data['product_id'] ?? 0);
        $baseRate = (float)($data['base_rate_percent'] ?? 0);
        $validFrom = trim((string)($data['valid_from'] ?? ''));
        $validTo = trim((string)($data['valid_to'] ?? ''));
        $isActive = isset($data['is_active']) ? (int)$data['is_active'] : 1;

        if ($salespersonUserId <= 0 || $productId <= 0 || $baseRate <= 0 || $validFrom === '') {
            throw new \InvalidArgumentException('اطلاعات قانون پورسانت کامل نیست');
        }

        $rule = new CommissionRule([
            'id' => isset($data['id']) ? (int)$data['id'] : null,
            'salesperson_user_id' => $salespersonUserId,
            'product_id' => $productId,
            'base_rate_percent' => $baseRate,
            'valid_from' => $validFrom,
            'valid_to' => $validTo !== '' ? $validTo : null,
            'is_active' => $isActive,
            'created_by_user_id' => $actorUserId > 0 ? $actorUserId : null,
        ]);
        return $this->ruleRepo->save($rule);
    }

    public function calculateAndStoreForWonDeal(string $dealDidarId): ?DealCommission
    {
        $deal = $this->dealRepo->findByDidarId($dealDidarId);
        if (!$deal || trim((string)$deal->status) !== 'Won') {
            return null;
        }

        $salesperson = $this->userRepo->findByDidarId((string)$deal->owner_didar_id);
        if (!$salesperson || (int)$salesperson->id <= 0) {
            return null;
        }

        $productId = $this->resolvePrimaryProductId((string)$deal->didar_deal_id);
        if ($productId <= 0) {
            return null;
        }

        $dealDate = !empty($deal->won_time) ? substr((string)$deal->won_time, 0, 10) : date('Y-m-d');
        $rule = $this->ruleRepo->findApplicableRule((int)$salesperson->id, $productId, $dealDate);
        if (!$rule) {
            return null;
        }

        $ncr = (float)($deal->payment_amount ?? 0);
        $kpiMultiplier = $this->calculateKpiMultiplier((string)$deal->didar_deal_id);
        $rate = (float)$rule->base_rate_percent;
        $calculated = round(($ncr * ($rate / 100)) * $kpiMultiplier, 2);

        $commission = new DealCommission([
            'deal_didar_id' => (string)$deal->didar_deal_id,
            'salesperson_user_id' => (int)$salesperson->id,
            'product_id' => $productId,
            'commission_rule_id' => (int)$rule->id,
            'ncr_amount' => $ncr,
            'applied_rate_percent' => $rate,
            'kpi_multiplier' => $kpiMultiplier,
            'calculated_commission' => $calculated,
            'status' => 'PENDING_MANAGER_REVIEW',
        ]);
        $id = $this->dealCommissionRepo->save($commission);
        if ($id <= 0) {
            return null;
        }
        return $this->dealCommissionRepo->findByDealDidarId((string)$deal->didar_deal_id);
    }

    public function getDealCommissions(array $filters = []): array
    {
        return $this->dealCommissionRepo->getAll($filters);
    }

    public function advanceStatus(int $commissionId, string $status, int $actorUserId = 0): bool
    {
        $allowed = ['PENDING_MANAGER_REVIEW', 'PENDING_FINANCE', 'READY_FOR_PAYOUT', 'SETTLED'];
        $status = strtoupper(trim($status));
        if (!in_array($status, $allowed, true)) {
            throw new \InvalidArgumentException('وضعیت نامعتبر است');
        }
        return $this->dealCommissionRepo->updateStatus($commissionId, $status, $actorUserId);
    }

    private function resolvePrimaryProductId(string $dealDidarId): int
    {
        $rows = $this->dealRepo->getProductsByDealDidarId($dealDidarId);
        if (!empty($rows) && isset($rows[0]['product_id'])) {
            return (int)$rows[0]['product_id'];
        }
        return 0;
    }

    private function calculateKpiMultiplier(string $dealDidarId): float
    {
        $activities = $this->activityRepo->findByDealId($dealDidarId, 500);
        $count = is_array($activities) ? count($activities) : 0;
        if ($count >= 8) return 1.20;
        if ($count >= 5) return 1.10;
        if ($count >= 2) return 1.00;
        return 0.90;
    }
}
