<?php

namespace App\Http\Controllers\Brand;

use App\Http\Controllers\Controller;
use App\Models\Campaign;
use App\Models\SocialAggregate;
use App\Models\SocialPost;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;

class AnalyticsController extends Controller
{
    /**
     * Display the analytics dashboard
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        // Guard clause for brand not found
        $brand = auth()->user()->brand;
        if (!$brand) {
            return redirect()->route('dashboard')->with('error', 'Brand not found');
        }
        
        // Get the brand's social accounts
        $socialAccounts = $brand->socialAccounts;
        
        // Get available campaigns for filtering
        $campaigns = Campaign::where('brand_id', $brand->id)->get();
        
        // Get analytics data with default parameters
        $analyticsData = $this->getAnalyticsData($brand->id, 30);
        
        // Extract KPIs
        $totalFollowers = $analyticsData['total_followers'];
        $totalPosts = $analyticsData['total_posts'];
        $engagementRate = $analyticsData['engagement_rate'];
        $totalLikes = $analyticsData['total_likes'];
        $totalComments = $analyticsData['total_comments'];
        $totalShares = $analyticsData['total_shares'];
        $totalSaves = $analyticsData['total_saves'];
        $totalImpressions = $analyticsData['total_impressions'];
        $followerGrowth = $analyticsData['follower_growth'];
        
        return view('brand.analytics.index', compact(
            'socialAccounts', 
            'campaigns',
            'totalFollowers', 
            'totalPosts', 
            'engagementRate',
            'totalLikes',
            'totalComments',
            'totalShares',
            'totalSaves',
            'totalImpressions',
            'followerGrowth'
        ));
    }
    
    /**
     * Return analytics data as JSON for charts
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function data(Request $request)
    {
        // Guard clause for brand not found
        $brand = auth()->user()->brand;
        if (!$brand) {
            return response()->json(['error' => 'Brand not found'], 404);
        }
        
        $provider = $request->input('provider');
        $days = $request->input('days', 30);
        $campaignId = $request->input('campaign_id');
        
        $data = $this->getAnalyticsData($brand->id, $days, $provider, $campaignId);
        
        return response()->json($data);
    }
    
    /**
     * Get comprehensive analytics data
     *
     * @param int $brandId
     * @param int $days
     * @param string|null $provider
     * @param int|null $campaignId
     * @return array
     */
    protected function getAnalyticsData($brandId, $days = 30, $provider = null, $campaignId = null)
    {
        $cacheKey = "brand_analytics_{$brandId}_{$days}_{$provider}_{$campaignId}";
        
        return Cache::remember($cacheKey, 300, function () use ($brandId, $days, $provider, $campaignId) {
            // Get date range
            $startDate = now()->subDays($days);
            
            // Build query for social posts
            $postsQuery = SocialPost::whereHas('socialAccount', function ($query) use ($brandId, $provider) {
                $query->where('brand_id', $brandId);
                if ($provider && $provider !== 'all') {
                    $query->where('provider', $provider);
                }
            })->where('published_at', '>=', $startDate);
            
            // If campaign filtering is enabled, we'll need to add that logic
            if ($campaignId) {
                $postsQuery->where('campaign_id', $campaignId);
            }
            
            // Get all posts for calculations
            $posts = $postsQuery->get();
            
            // Calculate metrics
            $totalImpressions = 0;
            $totalLikes = 0;
            $totalComments = 0;
            $totalShares = 0;
            $totalSaves = 0;
            
            foreach ($posts as $post) {
                $metrics = $post->metrics ?? [];
                $totalImpressions += $metrics['views'] ?? 0;
                $totalLikes += $metrics['likes'] ?? 0;
                $totalComments += $metrics['comments'] ?? 0;
                $totalShares += $metrics['shares'] ?? 0;
                $totalSaves += $metrics['saves'] ?? 0;
            }
            
            // Calculate engagement rate: (likes + comments + shares + saves) / impressions
            $engagementRate = 0;
            if ($totalImpressions > 0) {
                $engagementRate = round((($totalLikes + $totalComments + $totalShares + $totalSaves) / $totalImpressions) * 100, 2);
            }
            
            // Get follower data
            $totalFollowers = SocialAggregate::where('brand_id', $brandId)
                ->where('key', 'total_followers')
                ->value('value');
                
            $totalFollowers = $totalFollowers ? $totalFollowers['value'] ?? 0 : 0;
            
            // Get follower growth (compare with previous period)
            $previousStartDate = now()->subDays($days * 2);
            $previousEndDate = now()->subDays($days);
            
            $previousFollowers = SocialAggregate::where('brand_id', $brandId)
                ->where('key', 'total_followers')
                ->where('computed_at', '<=', $previousEndDate)
                ->orderBy('computed_at', 'desc')
                ->first();
                
            $previousFollowersCount = $previousFollowers ? $previousFollowers->getNumericValue() : 0;
            $followerGrowth = 0;
            
            if ($previousFollowersCount > 0) {
                $followerGrowth = round((($totalFollowers - $previousFollowersCount) / $previousFollowersCount) * 100, 2);
            }
            
            // Get total posts
            $totalPosts = $posts->count();
            
            // Get time series data for charts
            $timeSeriesData = $this->getTimeSeriesData($postsQuery, $days);
            
            // Get top performing posts
            $topPosts = $posts->sortByDesc(function ($post) {
                $metrics = $post->metrics ?? [];
                return ($metrics['likes'] ?? 0) + ($metrics['comments'] ?? 0) + ($metrics['shares'] ?? 0);
            })->take(5);
            
            $topPostsData = [];
            foreach ($topPosts as $post) {
                $metrics = $post->metrics ?? [];
                $topPostsData[] = [
                    'title' => $post->title ?? 'Untitled',
                    'provider' => $post->socialAccount->provider ?? 'Unknown',
                    'impressions' => $metrics['views'] ?? 0,
                    'engagement' => ($metrics['likes'] ?? 0) + ($metrics['comments'] ?? 0) + ($metrics['shares'] ?? 0)
                ];
            }
            
            return [
                'total_followers' => $totalFollowers,
                'total_posts' => $totalPosts,
                'engagement_rate' => $engagementRate,
                'total_likes' => $totalLikes,
                'total_comments' => $totalComments,
                'total_shares' => $totalShares,
                'total_saves' => $totalSaves,
                'total_impressions' => $totalImpressions,
                'follower_growth' => $followerGrowth,
                'time_series' => $timeSeriesData,
                'top_posts' => $topPostsData,
                'labels' => $timeSeriesData['labels'],
                'data' => $timeSeriesData['impressions']
            ];
        });
    }
    
