<?php

namespace App\Http\Controllers;

use App\Models\TierGame;
use App\Models\TierGameGroup;
use App\Models\SubscriptionPlan;
use App\Models\UserSubscription;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class TierGameController extends Controller
{
    private const CACHE_TTL = 60;

    /**
     * Get game groups for user's active subscription tier
     */
    public function myGames()
    {
        $user = Auth::user();
        
        $activeSubscription = UserSubscription::with('plan')
            ->where('user_id', $user->id)
            ->active()
            ->first();

        if (!$activeSubscription) {
            return response()->json([
                'success' => false,
                'error' => 'No active subscription found',
                'groups' => []
            ], 403);
        }

        // Only show games posted from when user subscribed
        $groups = TierGameGroup::with('games')
            ->where('subscription_plan_id', $activeSubscription->subscription_plan_id)
            ->where('selling', true)
            ->where('created_at', '>=', $activeSubscription->starts_at)
            ->where('created_at', '<=', $activeSubscription->expires_at)
            ->orderBy('created_at', 'desc')
            ->limit(50)
            ->get();

        return response()->json([
            'success' => true,
            'subscription' => [
                'plan' => $activeSubscription->plan->name,
                'starts_at' => $activeSubscription->starts_at,
                'expires_at' => $activeSubscription->expires_at,
                'days_remaining' => $activeSubscription->daysRemaining(),
            ],
            'groups' => $groups
        ]);
    }

    /**
     * Get specific game group with games
     */
    public function showGroup($id)
    {
        $user = Auth::user();
        
        $activeSubscription = UserSubscription::where('user_id', $user->id)
            ->active()
            ->first();

        if (!$activeSubscription) {
            return response()->json(['error' => 'No active subscription'], 403);
        }

        $group = TierGameGroup::with('games')
            ->where('id', $id)
            ->where('subscription_plan_id', $activeSubscription->subscription_plan_id)
            ->where('created_at', '>=', $activeSubscription->starts_at)
            ->where('created_at', '<=', $activeSubscription->expires_at)
            ->first();

        if (!$group) {
            return response()->json(['error' => 'Game group not found or not within your subscription period'], 404);
        }

        return response()->json([
            'success' => true,
            'group' => $group
        ]);
    }

    // ==================== ADMIN ENDPOINTS ====================

    /**
     * Admin: Get all game groups (like VIP index)
     */
    public function index(Request $request)
    {
        $planId = $request->query('plan_id');
        
        $query = TierGameGroup::with(['games', 'subscriptionPlan'])
            ->orderBy('created_at', 'desc');

        if ($planId) {
            $query->where('subscription_plan_id', $planId);
        }

        $groups = $query->limit(50)->get();

        return response()->json($groups);
    }

    /**
     * Admin: Get groups by date
     */
    public function getByDate(Request $request, $planId)
    {
        $startDate = $request->query('start_date');
        $endDate = $request->query('end_date');

        $query = TierGameGroup::with('games')
            ->where('subscription_plan_id', $planId);

        if ($startDate && $endDate) {
            $query->whereBetween('created_at', [$startDate, $endDate]);
        }

        $groups = $query->orderBy('created_at', 'desc')->get();

        return response()->json($groups);
    }

    /**
     * Admin: Create game group with games (like VIP store)
     */
    public function store(Request $request)
    {
        $validated = $request->validate([
            'subscription_plan_id' => 'required|exists:subscription_plans,id',
            'price' => 'nullable|numeric',
            'selling' => 'required|boolean',
            'sporty_booking' => 'nullable|string',
            'onex_booking' => 'nullable|string',
            'msport_booking' => 'nullable|string',
            'betway_booking' => 'nullable|string',
            'created_at' => 'nullable|date',
            'games' => 'required|array',
            'games.*.date_time' => 'required|date',
            'games.*.home_team' => 'required|string|max:255',
            'games.*.away_team' => 'required|string|max:255',
            'games.*.league' => 'required|string|max:255',
            'games.*.option' => 'required|string|max:255',
            'games.*.odds' => 'required|numeric',
        ]);

        DB::beginTransaction();
        try {
            $group = TierGameGroup::create([
                'subscription_plan_id' => $validated['subscription_plan_id'],
                'price' => $validated['price'] ?? null,
                'selling' => $validated['selling'],
                'sporty_booking' => $validated['sporty_booking'] ?? null,
                'onex_booking' => $validated['onex_booking'] ?? null,
                'msport_booking' => $validated['msport_booking'] ?? null,
                'betway_booking' => $validated['betway_booking'] ?? null,
                'created_at' => $validated['created_at'] ?? Carbon::now(),
            ]);

            $timestamp = now();
            $bulkGames = array_map(function($game) use ($group, $timestamp) {
                $game['tier_game_group_id'] = $group->id;
                $game['created_at'] = $timestamp;
                $game['updated_at'] = $timestamp;
                // Convert date_time to MySQL format
                if (isset($game['date_time'])) {
                    $game['date_time'] = Carbon::parse($game['date_time'])->format('Y-m-d H:i:s');
                }
                return $game;
            }, $validated['games']);

            TierGame::insert($bulkGames);

            $createdGames = TierGame::where('tier_game_group_id', $group->id)->get();

            DB::commit();

            $this->clearTierCaches($validated['subscription_plan_id']);

            Log::info('Tier game group created', [
                'group_id' => $group->id,
                'plan_id' => $validated['subscription_plan_id'],
                'games_count' => count($createdGames)
            ]);

            return response()->json(['group' => $group, 'games' => $createdGames], 201);

        } catch (\Exception $e) {
            DB::rollBack();
            Log::error('Error creating tier game group: ' . $e->getMessage());
            return response()->json(['message' => 'Error creating tier games'], 500);
        }
    }

    /**
     * Admin: Show single group
     */
    public function show($id)
    {
        $group = TierGameGroup::with(['games', 'subscriptionPlan'])->find($id);

        if (!$group) {
            return response()->json(['message' => 'Group Not Found'], 404);
        }

        return response()->json($group);
    }

    /**
     * Admin: Update game group (like VIP update)
     */
    public function update(Request $request, $id)
    {
        $group = TierGameGroup::find($id);
        if (!$group) {
            return response()->json(['message' => 'Group Not Found'], 404);
        }

        DB::beginTransaction();
        try {
            $group->update($request->only([
                'subscription_plan_id', 'price', 'selling', 
                'msport_booking', 'onex_booking', 'betway_booking', 'sporty_booking', 
                'status', 'created_at'
            ]));

            if ($request->has('games')) {
                $games = $request->input('games');

                TierGame::where('tier_game_group_id', $id)->delete();

                $timestamp = now();
                $bulkGames = array_map(function($game) use ($id, $timestamp) {
                    $game['tier_game_group_id'] = $id;
                    $game['created_at'] = $timestamp;
                    $game['updated_at'] = $timestamp;
                    // Convert date_time to MySQL format
                    if (isset($game['date_time'])) {
                        $game['date_time'] = Carbon::parse($game['date_time'])->format('Y-m-d H:i:s');
                    }
                    return $game;
                }, $games);

                TierGame::insert($bulkGames);
            }

            $group->load('games');

            DB::commit();

            $this->clearTierCaches($group->subscription_plan_id);

            return response()->json(['group' => $group, 'games' => $group->games]);

        } catch (\Exception $e) {
            DB::rollBack();
            Log::error('Error updating tier game group: ' . $e->getMessage());
            return response()->json(['message' => 'Error updating tier games'], 500);
        }
    }

    /**
     * Admin: Update group status (won/lost)
     */
    public function updateStatus(Request $request, $id)
    {
        $request->validate([
            'status' => 'required|in:pending,won,lost',
            'type' => 'required|in:group,individual',
        ]);

        if ($request->type === 'group') {
            $group = TierGameGroup::find($id);

            if (!$group) {
                return response()->json(['error' => 'Group not found'], 404);
            }

            $group->update(['status' => $request->status]);

            // If group status is won, also set all individual games to won
            if ($request->status === 'won') {
                TierGame::where('tier_game_group_id', $id)->update(['status' => 'won']);
            }

            // If group status is reset to pending/default, also reset all individual games
            if ($request->status === 'pending') {
                TierGame::where('tier_game_group_id', $id)->update(['status' => 'pending']);
            }

            $this->clearTierCaches($group->subscription_plan_id);

            return response()->json([
                'success' => true,
                'message' => 'Group status updated to ' . $request->status,
                'group' => $group->load('games')
            ]);

        } else if ($request->type === 'individual') {
            $game = TierGame::find($id);

            if (!$game) {
                return response()->json(['error' => 'Game not found'], 404);
            }

            $game->update(['status' => $request->status]);

            // Clear cache for the parent group
            if ($game->tier_game_group_id) {
                $group = TierGameGroup::find($game->tier_game_group_id);
                if ($group) {
                    $this->clearTierCaches($group->subscription_plan_id);
                }
            }

            return response()->json([
                'success' => true,
                'message' => 'Individual game status updated to ' . $request->status,
                'game' => $game
            ]);
        }

        return response()->json(['error' => 'Invalid request'], 400);
    }

    /**
     * Admin: Delete game group
     */
    public function destroy($id)
    {
        $group = TierGameGroup::find($id);

        if (!$group) {
            return response()->json(['error' => 'Group not found'], 404);
        }

        $planId = $group->subscription_plan_id;
        $group->delete();

        $this->clearTierCaches($planId);

        return response()->json([
            'success' => true,
            'message' => 'Game group deleted successfully'
        ]);
    }

    /**
     * Admin: Transfer group to different tier
     */
    public function transfer(Request $request, $id)
    {
        $group = TierGameGroup::with('games')->find($id);

        if (!$group) {
            return response()->json(['error' => 'Group not found'], 404);
        }

        $request->validate([
            'target_plan_id' => 'required|exists:subscription_plans,id',
        ]);

        $oldPlanId = $group->subscription_plan_id;
        $group->update(['subscription_plan_id' => $request->target_plan_id]);

        $targetPlan = SubscriptionPlan::find($request->target_plan_id);

        $this->clearTierCaches($oldPlanId);
        $this->clearTierCaches($request->target_plan_id);

        Log::info('Tier game group transferred', [
            'group_id' => $id,
            'from_plan_id' => $oldPlanId,
            'to_plan_id' => $request->target_plan_id
        ]);

        return response()->json([
            'success' => true,
            'message' => "Game group transferred to {$targetPlan->name}",
            'group' => $group->fresh()->load('games')
        ]);
    }

    /**
     * Admin: Duplicate group to other tier(s)
     */
    public function duplicate(Request $request, $id)
    {
        $group = TierGameGroup::with('games')->find($id);

        if (!$group) {
            return response()->json(['error' => 'Group not found'], 404);
        }

        $request->validate([
            'target_plan_ids' => 'required|array|min:1',
            'target_plan_ids.*' => 'exists:subscription_plans,id',
        ]);

        $duplicatedGroups = [];

        DB::beginTransaction();
        try {
            foreach ($request->target_plan_ids as $planId) {
                if ($planId == $group->subscription_plan_id) {
                    continue;
                }

                $newGroup = TierGameGroup::create([
                    'subscription_plan_id' => $planId,
                    'price' => $group->price,
                    'selling' => $group->selling,
                    'status' => $group->status,
                    'sporty_booking' => $group->sporty_booking,
                    'msport_booking' => $group->msport_booking,
                    'betway_booking' => $group->betway_booking,
                    'onex_booking' => $group->onex_booking,
                ]);

                $timestamp = now();
                $bulkGames = $group->games->map(function($game) use ($newGroup, $timestamp) {
                    return [
                        'tier_game_group_id' => $newGroup->id,
                        'date_time' => $game->date_time,
                        'home_team' => $game->home_team,
                        'away_team' => $game->away_team,
                        'league' => $game->league,
                        'option' => $game->option,
                        'odds' => $game->odds,
                        'status' => $game->status,
                        'created_at' => $timestamp,
                        'updated_at' => $timestamp,
                    ];
                })->toArray();

                TierGame::insert($bulkGames);

                $duplicatedGroups[] = $newGroup->load('games');
                $this->clearTierCaches($planId);
            }

            DB::commit();

            Log::info('Tier game group duplicated', [
                'original_group_id' => $id,
                'duplicated_to' => $request->target_plan_ids
            ]);

            return response()->json([
                'success' => true,
                'message' => count($duplicatedGroups) . ' group(s) duplicated successfully',
                'original_group' => $group,
                'duplicated_groups' => $duplicatedGroups
            ]);

        } catch (\Exception $e) {
            DB::rollBack();
            Log::error('Error duplicating tier game group: ' . $e->getMessage());
            return response()->json(['message' => 'Error duplicating tier games'], 500);
        }
    }

    /**
     * Admin: Duplicate group to ALL tiers
     */
    public function duplicateToAll(Request $request, $id)
    {
        $group = TierGameGroup::find($id);

        if (!$group) {
            return response()->json(['error' => 'Group not found'], 404);
        }

        $allPlanIds = SubscriptionPlan::active()->pluck('id')->toArray();
        $targetPlanIds = array_filter($allPlanIds, function($planId) use ($group) {
            return $planId != $group->subscription_plan_id;
        });

        $request->merge(['target_plan_ids' => array_values($targetPlanIds)]);

        return $this->duplicate($request, $id);
    }

    /**
     * Admin: Get stats for tier games
     */
    public function stats()
    {
        $plans = SubscriptionPlan::active()->get();
        
        $stats = [];
        foreach ($plans as $plan) {
            $totalGroups = TierGameGroup::where('subscription_plan_id', $plan->id)->count();
            $wonGroups = TierGameGroup::where('subscription_plan_id', $plan->id)->where('status', 'won')->count();
            $lostGroups = TierGameGroup::where('subscription_plan_id', $plan->id)->where('status', 'lost')->count();
            $pendingGroups = TierGameGroup::where('subscription_plan_id', $plan->id)->whereNull('status')->orWhere('status', 'pending')->count();
            
            $winRate = $totalGroups > 0 ? round(($wonGroups / max(1, $wonGroups + $lostGroups)) * 100, 1) : 0;

            $stats[] = [
                'plan' => $plan->name,
                'plan_id' => $plan->id,
                'total_groups' => $totalGroups,
                'won' => $wonGroups,
                'lost' => $lostGroups,
                'pending' => $pendingGroups,
                'win_rate' => $winRate . '%'
            ];
        }

        return response()->json([
            'success' => true,
            'stats' => $stats
        ]);
    }

    private function clearTierCaches($planId = null)
    {
        Cache::forget('tier_groups.index');
        if ($planId) {
            Cache::forget("tier_groups.plan.{$planId}");
        }
    }
}
