<?php

namespace App\Http\Controllers\API\Admin;

use App\Http\Controllers\Controller;
use App\Models\User;
use App\Models\Restaurant;
use App\Models\Order;
use App\Models\DeliveryBoy;
use App\Models\Product;
use App\Models\Payment;
use App\Models\Commission;
use App\Models\Payout;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\DB;
use Carbon\Carbon;

class DashboardAnalyticsController extends Controller
{
    /**
     * Get dashboard overview statistics.
     */
    public function overview(Request $request): JsonResponse
    {
        $startDate = $request->start_date ?? Carbon::now()->subDays(30);
        $endDate = $request->end_date ?? Carbon::now();

        $overview = [
            'total_users' => User::count(),
            'total_restaurants' => Restaurant::count(),
            'total_delivery_boys' => DeliveryBoy::count(),
            'total_orders' => Order::count(),
            'total_products' => Product::count(),
            'total_revenue' => Order::where('payment_status', 'paid')->sum('total_amount'),
            'active_restaurants' => Restaurant::where('is_active', true)->count(),
            'active_delivery_boys' => DeliveryBoy::where('is_active', true)->count(),
            'today_orders' => Order::whereDate('created_at', Carbon::today())->count(),
            'today_revenue' => Order::whereDate('created_at', Carbon::today())
                ->where('payment_status', 'paid')->sum('total_amount'),
        ];

        // Growth percentages compared to previous period
        $previousStartDate = Carbon::parse($startDate)->subDays(
            Carbon::parse($startDate)->diffInDays(Carbon::parse($endDate))
        );

        $overview['user_growth'] = $this->calculateGrowth(
            User::whereBetween('created_at', [$startDate, $endDate])->count(),
            User::whereBetween('created_at', [$previousStartDate, $startDate])->count()
        );

        $overview['order_growth'] = $this->calculateGrowth(
            Order::whereBetween('created_at', [$startDate, $endDate])->count(),
            Order::whereBetween('created_at', [$previousStartDate, $startDate])->count()
        );

        $overview['revenue_growth'] = $this->calculateGrowth(
            Order::whereBetween('created_at', [$startDate, $endDate])
                ->where('payment_status', 'paid')->sum('total_amount'),
            Order::whereBetween('created_at', [$previousStartDate, $startDate])
                ->where('payment_status', 'paid')->sum('total_amount')
        );

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

    /**
     * Get order analytics.
     */
    public function orderAnalytics(Request $request): JsonResponse
    {
        $startDate = $request->start_date ?? Carbon::now()->subDays(30);
        $endDate = $request->end_date ?? Carbon::now();

        $analytics = [
            'total_orders' => Order::whereBetween('created_at', [$startDate, $endDate])->count(),
            'total_revenue' => Order::whereBetween('created_at', [$startDate, $endDate])
                ->where('payment_status', 'paid')->sum('total_amount'),
            'average_order_value' => Order::whereBetween('created_at', [$startDate, $endDate])
                ->where('payment_status', 'paid')->avg('total_amount'),
            'completed_orders' => Order::whereBetween('created_at', [$startDate, $endDate])
                ->where('status', 'delivered')->count(),
            'cancelled_orders' => Order::whereBetween('created_at', [$startDate, $endDate])
                ->where('status', 'cancelled')->count(),
        ];

        // Order status breakdown
        $statusBreakdown = Order::whereBetween('created_at', [$startDate, $endDate])
            ->selectRaw('status, COUNT(*) as count, SUM(total_amount) as revenue')
            ->groupBy('status')
            ->get();

        $analytics['status_breakdown'] = $statusBreakdown;

        // Daily order trends
        $dailyOrders = Order::whereBetween('created_at', [$startDate, $endDate])
            ->selectRaw('DATE(created_at) as date, COUNT(*) as orders, SUM(total_amount) as revenue')
            ->groupBy('date')
            ->orderBy('date')
            ->get();

        $analytics['daily_trends'] = $dailyOrders;

        // Hourly order distribution
        $hourlyDistribution = Order::whereBetween('created_at', [$startDate, $endDate])
            ->selectRaw('HOUR(created_at) as hour, COUNT(*) as count')
            ->groupBy('hour')
            ->orderBy('hour')
            ->get();

        $analytics['hourly_distribution'] = $hourlyDistribution;

        // Top performing days
        $topDays = Order::whereBetween('created_at', [$startDate, $endDate])
            ->selectRaw('DAYNAME(created_at) as day, COUNT(*) as orders, SUM(total_amount) as revenue')
            ->groupBy('day')
            ->orderByDesc('orders')
            ->get();

        $analytics['top_days'] = $topDays;

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

    /**
     * Get restaurant analytics.
     */
    public function restaurantAnalytics(Request $request): JsonResponse
    {
        $startDate = $request->start_date ?? Carbon::now()->subDays(30);
        $endDate = $request->end_date ?? Carbon::now();

        $analytics = [
            'total_restaurants' => Restaurant::count(),
            'active_restaurants' => Restaurant::where('is_active', true)->count(),
            'inactive_restaurants' => Restaurant::where('is_active', false)->count(),
            'verified_restaurants' => Restaurant::where('is_verified', true)->count(),
            'new_restaurants_this_month' => Restaurant::whereMonth('created_at', Carbon::now()->month)->count(),
        ];

        // Top restaurants by orders
        $topRestaurantsByOrders = Order::whereBetween('created_at', [$startDate, $endDate])
            ->where('status', 'delivered')
            ->selectRaw('restaurant_id, COUNT(*) as order_count, SUM(total_amount) as revenue')
            ->groupBy('restaurant_id')
            ->orderByDesc('order_count')
            ->limit(10)
            ->with(['restaurant:id,name'])
            ->get();

        $analytics['top_restaurants_by_orders'] = $topRestaurantsByOrders;

        // Top restaurants by revenue
        $topRestaurantsByRevenue = Order::whereBetween('created_at', [$startDate, $endDate])
            ->where('status', 'delivered')
            ->selectRaw('restaurant_id, SUM(total_amount) as revenue, COUNT(*) as order_count')
            ->groupBy('restaurant_id')
            ->orderByDesc('revenue')
            ->limit(10)
            ->with(['restaurant:id,name'])
            ->get();

        $analytics['top_restaurants_by_revenue'] = $topRestaurantsByRevenue;

        // Restaurant status breakdown
        $statusBreakdown = Restaurant::selectRaw('is_active, COUNT(*) as count')
            ->groupBy('is_active')
            ->get();

        $analytics['status_breakdown'] = $statusBreakdown;

        // Daily restaurant registrations
        $dailyRegistrations = Restaurant::whereBetween('created_at', [$startDate, $endDate])
            ->selectRaw('DATE(created_at) as date, COUNT(*) as count')
            ->groupBy('date')
            ->orderBy('date')
            ->get();

        $analytics['daily_registrations'] = $dailyRegistrations;

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

    /**
     * Get delivery boy analytics.
     */
    public function deliveryBoyAnalytics(Request $request): JsonResponse
    {
        $startDate = $request->start_date ?? Carbon::now()->subDays(30);
        $endDate = $request->end_date ?? Carbon::now();

        $analytics = [
            'total_delivery_boys' => DeliveryBoy::count(),
            'active_delivery_boys' => DeliveryBoy::where('is_active', true)->count(),
            'inactive_delivery_boys' => DeliveryBoy::where('is_active', false)->count(),
            'verified_delivery_boys' => DeliveryBoy::where('is_verified', true)->count(),
            'new_delivery_boys_this_month' => DeliveryBoy::whereMonth('created_at', Carbon::now()->month)->count(),
        ];

        // Top delivery boys by deliveries
        $topDeliveryBoys = Order::whereBetween('created_at', [$startDate, $endDate])
            ->where('status', 'delivered')
            ->whereNotNull('delivery_boy_id')
            ->selectRaw('delivery_boy_id, COUNT(*) as delivery_count, SUM(delivery_fee) as earnings')
            ->groupBy('delivery_boy_id')
            ->orderByDesc('delivery_count')
            ->limit(10)
            ->with(['deliveryBoy.user:id,name'])
            ->get();

        $analytics['top_delivery_boys'] = $topDeliveryBoys;

        // Delivery boy status breakdown
        $statusBreakdown = DeliveryBoy::selectRaw('is_active, COUNT(*) as count')
            ->groupBy('is_active')
            ->get();

        $analytics['status_breakdown'] = $statusBreakdown;

        // Average delivery time
        $avgDeliveryTime = Order::whereBetween('created_at', [$startDate, $endDate])
            ->where('status', 'delivered')
            ->whereNotNull('delivered_at')
            ->selectRaw('AVG(TIMESTAMPDIFF(MINUTE, created_at, delivered_at)) as avg_time')
            ->first();

        $analytics['average_delivery_time'] = round($avgDeliveryTime->avg_time ?? 0, 2);

        // Daily delivery boy registrations
        $dailyRegistrations = DeliveryBoy::whereBetween('created_at', [$startDate, $endDate])
            ->selectRaw('DATE(created_at) as date, COUNT(*) as count')
            ->groupBy('date')
            ->orderBy('date')
            ->get();

        $analytics['daily_registrations'] = $dailyRegistrations;

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

    /**
     * Get payment analytics.
     */
    public function paymentAnalytics(Request $request): JsonResponse
    {
        $startDate = $request->start_date ?? Carbon::now()->subDays(30);
        $endDate = $request->end_date ?? Carbon::now();

        $analytics = [
            'total_payments' => Payment::whereBetween('created_at', [$startDate, $endDate])->count(),
            'total_amount' => Payment::whereBetween('created_at', [$startAt, $endDate])
                ->where('status', 'completed')->sum('amount'),
            'successful_payments' => Payment::whereBetween('created_at', [$startDate, $endDate])
                ->where('status', 'completed')->count(),
            'failed_payments' => Payment::whereBetween('created_at', [$startDate, $endDate])
                ->where('status', 'failed')->count(),
            'pending_payments' => Payment::whereBetween('created_at', [$startDate, $endDate])
                ->where('status', 'pending')->count(),
        ];

        // Payment method breakdown
        $methodBreakdown = Payment::whereBetween('created_at', [$startDate, $endDate])
            ->where('status', 'completed')
            ->selectRaw('payment_method, COUNT(*) as count, SUM(amount) as total')
            ->groupBy('payment_method')
            ->get();

        $analytics['payment_method_breakdown'] = $methodBreakdown;

        // Daily payment trends
        $dailyTrends = Payment::whereBetween('created_at', [$startDate, $endDate])
            ->where('status', 'completed')
            ->selectRaw('DATE(created_at) as date, COUNT(*) as count, SUM(amount) as total')
            ->groupBy('date')
            ->orderBy('date')
            ->get();

        $analytics['daily_trends'] = $dailyTrends;

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

    /**
     * Get commission analytics.
     */
    public function commissionAnalytics(Request $request): JsonResponse
    {
        $startDate = $request->start_date ?? Carbon::now()->subDays(30);
        $endDate = $request->end_date ?? Carbon::now();

        $analytics = [
            'total_commissions' => Commission::whereBetween('created_at', [$startDate, $endDate])->sum('amount'),
            'restaurant_commissions' => Commission::whereBetween('created_at', [$startDate, $endDate])
                ->where('commissionable_type', 'App\Models\Restaurant')->sum('amount'),
            'delivery_boy_commissions' => Commission::whereBetween('created_at', [$startDate, $endDate])
                ->where('commissionable_type', 'App\Models\DeliveryBoy')->sum('amount'),
        ];

        // Commission breakdown by type
        $typeBreakdown = Commission::whereBetween('created_at', [$startDate, $endDate])
            ->selectRaw('type, SUM(amount) as total')
            ->groupBy('type')
            ->get();

        $analytics['commission_type_breakdown'] = $typeBreakdown;

        // Daily commission trends
        $dailyTrends = Commission::whereBetween('created_at', [$startDate, $endDate])
            ->selectRaw('DATE(created_at) as date, SUM(amount) as total')
            ->groupBy('date')
            ->orderBy('date')
            ->get();

        $analytics['daily_trends'] = $dailyTrends;

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

    /**
     * Get user analytics.
     */
    public function userAnalytics(Request $request): JsonResponse
    {
        $startDate = $request->start_date ?? Carbon::now()->subDays(30);
        $endDate = $request->end_date ?? Carbon::now();

        $analytics = [
            'total_users' => User::count(),
            'new_users_this_month' => User::whereMonth('created_at', Carbon::now()->month)->count(),
            'active_users' => User::where('is_active', true)->count(),
            'verified_users' => User::whereNotNull('email_verified_at')->count(),
        ];

        // User registration trends
        $registrationTrends = User::whereBetween('created_at', [$startDate, $endDate])
            ->selectRaw('DATE(created_at) as date, COUNT(*) as count')
            ->groupBy('date')
            ->orderBy('date')
            ->get();

        $analytics['registration_trends'] = $registrationTrends;

        // User role breakdown
        $roleBreakdown = DB::table('model_has_roles')
            ->join('roles', 'model_has_roles.role_id', '=', 'roles.id')
            ->selectRaw('roles.name, COUNT(*) as count')
            ->groupBy('roles.name')
            ->get();

        $analytics['role_breakdown'] = $roleBreakdown;

        // Top users by orders
        $topUsersByOrders = User::withCount(['orders as order_count' => function($q) use ($startDate, $endDate) {
                $q->whereBetween('created_at', [$startDate, $endDate])
                  ->where('status', 'delivered');
            }])
            ->orderByDesc('order_count')
            ->limit(10)
            ->get();

        $analytics['top_users_by_orders'] = $topUsersByOrders;

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

    /**
     * Get real-time statistics.
     */
    public function realTimeStats(Request $request): JsonResponse
    {
        $stats = [
            'online_users' => User::where('last_seen', '>', Carbon::now()->subMinutes(5))->count(),
            'active_restaurants' => Restaurant::where('is_active', true)->count(),
            'available_delivery_boys' => DeliveryBoy::where('status', 'available')->count(),
            'pending_orders' => Order::where('status', 'pending')->count(),
            'processing_orders' => Order::whereIn('status', ['confirmed', 'preparing', 'ready_for_pickup', 'out_for_delivery'])->count(),
            'today_revenue' => Order::whereDate('created_at', Carbon::today())
                ->where('payment_status', 'paid')->sum('total_amount'),
            'today_orders' => Order::whereDate('created_at', Carbon::today())->count(),
        ];

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

    /**
     * Get system health metrics.
     */
    public function systemHealth(Request $request): JsonResponse
    {
        $health = [
            'database_connection' => $this->checkDatabaseConnection(),
            'queue_status' => $this->checkQueueStatus(),
            'storage_space' => $this->getStorageSpace(),
            'memory_usage' => $this->getMemoryUsage(),
            'cpu_usage' => $this->getCpuUsage(),
            'disk_usage' => $this->getDiskUsage(),
        ];

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

    /**
     * Get recent activities.
     */
    public function recentActivities(Request $request): JsonResponse
    {
        $activities = [];

        // Recent orders
        $recentOrders = Order::with(['user', 'restaurant'])
            ->orderBy('created_at', 'desc')
            ->limit(10)
            ->get()
            ->map(function($order) {
                return [
                    'type' => 'order',
                    'title' => 'New Order',
                    'description' => "Order #{$order->order_number} placed by {$order->user->name}",
                    'timestamp' => $order->created_at,
                    'data' => $order
                ];
            });

        // Recent users
        $recentUsers = User::orderBy('created_at', 'desc')
            ->limit(10)
            ->get()
            ->map(function($user) {
                return [
                    'type' => 'user',
                    'title' => 'New User',
                    'description' => "{$user->name} registered",
                    'timestamp' => $user->created_at,
                    'data' => $user
                ];
            });

        // Recent restaurants
        $recentRestaurants = Restaurant::orderBy('created_at', 'desc')
            ->limit(10)
            ->get()
            ->map(function($restaurant) {
                return [
                    'type' => 'restaurant',
                    'title' => 'New Restaurant',
                    'description' => "{$restaurant->name} registered",
                    'timestamp' => $restaurant->created_at,
                    'data' => $restaurant
                ];
            });

        $activities = collect($recentOrders)
            ->merge($recentUsers)
            ->merge($recentRestaurants)
            ->sortByDesc('timestamp')
            ->take(20)
            ->values();

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

    /**
     * Calculate growth percentage.
     */
    private function calculateGrowth($current, $previous): float
    {
        if ($previous == 0) {
            return $current > 0 ? 100 : 0;
        }

        return round((($current - $previous) / $previous) * 100, 2);
    }

    /**
     * Check database connection.
     */
    private function checkDatabaseConnection(): array
    {
        try {
            DB::connection()->getPdo();
            return ['status' => 'healthy', 'message' => 'Database connection is active'];
        } catch (\Exception $e) {
            return ['status' => 'unhealthy', 'message' => 'Database connection failed: ' . $e->getMessage()];
        }
    }

    /**
     * Check queue status.
     */
    private function checkQueueStatus(): array
    {
        // This would typically check Redis or database queue connection
        // For now, return a basic status
        return ['status' => 'healthy', 'message' => 'Queue system is operational'];
    }

    /**
     * Get storage space information.
     */
    private function getStorageSpace(): array
    {
        $total = disk_total_space(storage_path());
        $free = disk_free_space(storage_path());
        $used = $total - $free;

        return [
            'total' => $this->formatBytes($total),
            'free' => $this->formatBytes($free),
            'used' => $this->formatBytes($used),
            'percentage' => round(($used / $total) * 100, 2)
        ];
    }

    /**
     * Get memory usage.
     */
    private function getMemoryUsage(): array
    {
        $total = memory_get_usage(true);
        $peak = memory_get_peak_usage(true);

        return [
            'current' => $this->formatBytes($total),
            'peak' => $this->formatBytes($peak),
            'percentage' => round(($total / (1024 * 1024 * 256)) * 100, 2) // Assuming 256MB limit
        ];
    }

    /**
     * Get CPU usage.
     */
    private function getCpuUsage(): array
    {
        // This would typically use system commands to get CPU usage
        // For now, return a placeholder
        return [
            'percentage' => rand(10, 50), // Simulated data
            'status' => 'healthy'
        ];
    }

    /**
     * Get disk usage.
     */
    private function getDiskUsage(): array
    {
        $total = disk_total_space('/');
        $free = disk_free_space('/');
        $used = $total - $free;

        return [
            'total' => $this->formatBytes($total),
            'free' => $this->formatBytes($free),
            'used' => $this->formatBytes($used),
            'percentage' => round(($used / $total) * 100, 2)
        ];
    }

    /**
     * Format bytes to human readable format.
     */
    private function formatBytes($bytes, $precision = 2): string
    {
        $units = ['B', 'KB', 'MB', 'GB', 'TB'];

        $bytes = max($bytes, 0);
        $pow = floor(($bytes ? log($bytes) : 0) / log(1024));
        $pow = min($pow, count($units) - 1);

        $bytes /= pow(1024, $pow);

        return round($bytes, $precision) . ' ' . $units[$pow];
    }
}