<?php

namespace App\Services;

use App\Models\SeasonalCalendar;
use App\Models\SeasonalCache;
use App\Models\AiSubscription;
use Carbon\Carbon;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\DB;

class SeasonalPriceService
{
    /**
     * Calculate seasonal price adjustment for a given date and base price
     * Now returns detailed session information
     */
    public function calculateAdjustedPrice(float $basePrice, Carbon $date, int $travelAgentId): array
    {
        $userEligible = $this->isUserEligibleForSeasonalPricing($travelAgentId);
        
        if (!$userEligible) {
            return [
                'base_price' => $basePrice,
                'adjusted_price' => $basePrice,
                'total_hike_percentage' => 0,
                'seasonal_sessions' => [], // Empty array for consistency
                'is_eligible' => false
            ];
        }

        $seasonalData = $this->getSeasonalMultiplierForDate($date);
        
        $adjustedPrice = $basePrice * (1 + ($seasonalData['total_hike_percentage'] / 100));

        // Combine all sessions with their details
        $allSessions = array_merge(
            $seasonalData['regular_sessions'],
            $seasonalData['special_sessions']
        );

        return [
            'base_price' => $basePrice,
            'adjusted_price' => round($adjustedPrice, 2),
            'total_hike_percentage' => $seasonalData['total_hike_percentage'],
            'seasonal_sessions' => $allSessions, // Detailed session data
            'is_eligible' => true
        ];
    }

    /**
     * Get seasonal multiplier for a specific date with detailed session information
     */
    public function getSeasonalMultiplierForDate(Carbon $date): array
    {
        // Try cache first
        $cacheKey = "seasonal_multiplier_{$date->format('Y-m-d')}";
        $cached = Cache::get($cacheKey);
        
        if ($cached) {
            Log::info('Using cached seasonal multiplier', [
                'date' => $date->format('Y-m-d'),
                'cache_key' => $cacheKey
            ]);
            return $cached;
        }

        // Try database cache
        try {
            $dbCached = SeasonalCache::getCachedMultiplier($date);
            if ($dbCached) {
                $result = [
                    'total_hike_percentage' => $dbCached->total_hike_percentage,
                    'regular_sessions' => [],
                    'special_sessions' => []
                ];

                // Reconstruct session details from IDs
                foreach ($dbCached->applicable_sessions as $sessionId) {
                    $session = SeasonalCalendar::find($sessionId);
                    if ($session) {
                        $sessionData = [
                            'id' => $session->id,
                            'name' => $session->name,
                            'percentage' => (float) $session->price_increase_percentage,
                            'type' => $session->session_type,
                            'description' => $session->description
                        ];
                        
                        if ($session->session_type === 'regular') {
                            $result['regular_sessions'][] = $sessionData;
                        } else {
                            $result['special_sessions'][] = $sessionData;
                        }
                    }
                }

                Cache::put($cacheKey, $result, 3600);
                
                Log::info('Using database cached seasonal multiplier', [
                    'date' => $date->format('Y-m-d'),
                    'total_hike_percentage' => $result['total_hike_percentage'],
                    'sessions_count' => count($result['regular_sessions']) + count($result['special_sessions'])
                ]);
                
                return $result;
            }
        } catch (\Exception $e) {
            Log::warning('Database cache not available, calculating fresh', [
                'date' => $date->format('Y-m-d'),
                'error' => $e->getMessage()
            ]);
        }

        // Calculate fresh with detailed session data
        $result = $this->calculateFreshMultiplier($date);
        
        // Cache the result
        Cache::put($cacheKey, $result, 3600);
        
        // Store in database cache if table exists
        try {
            $sessionIds = array_merge(
                array_map(fn($s) => $s['id'], $result['regular_sessions']),
                array_map(fn($s) => $s['id'], $result['special_sessions'])
            );
            
            SeasonalCache::cacheMultiplier($date, $result['total_hike_percentage'], $sessionIds);
            
            Log::info('Fresh seasonal multiplier calculated and cached', [
                'date' => $date->format('Y-m-d'),
                'total_hike_percentage' => $result['total_hike_percentage'],
                'regular_sessions_count' => count($result['regular_sessions']),
                'special_sessions_count' => count($result['special_sessions'])
            ]);
        } catch (\Exception $e) {
            Log::warning('Failed to cache seasonal multiplier in database', [
                'date' => $date->format('Y-m-d'),
                'error' => $e->getMessage()
            ]);
        }

        return $result;
    }

