<?php

namespace App\Services;

use App\Models\Admin;
use App\Models\BalanceLog;
use App\Models\IncomeHistory;
use App\Models\User;
use App\Models\WelcomeOfferClaim;
use App\Support\WelcomeOfferSettings;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
use Illuminate\Validation\ValidationException;

class WelcomeOfferClaimService
{
    public function __construct(private WelcomeOfferService $welcomeOfferService)
    {
    }

    public function existingClaimForUser(?User $user): ?WelcomeOfferClaim
    {
        if (!$user || !Schema::hasTable('welcome_offer_claims')) {
            return null;
        }

        return WelcomeOfferClaim::query()
            ->with(['admin:id,name', 'user:id,name,referral_code,mobile,profile_photo'])
            ->where('user_id', $user->id)
            ->first();
    }

    public function canUserClaim(?User $user, ?array $levelCards = null): bool
    {
        if (!$user || !Schema::hasTable('welcome_offer_claims') || $this->existingClaimForUser($user)) {
            return false;
        }

        $levelCards ??= $this->welcomeOfferService->progressForUser($user);

        foreach (WelcomeOfferService::TRACKED_LEVELS as $level) {
            if (!((bool) ($levelCards[$level]['is_complete'] ?? false))) {
                return false;
            }
        }

        return true;
    }

    public function claimForUser(
        User $user,
        ?Admin $admin = null,
        string $source = 'user_claim',
        ?string $note = null
    ): WelcomeOfferClaim {
        if (!Schema::hasTable('welcome_offer_claims')) {
            throw ValidationException::withMessages([
                'claim' => 'Welcome Offer history table এখনো ready না।',
            ]);
        }

        $levelCards = $this->welcomeOfferService->progressForUser($user);
        if ($source === 'user_claim' && !$this->canUserClaim($user, $levelCards)) {
            throw ValidationException::withMessages([
                'claim' => 'টার্গেট এখনো পূরণ হয়নি, তাই অফার নেওয়া যাবে না।',
            ]);
        }

        $targets = WelcomeOfferSettings::targets();
        $levelOneCount = (int) ($levelCards[1]['count'] ?? 0);
        $levelTwoCount = (int) ($levelCards[2]['count'] ?? 0);

        if ($source === 'admin_manual_grant') {
            $levelOneCount = max($levelOneCount, (int) ($targets[1] ?? 0));
            $levelTwoCount = max($levelTwoCount, (int) ($targets[2] ?? 0));
        }

        $rewardAmount = WelcomeOfferSettings::amount();
        $note = trim((string) $note);

        return DB::transaction(function () use (
            $user,
            $admin,
            $source,
            $note,
            $rewardAmount,
            $targets,
            $levelOneCount,
            $levelTwoCount
        ) {
            $lockedUser = User::query()->lockForUpdate()->findOrFail($user->id);

            $existing = WelcomeOfferClaim::query()
                ->where('user_id', $lockedUser->id)
                ->lockForUpdate()
                ->first();

            if ($existing) {
                throw ValidationException::withMessages([
                    'claim' => 'এই user ইতোমধ্যে Welcome Offer নিয়েছে।',
                ]);
            }

            $claim = WelcomeOfferClaim::query()->create([
                'user_id' => $lockedUser->id,
                'admin_id' => $admin?->id,
                'claim_source' => $source,
                'reward_amount' => $rewardAmount,
                'level_one_target' => (int) ($targets[1] ?? 0),
                'level_two_target' => (int) ($targets[2] ?? 0),
                'level_one_count' => $levelOneCount,
                'level_two_count' => $levelTwoCount,
                'note' => $note !== '' ? $note : null,
                'claimed_at' => now(),
            ]);

            if ($rewardAmount > 0) {
                $lockedUser->balance = (float) ($lockedUser->balance ?? 0) + $rewardAmount;
                $lockedUser->save();

                if (Schema::hasTable('balance_logs')) {
                    $balanceLogData = [
                        'user_id' => $lockedUser->id,
                        'amount' => $rewardAmount,
                    ];

                    if (Schema::hasColumn('balance_logs', 'type')) {
                        $balanceLogData['type'] = 'welcome_offer_reward';
                    }

                    BalanceLog::create($balanceLogData);
                }

                if (Schema::hasTable('income_histories')) {
                    IncomeHistory::create([
                        'user_id' => $lockedUser->id,
                        'source' => 'welcome_offer_reward',
                        'amount' => $rewardAmount,
                        'description' => $source === 'admin_manual_grant'
                            ? 'অভিনন্দন! Admin থেকে আপনাকে Welcome Offer হিসেবে ' . $rewardAmount . '৳ প্রদান করা হয়েছে।'
                            : 'অভিনন্দন! আপনি Welcome Offer claim করে ' . $rewardAmount . '৳ পেয়েছেন।',
                    ]);
                }
            }

            return $claim->load(['admin:id,name', 'user:id,name,referral_code,mobile,profile_photo']);
        });
    }
}
