<?php

namespace App\Http\Controllers;

use App\Models\TargetCampaign;
use App\Models\TargetClaim;
use App\Services\TargetBonusService;
use Illuminate\Http\Request;

// Extra models used for leaderboards:
use App\Models\User;
use App\Models\Job;        // jobpost
use App\Models\Order;      // drive_offer (approved)
use App\Models\PdOrder;    // product (completed)
use Illuminate\Support\Collection;

class TargetBonusController extends Controller
{
    public function index()
    {
        $userId = auth()->id();

        $campaigns = TargetCampaign::live()
            ->orderBy('start_at')
            ->get()
            ->map(function ($cp) use ($userId) {
                // আপনার নিজের সার্ভিস—ব্যক্তিগত প্রগ্রেস অপরিবর্তিত থাকবে
                $progress = TargetBonusService::progress($cp, $userId);
                $claimed  = TargetClaim::where('campaign_id', $cp->id)
                                       ->where('user_id', $userId)
                                       ->exists();

                // === নতুন: লিডারবোর্ড ডেটা বানাই ===
                [$winners, $contenders] = $this->buildLeaderboards($cp);

                return (object)[
                    'model'      => $cp,
                    'progress'   => $progress,     // current, required, met
                    'claimed'    => $claimed,
                    'winners'    => $winners,      // collection of ['user'=>User,'count'=>int]
                    'contenders' => $contenders,   // collection of ['user'=>User,'count'=>int]
                ];
            });

        return view('targets.index', compact('campaigns'));
    }

    public function claim(TargetCampaign $target)
    {
        TargetBonusService::claim($target, auth()->id());
        return back()->with('success', '🎉 বোনাস আপনার ব্যালেন্সে যুক্ত হয়েছে!');
    }

    /**
     * প্রতিটি ক্যাম্পেইনের জন্য Winners & Contenders বানায়
     * return array{Collection $winners, Collection $contenders}
     */
    private function buildLeaderboards($cp): array
    {
        $required = max(1, (int)$cp->required_count);
        $start    = $cp->start_at;
        $end      = $cp->end_at;

        // user_id => count
        $counts = match ($cp->project_type) {
            'referral'    => $this->countReferralLevel($cp->referral_level ?? 1, $start, $end),
            'jobpost'     => $this->countJobpostApproved($start, $end),
            'drive_offer' => $this->countDriveOfferApproved($start, $end),
            'product'     => $this->countProductCompleted($start, $end),
            default       => collect(),
        };

        if (!($counts instanceof Collection)) {
            $counts = collect($counts ?? []);
        }

        // user_ids needed
        $userIds = $counts->keys()->filter()->values();
        $users = $userIds->count()
            ? User::whereIn('id', $userIds)->get()->keyBy('id')
            : collect();

        // winners = >= required, contenders = (0 < count < required)
        $winners = $counts
            ->filter(fn ($c) => (int)$c >= $required)
            ->map(fn ($c, $uid) => ['user' => $users->get($uid), 'count' => (int)$c])
            ->filter(fn ($row) => $row['user']) // null user guard
            ->sortByDesc('count')
            ->values();

        $contenders = $counts
            ->filter(fn ($c) => (int)$c > 0 && (int)$c < $required)
            ->map(fn ($c, $uid) => ['user' => $users->get($uid), 'count' => (int)$c])
            ->filter(fn ($row) => $row['user'])
            ->sortByDesc('count')
            ->values();

        return [$winners, $contenders];
    }

    /**
     * Referral: নির্দিষ্ট level-এ active referral গণনা (activated_at within window)
     * লজিক: যে সকল ইউজার উইন্ডোতে activate হয়েছে -> তাদের uplink chain ধরে N-level up-এর user_id তে +1
     */
    private function countReferralLevel(int $level, $start, $end): Collection
    {
        $level = max(1, min(10, $level));

        // উইন্ডোর মধ্যে অ্যাক্টিভ হওয়া সবাই
        $activated = User::query()
            ->where('is_active', 1)
            ->when($start, fn($q) => $q->where('activated_at', '>=', $start))
            ->when($end,   fn($q) => $q->where('activated_at', '<=', $end))
            ->get(['id', 'name', 'referred_by', 'referral_code']);

        $byReferralCode = fn(string $refCode) => User::where('referral_code', $refCode)->first(['id','referred_by','referral_code']);

        $counts = [];

        foreach ($activated as $downline) {
            $refCode = $downline->referred_by; // immediate upline code
            $upline = null;

            // chain up N levels
            for ($i = 1; $i <= $level; $i++) {
                if (!$refCode) { $upline = null; break; }
                $upline = $byReferralCode($refCode);
                $refCode = $upline?->referred_by;
                if (!$upline) break;
            }

            if ($upline && isset($upline->id)) {
                $uid = (int)$upline->id;
                $counts[$uid] = ($counts[$uid] ?? 0) + 1;
            }
        }

        return collect($counts);
    }

    /**
     * Job Post: যে ইউজার approved job পোস্ট করেছেন (উইন্ডোর মধ্যে) -> count(user_id)
     */
    private function countJobpostApproved($start, $end): Collection
    {
        if (!class_exists(Job::class)) return collect();

        return Job::query()
            ->where('status', 'approved')
            ->when($start, fn($q) => $q->where('created_at', '>=', $start))
            ->when($end,   fn($q) => $q->where('created_at', '<=', $end))
            ->selectRaw('user_id, COUNT(*) as c')
            ->groupBy('user_id')
            ->pluck('c', 'user_id'); // user_id => count
    }

    /**
     * Drive Offer: Order status approved (উইন্ডোর মধ্যে) -> count(user_id)
     */
    private function countDriveOfferApproved($start, $end): Collection
    {
        if (!class_exists(Order::class)) return collect();

        return Order::query()
            ->where('status', 'approved')
            ->when($start, fn($q) => $q->where('updated_at', '>=', $start))
            ->when($end,   fn($q) => $q->where('updated_at', '<=', $end))
            ->selectRaw('user_id, COUNT(*) as c')
            ->groupBy('user_id')
            ->pluck('c', 'user_id');
    }

    /**
     * Product: PdOrder status completed (উইন্ডোর মধ্যে) -> count(user_id)
     */
    private function countProductCompleted($start, $end): Collection
    {
        if (!class_exists(PdOrder::class)) return collect();

        return PdOrder::query()
            ->where('status', 'completed')
            ->when($start, fn($q) => $q->where('updated_at', '>=', $start))
            ->when($end,   fn($q) => $q->where('updated_at', '<=', $end))
            ->selectRaw('user_id, COUNT(*) as c')
            ->groupBy('user_id')
            ->pluck('c', 'user_id');
    }
}