    /**
     * Calculate seasonal multiplier from scratch with detailed session data
     */
    private function calculateFreshMultiplier(Carbon $date): array
    {
        $applicableSessions = SeasonalCalendar::active()->get()->filter(
            fn($session) => $session->isApplicableForDate($date)
        );

        Log::info('Seasonal calculation for date', [
            'date' => $date->format('Y-m-d'),
            'applicable_sessions_count' => $applicableSessions->count(),
            'sessions' => $applicableSessions->map(fn($s) => [
                'id' => $s->id,
                'name' => $s->name,
                'type' => $s->session_type,
                'percentage' => $s->price_increase_percentage
            ])->toArray()
        ]);

        // Separate regular and special sessions
        $regularSessions = $applicableSessions->where('session_type', 'regular');
        $specialSessions = $applicableSessions->where('session_type', 'special');

        $totalHike = 0;

        // For regular sessions: Take HIGHEST one only
        if ($regularSessions->isNotEmpty()) {
            $highestRegular = $regularSessions->max('price_increase_percentage');
            $totalHike += $highestRegular;
            
            // Get the highest regular session(s) - there might be multiple with same percentage
            $highestRegularSessions = $regularSessions->where('price_increase_percentage', $highestRegular);
        } else {
            $highestRegularSessions = collect();
        }

        // For special sessions: ADD ALL (additive)
        $specialTotal = $specialSessions->sum('price_increase_percentage');
        $totalHike += $specialTotal;

        Log::info('Total hike calculation', [
            'regular_contribution' => $highestRegularSessions->isNotEmpty() ? $highestRegular : 0,
            'special_contribution' => $specialTotal,
            'total_hike' => $totalHike
        ]);

        // Build detailed session arrays
        $regularSessionsData = $highestRegularSessions->map(function($session) {
            return [
                'id' => $session->id,
                'name' => $session->name,
                'percentage' => (float) $session->price_increase_percentage,
                'type' => $session->session_type,
                'description' => $session->description,
                'color_code' => $session->color_code
            ];
        })->toArray();

        $specialSessionsData = $specialSessions->map(function($session) {
            return [
                'id' => $session->id,
                'name' => $session->name,
                'percentage' => (float) $session->price_increase_percentage,
                'type' => $session->session_type,
                'description' => $session->description,
                'color_code' => $session->color_code
            ];
        })->toArray();

        return [
            'total_hike_percentage' => $totalHike,
            'regular_sessions' => $regularSessionsData,
            'special_sessions' => $specialSessionsData
        ];
    }

    /**
     * Bulk calculate multipliers for multiple dates with detailed session data
     */
    public function getBulkMultipliers(array $dates, int $travelAgentId): array
    {
        $userEligible = $this->isUserEligibleForSeasonalPricing($travelAgentId);
        $results = [];

        foreach ($dates as $dateString) {
            $date = Carbon::parse($dateString);
            
            if (!$userEligible) {
                $results[$dateString] = [
                    'total_hike_percentage' => 0,
                    'seasonal_sessions' => [],
                    'is_eligible' => false,
                    'regular_sessions' => [],
                    'special_sessions' => []
                ];
            } else {
                $multiplierData = $this->getSeasonalMultiplierForDate($date);
                $results[$dateString] = array_merge($multiplierData, [
                    'is_eligible' => true,
                    'multiplier' => 1 + ($multiplierData['total_hike_percentage'] / 100)
                ]);
            }
        }

        Log::info('Bulk seasonal multipliers calculated', [
            'travel_agent_id' => $travelAgentId,
            'user_eligible' => $userEligible,
            'dates_count' => count($dates),
            'results_summary' => array_map(fn($r) => [
                'hike_percentage' => $r['total_hike_percentage'],
                'sessions_count' => count($r['regular_sessions']) + count($r['special_sessions']),
                'is_eligible' => $r['is_eligible']
            ], $results)
        ]);

        return $results;
    }

    /**
     * Get seasonal calendar for a specific year/month with detailed session data
     */
    public function getSeasonalCalendar(int $year, ?int $month = null): array
    {
        $startDate = $month 
            ? Carbon::createFromDate($year, $month, 1)
            : Carbon::createFromDate($year, 1, 1);
            
        $endDate = $month
            ? $startDate->copy()->endOfMonth()
            : Carbon::createFromDate($year, 12, 31);

        $calendar = [];
        $sessions = SeasonalCalendar::active()->get();

        for ($date = $startDate->copy(); $date->lte($endDate); $date->addDay()) {
            $applicableSessions = $sessions->filter(
                fn($session) => $session->isApplicableForDate($date)
            );

            $regularSessions = $applicableSessions->where('session_type', 'regular');
            $specialSessions = $applicableSessions->where('session_type', 'special');

            $calendar[$date->format('Y-m-d')] = [
                'date' => $date->format('Y-m-d'),
                'applicable_sessions' => $applicableSessions->values()->toArray(),
                'total_hike_percentage' => $applicableSessions->isNotEmpty() 
                    ? $this->calculateTotalHike($applicableSessions) 
                    : 0,
                'regular_sessions' => $regularSessions->values()->toArray(),
                'special_sessions' => $specialSessions->values()->toArray()
            ];
        }

        return $calendar;
    }