    /**
     * Get time series data for charts
     *
     * @param \Illuminate\Database\Eloquent\Builder $postsQuery
     * @param int $days
     * @return array
     */
    protected function getTimeSeriesData($postsQuery, $days)
    {
        // Get views data for the last N days
        $viewsData = $postsQuery->selectRaw('DATE(published_at) as date, 
            SUM(JSON_EXTRACT(metrics, "$.views")) as impressions,
            SUM(JSON_EXTRACT(metrics, "$.likes")) as likes,
            SUM(JSON_EXTRACT(metrics, "$.comments")) as comments,
            SUM(JSON_EXTRACT(metrics, "$.shares")) as shares')
            ->groupBy('date')
            ->orderBy('date')
            ->get();
        
        // Format data for Chart.js
        $labels = [];
        $impressions = [];
        $engagements = [];
        
        // Fill in missing dates
        $startDate = now()->subDays($days);
        for ($i = 0; $i <= $days; $i++) {
            $date = $startDate->copy()->addDays($i)->format('Y-m-d');
            $labels[] = $date;
            $impressions[] = 0;
            $engagements[] = 0;
        }
        
        // Fill in actual data
        foreach ($viewsData as $item) {
            $index = array_search($item->date, $labels);
            if ($index !== false) {
                $impressions[$index] = (int) $item->impressions;
                $engagements[$index] = (int) ($item->likes + $item->comments + $item->shares);
            }
        }
        
        return [
            'labels' => $labels,
            'impressions' => $impressions,
            'engagements' => $engagements
        ];
    }
}