<?php

namespace App\Services;

use App\Models\User;
use App\Models\Referral;
use Illuminate\Support\Facades\Cache;

class GenealogyService
{
    public function getTree(int $userId, int $maxDepth = 10): array
    {
        return Cache::remember("genealogy_tree_{$userId}_{$maxDepth}", 300, function () use ($userId, $maxDepth) {
            $user = User::with('rank')->find($userId);
            if (!$user) return [];

            return $this->buildTree($user, 0, $maxDepth);
        });
    }

    protected function buildTree(User $user, int $currentDepth, int $maxDepth): array
    {
        if ($currentDepth >= $maxDepth) {
            return [];
        }

        $referrals = Referral::where('sponsor_id', $user->id)
            ->with(['referred.rank'])
            ->get();

        $node = [
            'id' => $user->id,
            'name' => $user->name,
            'email' => $user->email,
            'rank' => $user->rank?->name ?? 'Débutant',
            'level' => $currentDepth,
            'referrals_count' => $referrals->count(),
            'children' => [],
        ];

        foreach ($referrals as $referral) {
            if ($referral->referred) {
                $node['children'][] = $this->buildTree($referral->referred, $currentDepth + 1, $maxDepth);
            }
        }

        return $node;
    }

    public function getNetworkStats(int $userId): array
    {
        $directReferrals = Referral::where('sponsor_id', $userId)->count();
        
        $allDownlineIds = $this->getAllDownlineIds($userId);
        $totalNetwork = count($allDownlineIds);

        $levelStats = [];
        for ($level = 1; $level <= 10; $level++) {
            $levelStats[$level] = Referral::where('sponsor_id', $userId)
                ->where('level', $level)
                ->count();
        }

        return [
            'direct_referrals' => $directReferrals,
            'total_network' => $totalNetwork,
            'by_level' => $levelStats,
        ];
    }

    public function getAllDownlineIds(int $userId, int $maxDepth = 10): array
    {
        $allIds = [];
        $currentLevelIds = [$userId];
        
        for ($depth = 0; $depth < $maxDepth; $depth++) {
            $nextLevelIds = Referral::whereIn('sponsor_id', $currentLevelIds)
                ->pluck('referred_id')
                ->toArray();
            
            if (empty($nextLevelIds)) {
                break;
            }
            
            $allIds = array_merge($allIds, $nextLevelIds);
            $currentLevelIds = $nextLevelIds;
        }

        return array_unique($allIds);
    }

    public function getUpline(int $userId, int $maxLevels = 10): array
    {
        $upline = [];
        $currentUser = User::find($userId);
        $level = 0;

        while ($currentUser && $level < $maxLevels) {
            $referral = Referral::where('referred_id', $currentUser->id)->first();
            if (!$referral) break;

            $sponsor = User::with('rank')->find($referral->sponsor_id);
            if (!$sponsor) break;

            $level++;
            $upline[] = [
                'level' => $level,
                'id' => $sponsor->id,
                'name' => $sponsor->name,
                'rank' => $sponsor->rank?->name ?? 'Débutant',
            ];

            $currentUser = $sponsor;
        }

        return $upline;
    }

    public function getNetworkVolume(int $userId, string $period = 'monthly'): float
    {
        $downlineIds = $this->getAllDownlineIds($userId);
        $downlineIds[] = $userId;

        $startDate = match($period) {
            'weekly' => now()->startOfWeek(),
            'monthly' => now()->startOfMonth(),
            'quarterly' => now()->startOfQuarter(),
            'yearly' => now()->startOfYear(),
            default => now()->startOfMonth(),
        };

        return \App\Models\Order::whereIn('user_id', $downlineIds)
            ->where('status', 'completed')
            ->where('created_at', '>=', $startDate)
            ->sum('total_amount');
    }

    public function clearCache(int $userId): void
    {
        for ($depth = 1; $depth <= 10; $depth++) {
            Cache::forget("genealogy_tree_{$userId}_{$depth}");
        }
    }
}