    /**
     * Get detailed seasonal breakdown for reporting
     */
    public function getSeasonalBreakdown(array $dates, int $travelAgentId): array
    {
        $bulkMultipliers = $this->getBulkMultipliers($dates, $travelAgentId);
        
        $breakdown = [
            'total_days' => count($dates),
            'days_with_seasonal' => 0,
            'total_seasonal_revenue_impact' => 0,
            'session_breakdown' => [],
            'daily_breakdown' => []
        ];

        foreach ($bulkMultipliers as $date => $data) {
            if ($data['is_eligible'] && $data['total_hike_percentage'] > 0) {
                $breakdown['days_with_seasonal']++;
                
                $allSessions = array_merge($data['regular_sessions'], $data['special_sessions']);
                $breakdown['daily_breakdown'][$date] = [
                    'hike_percentage' => $data['total_hike_percentage'],
                    'sessions' => $allSessions
                ];

                // Track session usage for overall breakdown
                foreach ($allSessions as $session) {
                    $sessionName = $session['name'];
                    if (!isset($breakdown['session_breakdown'][$sessionName])) {
                        $breakdown['session_breakdown'][$sessionName] = [
                            'count' => 0,
                            'total_percentage' => 0,
                            'type' => $session['type']
                        ];
                    }
                    $breakdown['session_breakdown'][$sessionName]['count']++;
                    $breakdown['session_breakdown'][$sessionName]['total_percentage'] += $session['percentage'];
                }
            }
        }

        return $breakdown;
    }

    // ... (keep the existing isUserEligibleForSeasonalPricing, preCacheYear, calculateTotalHike methods as they are)
    
    /**
     * Check if user is eligible for seasonal pricing
     */
    public function isUserEligibleForSeasonalPricing(int $travelAgentId): bool
    {
        try {
            $subscription = AiSubscription::where('travel_agent_id', $travelAgentId)
                ->where('status', 'active')
                ->where('end_date', '>', now())
                ->with('plan')
                ->first();

            $isEligible = $subscription && $subscription->plan && $subscription->plan->name !== 'free';

            Log::info('Seasonal pricing eligibility check', [
                'travel_agent_id' => $travelAgentId,
                'subscription_found' => !is_null($subscription),
                'plan_name' => $subscription->plan->name ?? 'none',
                'is_eligible' => $isEligible
            ]);

            return $isEligible;

        } catch (\Exception $e) {
            Log::error('Error in seasonal pricing eligibility check', [
                'travel_agent_id' => $travelAgentId,
                'error' => $e->getMessage()
            ]);

            return false;
        }
    }

    /**
     * Calculate total hike from sessions
     */
    private function calculateTotalHike($sessions): float
    {
        $regularSessions = $sessions->where('session_type', 'regular');
        $specialSessions = $sessions->where('session_type', 'special');

        $totalHike = 0;

        if ($regularSessions->isNotEmpty()) {
            $totalHike += $regularSessions->max('price_increase_percentage');
        }

        $totalHike += $specialSessions->sum('price_increase_percentage');

        return $totalHike;
    }

    /**
     * Pre-cache seasonal data for a whole year
     */
    public function preCacheYear(int $year): void
    {
        $startDate = Carbon::createFromDate($year, 1, 1);
        $endDate = Carbon::createFromDate($year, 12, 31);

        $cachedCount = 0;
        $errorCount = 0;

        for ($date = $startDate->copy(); $date->lte($endDate); $date->addDay()) {
            try {
                $this->getSeasonalMultiplierForDate($date);
                $cachedCount++;
            } catch (\Exception $e) {
                $errorCount++;
                Log::error('Error pre-caching date', [
                    'date' => $date->format('Y-m-d'),
                    'error' => $e->getMessage()
                ]);
            }
        }

        Log::info('Seasonal pre-caching completed', [
            'year' => $year,
            'cached_days' => $cachedCount,
            'error_days' => $errorCount
        ]);
    }
}