<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Models\AdAnalytics;
use App\Models\AdAnalyticsRealtime;
use App\Models\Ad;
use Carbon\Carbon;
use Illuminate\Support\Facades\Auth;

class AnalyticsController extends Controller
{
    /**
     * Get overview analytics for the authenticated user
     * GET /api/v1/analytics/overview
     */
    public function overview(Request $request)
    {
        $user = Auth::user()->fresh('currentPlan');
        
        // Check if user has analytics access (VIP only)
        if (!$user->currentPlan || !($user->currentPlan->has_analytics ?? false)) {
            return response()->json([
                'message' => 'Analytics feature requires VIP plan',
                'upgrade_required' => true
            ], 403);
        }

        $validated = $request->validate([
            'period' => 'nullable|string|in:last_7_days,last_30_days,last_90_days',
            'start_date' => 'nullable|date',
            'end_date' => 'nullable|date|after_or_equal:start_date',
        ]);

        // Determine date range
        [$startDate, $endDate] = $this->getDateRange($validated);

        // Get user's ads
        $adIds = Ad::where('user_id', $user->id)->pluck('id');

        if ($adIds->isEmpty()) {
            return response()->json([
                'period' => $validated['period'] ?? 'last_30_days',
                'total_impressions' => 0,
                'total_views' => 0,
                'total_clicks' => 0,
                'avg_ctr' => 0,
                'trending_ads' => [],
                'analytics_tier' => 'advanced',
            ]);
        }

        // Aggregate stats
        $stats = AdAnalytics::whereIn('ad_id', $adIds)
            ->dateRange($startDate, $endDate)
            ->selectRaw('
                SUM(impressions) as total_impressions,
                SUM(views) as total_views,
                SUM(clicks) as total_clicks,
                AVG(ctr) as avg_ctr,
                AVG(bounce_rate) as avg_bounce_rate
            ')
            ->first();

        // Calculate Previous Period for Trends
        $daysDiff = $startDate->diffInDays($endDate);
        if ($daysDiff < 1) $daysDiff = 1;
        $prevEndDate = $startDate->copy()->subDay();
        $prevStartDate = $prevEndDate->copy()->subDays($daysDiff);
        
        $prevStats = AdAnalytics::whereIn('ad_id', $adIds)
            ->dateRange($prevStartDate, $prevEndDate)
            ->selectRaw('
                SUM(impressions) as total_impressions,
                SUM(views) as total_views,
                SUM(clicks) as total_clicks
            ')
            ->first();
            
        $trends = [
            'impressions' => $this->calculateTrend($stats->total_impressions ?? 0, $prevStats->total_impressions ?? 0),
            'views' => $this->calculateTrend($stats->total_views ?? 0, $prevStats->total_views ?? 0),
            'clicks' => $this->calculateTrend($stats->total_clicks ?? 0, $prevStats->total_clicks ?? 0),
        ];

        // Get trending ads (highest CTR in period)
        $trendingAds = AdAnalytics::whereIn('ad_id', $adIds)
            ->dateRange($startDate, $endDate)
            ->selectRaw('ad_id, SUM(views) as total_views, AVG(ctr) as avg_ctr')
            ->groupBy('ad_id')
            ->orderBy('avg_ctr', 'DESC')
            ->limit(5)
            ->get()
            ->map(function ($item) {
                $ad = Ad::find($item->ad_id);
                return [
                    'ad_id' => $item->ad_id,
                    'title' => $ad->title ?? 'Unknown',
                    'total_views' => $item->total_views,
                    'avg_ctr' => round($item->avg_ctr, 2),
                ];
            });

        return response()->json([
            'period' => $validated['period'] ?? 'custom',
            'start_date' => $startDate->toDateString(),
            'end_date' => $endDate->toDateString(),
            'total_impressions' => $stats->total_impressions ?? 0,
            'total_views' => $stats->total_views ?? 0,
            'total_clicks' => $stats->total_clicks ?? 0,
            'avg_ctr' => round($stats->avg_ctr ?? 0, 2),
            'avg_bounce_rate' => round($stats->avg_bounce_rate ?? 0, 2),
            'trends' => $trends,
            'trending_ads' => $trendingAds,
            'analytics_tier' => 'advanced',
        ]);
    }

    /**
     * Compare performance of specific ads
     * POST /api/v1/analytics/compare
     */
    public function compare(Request $request) 
    {
        $user = Auth::user();
        $validated = $request->validate([
            'ad_ids' => 'required|array|min:2|max:3',
            'ad_ids.*' => 'integer|exists:ads,id',
            'period' => 'nullable|string|in:last_7_days,last_30_days,last_90_days',
        ]);

        [$startDate, $endDate] = $this->getDateRange($validated);
        $adIds = $validated['ad_ids'];

        // Verify ownership
        $ownedAds = Ad::whereIn('id', $adIds)->where('user_id', $user->id)->count();
        if ($ownedAds != count($adIds)) {
            return response()->json(['message' => 'Invalid ads selected'], 403);
        }

        $comparisonData = [];
        foreach ($adIds as $adId) {
            $ad = Ad::find($adId);
            $stats = AdAnalytics::forAd($adId)
                ->dateRange($startDate, $endDate)
                ->selectRaw('
                    SUM(impressions) as impressions,
                    SUM(views) as views,
                    SUM(clicks) as clicks,
                    AVG(ctr) as ctr,
                    AVG(bounce_rate) as bounce_rate
                ')
                ->first();

            $comparisonData[] = [
                'ad_id' => $ad->id,
                'title' => $ad->title,
                'image' => $ad->images[0] ?? null,
                'stats' => [
                    'impressions' => $stats->impressions ?? 0,
                    'views' => $stats->views ?? 0,
                    'clicks' => $stats->clicks ?? 0,
                    'ctr' => round($stats->ctr ?? 0, 2),
                    'bounce_rate' => round($stats->bounce_rate ?? 0, 2),
                ]
            ];
        }

        return response()->json([
            'period' => $validated['period'] ?? 'last_30_days',
            'comparison' => $comparisonData
        ]);
    }
    
    private function calculateTrend($current, $previous) {
        if ($previous == 0) {
            return $current > 0 ? 100 : 0;
        }
        return round((($current - $previous) / $previous) * 100, 1);
    }

    /**
     * Get detailed analytics for a specific ad
     * GET /api/v1/analytics/ad/{id}
     */
    public function adAnalytics(Request $request, $adId)
    {
        $user = Auth::user();
        
        // Verify ad ownership
        $ad = Ad::where('id', $adId)->where('user_id', $user->id)->first();
        
        if (!$ad) {
            return response()->json(['message' => 'Ad not found'], 404);
        }

        $validated = $request->validate([
            'start_date' => 'nullable|date',
            'end_date' => 'nullable|date|after_or_equal:start_date',
            'granularity' => 'nullable|string|in:day,week,month',
        ]);

        [$startDate, $endDate] = $this->getDateRange($validated);
        $granularity = $validated['granularity'] ?? 'day';

        // Get aggregated metrics
        $metrics = AdAnalytics::forAd($adId)
            ->dateRange($startDate, $endDate)
            ->selectRaw('
                SUM(impressions) as impressions,
                SUM(views) as views,
                SUM(clicks) as clicks,
                AVG(ctr) as ctr,
                AVG(bounce_rate) as bounce_rate,
                AVG(avg_time_spent) as avg_time_spent
            ')
            ->first();

        // Get chart data (time series)
        $chartData = AdAnalytics::forAd($adId)
            ->dateRange($startDate, $endDate)
            ->selectRaw('date, SUM(impressions) as impressions, SUM(views) as views, SUM(clicks) as clicks')
            ->groupBy('date')
            ->orderBy('date')
            ->get()
            ->map(function ($item) {
                return [
                    'date' => $item->date->format('Y-m-d'),
                    'impressions' => $item->impressions,
                    'views' => $item->views,
                    'clicks' => $item->clicks,
                ];
            });

        // Get rich analytics from service
        $richAnalytics = app(\App\Services\IndividualAdAnalyticsService::class)
            ->getAdAnalytics($adId, $startDate->toDateString(), $endDate->toDateString());

        return response()->json([
            'ad_id' => $adId,
            'title' => $ad->title,
            'metrics' => [
                'impressions' => $metrics->impressions ?? 0,
                'views' => $metrics->views ?? 0,
                'clicks' => $metrics->clicks ?? 0,
                'ctr' => round($metrics->ctr ?? 0, 2),
                'bounce_rate' => round($metrics->bounce_rate ?? 0, 2),
                'avg_time_spent' => round($metrics->avg_time_spent ?? 0),
            ],
            'chart_data' => [
                'daily_views' => $chartData,
            ],
            // Expanded Data for Demographics Screen
            'geographic_analytics' => $richAnalytics['geographic_analytics'] ?? [],
            'device_analytics' => $richAnalytics['device_analytics'] ?? [],
            'temporal_analytics' => $richAnalytics['temporal_analytics'] ?? [],
            'sources' => $richAnalytics['traffic_source_analytics']['sources'] ?? [],
        ]);
    }

    /**
     * Get real-time analytics overview for all user ads
     * GET /api/v1/analytics/realtime/overview
     */
    public function realtimeOverview(Request $request)
    {
        $user = Auth::user();
        $validated = $request->validate([
            'range' => 'nullable|string|in:30min,60min,3h,6h,12h,24h,48h',
        ]);
        $range = $validated['range'] ?? '60min';

        // 1. Get User Ads
        $adIds = Ad::where('user_id', $user->id)->pluck('id');
        
        if ($adIds->isEmpty()) {
             return response()->json([
                'timestamp' => now()->toIso8601String(),
                'summary' => ['impressions' => 0, 'views' => 0, 'clicks' => 0, 'active_viewers' => 0],
                'timeline' => [],
                'active_ads' => [],
             ]);
        }

        // 2. Define Time Window
        $now = Carbon::now();
        $minutes = match($range) {
            '30min' => 30,
            '60min' => 60,
            '3h' => 180,
            '6h' => 360,
            '12h' => 720,
            '24h' => 1440,
            '48h' => 2880,
            default => 60
        };
        $startTime = $now->copy()->subMinutes($minutes);

        // 3. Aggregate Realtime Events
        $events = AdAnalyticsRealtime::whereIn('ad_id', $adIds)
            ->whereBetween('created_at', [$startTime, $now])
            ->get();

        // 4. Build Timeline
        $timeline = [];
        
        // Determine grouping interval based on range duration to avoid massive JSON payloads
        // < 3h: 1 min
        // 3h - 12h: 5 min
        // > 12h: 15 min
        $interval = 1; 
        if ($minutes > 180 && $minutes <= 720) $interval = 5;
        if ($minutes > 720) $interval = 15;

        for ($i = 0; $i < $minutes; $i += $interval) {
            $timeSlot = $now->copy()->subMinutes($i);
            // Round to nearest interval
            $timeSlot = $timeSlot->minute((int)($timeSlot->minute / $interval) * $interval)->second(0);
            
            $slotKey = $timeSlot->format('H:i');
            
            // Filter events for this interval (inclusive)
            $upperBound = $timeSlot->copy()->addMinutes($interval);
            
            $slotEvents = $events->filter(function($e) use ($timeSlot, $upperBound) {
                return $e->created_at >= $timeSlot && $e->created_at < $upperBound;
            });

            $timeline[] = [
                'time' => $timeSlot->toIso8601String(),
                'minute_label' => $slotKey,
                'impressions' => $slotEvents->where('event_type', 'impression')->count(),
                'views' => $slotEvents->where('event_type', 'view')->count(),
                'clicks' => $slotEvents->where('event_type', 'click')->count(),
            ];
        }

        // 5. Build Active Ads List
        $activeAds = $adIds->map(function($id) use ($events, $user) {
            $adEvents = $events->where('ad_id', $id);
            $ad = Ad::find($id);
            
            $views = $adEvents->where('event_type', 'view')->count();
            $impressions = $adEvents->where('event_type', 'impression')->count();
            $clicks = $adEvents->where('event_type', 'click')->count();
            
            // If no activity, verify if we should verify
            if ($views + $impressions + $clicks == 0) return null;

            return [
                'ad_id' => $id,
                'title' => $ad->title,
                'impressions' => $impressions,
                'views' => $views,
                'clicks' => $clicks,
                'ctr' => $views > 0 ? round(($clicks / $views) * 100, 1) : 0,
                'live_viewers' => rand(0, 5), // Simulation for now
                'trend' => rand(0, 1) ? 'up' : 'stable',
            ];
        })->filter()->values();

        return response()->json([
            'timestamp' => $now->toIso8601String(),
            'summary' => [
                'impressions' => $events->where('event_type', 'impression')->count(),
                'views' => $events->where('event_type', 'view')->count(),
                'clicks' => $events->where('event_type', 'click')->count(),
                'active_viewers' => $activeAds->sum('live_viewers'),
            ],
            'timeline' => array_reverse($timeline), // Oldest first
            'active_ads' => $activeAds
        ]);
    }

    /**
     * Get real-time analytics for a specific ad
     * GET /api/v1/analytics/realtime/{id}
     */
    public function realtimeAnalytics(Request $request, $adId)
    {
        // Re-using logic or keeping specific implementation
        return response()->json(['message' => 'Use overview endpoint for dashboard']); 
    }

    /**
     * Get performance of ad packages
     * GET /api/v1/analytics/packages
     */
    public function packagePerformance(Request $request)
    {
        $data = app(\App\Services\IndividualAdAnalyticsService::class)
            ->getPackagePerformance(Auth::id());
        
        return response()->json(['packages' => $data]);
    }

    /**
     * Get AI-generated suggestions for user's ads
     * GET /api/v1/analytics/suggestions
     */
    public function suggestions(Request $request)
    {
        $user = Auth::user();
        
        $aiService = new \App\Services\AIInsightsService();
        $suggestions = $aiService->getUserSuggestions($user->id);
        
        return response()->json([
            'suggestions' => $suggestions,
            'total' => count($suggestions),
        ]);
    }
    
    /**
     * Get AI suggestions for a specific ad
     * GET /api/v1/analytics/ad/{id}/suggestions
     */
    public function adSuggestions(Request $request, $adId)
    {
        $user = Auth::user();
        
        // Verify ad ownership
        $ad = Ad::where('id', $adId)->where('user_id', $user->id)->first();
        
        if (!$ad) {
            return response()->json(['message' => 'Ad not found'], 404);
        }
        
        $aiService = new \App\Services\AIInsightsService();
        $suggestions = $aiService->generateSuggestions($ad);
        
        return response()->json([
            'ad_id' => $adId,
            'suggestions' => $suggestions,
        ]);
    }

    // Helper: Get date range from request
    private function getDateRange(array $validated): array
    {
        if (isset($validated['start_date']) && isset($validated['end_date'])) {
            return [
                Carbon::parse($validated['start_date'])->startOfDay(),
                Carbon::parse($validated['end_date'])->endOfDay(),
            ];
        }

        $period = $validated['period'] ?? 'last_30_days';
        $endDate = Carbon::now()->endOfDay();
        
        $periodMap = [
            'last_7_days' => 7,
            'last_30_days' => 30,
            'last_90_days' => 90,
        ];

        $days = $periodMap[$period] ?? 30;
        $startDate = Carbon::now()->subDays($days)->startOfDay();

        return [$startDate, $endDate];
    }

    // Legacy methods (keep for backward compatibility)
    public function dashboard() {}
    public function adPostAnalytics() {}
    public function userAnalytics() {}
    public function engagementAnalytics() {}
    public function businessIntelligence() {}
    public function aiInsights() {}
    public function executiveSummary() {}
    public function exportReport() {}
    public function geoDistributionReport() {}
}
