<?php
// app/Http/Controllers/Api/Admin/ReportController.php

namespace App\Http\Controllers\Api\Admin;

use App\Http\Controllers\Controller;
use App\Traits\ApiResponse;
use App\Models\Order;
use App\Models\Payment;
use App\Models\User;
use App\Models\Menu;
use Illuminate\Http\Request;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;

class ReportController extends Controller
{
    use ApiResponse;

    /**
     * Get sales report with date filter
     */
    public function salesReport(Request $request)
    {
        $request->validate([
            'start_date' => 'nullable|date',
            'end_date' => 'nullable|date|after_or_equal:start_date',
            'group_by' => 'nullable|in:day,week,month,year',
            'order_type' => 'nullable|in:dine_in,takeaway,delivery'
        ]);

        try {
            $startDate = $request->start_date ? Carbon::parse($request->start_date) : Carbon::now()->subMonth();
            $endDate = $request->end_date ? Carbon::parse($request->end_date) : Carbon::now();
            $groupBy = $request->group_by ?? 'day';

            // Base query
            $query = Order::where('status', 'completed')
                ->whereBetween('created_at', [$startDate, $endDate])
                ->when($request->order_type, function ($q, $orderType) {
                    $q->where('order_type', $orderType);
                });

            // Group by period
            $dateFormat = match($groupBy) {
                'day' => '%Y-%m-%d',
                'week' => '%Y-%U',
                'month' => '%Y-%m',
                'year' => '%Y',
                default => '%Y-%m-%d'
            };

            $salesData = $query->select(
                DB::raw("DATE_FORMAT(created_at, '{$dateFormat}') as period"),
                DB::raw('COUNT(*) as total_orders'),
                DB::raw('SUM(total_amount) as total_sales'),
                DB::raw('SUM(discount_amount) as total_discount'),
                DB::raw('SUM(tax_amount) as total_tax'),
                DB::raw('SUM(service_fee) as total_service_fee'),
                DB::raw('SUM(final_amount) as net_sales')
            )
            ->groupBy('period')
            ->orderBy('period')
            ->get();

            // Summary statistics
            $summary = [
                'total_orders' => $salesData->sum('total_orders'),
                'total_sales' => $salesData->sum('total_sales'),
                'total_discount' => $salesData->sum('total_discount'),
                'total_tax' => $salesData->sum('total_tax'),
                'total_service_fee' => $salesData->sum('total_service_fee'),
                'net_sales' => $salesData->sum('net_sales'),
                'average_order_value' => $salesData->sum('net_sales') / max($salesData->sum('total_orders'), 1)
            ];

            // Order type distribution
            $orderTypeDistribution = Order::where('status', 'completed')
                ->whereBetween('created_at', [$startDate, $endDate])
                ->select('order_type', DB::raw('COUNT(*) as count'), DB::raw('SUM(final_amount) as amount'))
                ->groupBy('order_type')
                ->get();

            // Payment method distribution
            $paymentMethodDistribution = Payment::where('status', 'confirmed')
                ->whereBetween('created_at', [$startDate, $endDate])
                ->with('paymentMethod')
                ->select('payment_method_id', DB::raw('COUNT(*) as count'), DB::raw('SUM(amount) as amount'))
                ->groupBy('payment_method_id')
                ->get()
                ->map(function ($payment) {
                    return [
                        'payment_method' => $payment->paymentMethod->name ?? 'Unknown',
                        'count' => $payment->count,
                        'amount' => $payment->amount
                    ];
                });

            return $this->successResponse([
                'period' => [
                    'start_date' => $startDate->toDateString(),
                    'end_date' => $endDate->toDateString(),
                    'group_by' => $groupBy
                ],
                'sales_data' => $salesData,
                'summary' => $summary,
                'order_type_distribution' => $orderTypeDistribution,
                'payment_method_distribution' => $paymentMethodDistribution,
                'top_selling_menus' => $this->getTopSellingMenus($startDate, $endDate)
            ], 'Sales report generated successfully');
        } catch (\Exception $e) {
            return $this->errorResponse('Failed to generate sales report', 500, $e->getMessage());
        }
    }

    /**
     * Get customer report
     */
    public function customerReport(Request $request)
    {
        $request->validate([
            'start_date' => 'nullable|date',
            'end_date' => 'nullable|date|after_or_equal:start_date'
        ]);

        try {
            $startDate = $request->start_date ? Carbon::parse($request->start_date) : Carbon::now()->subMonth();
            $endDate = $request->end_date ? Carbon::parse($request->end_date) : Carbon::now();

            // Customer acquisition
            $newCustomers = User::where('role', 'customer')
                ->whereBetween('created_at', [$startDate, $endDate])
                ->count();

            // Customer order statistics
            $customerStats = Order::where('status', 'completed')
                ->whereBetween('created_at', [$startDate, $endDate])
                ->select('customer_id')
                ->with('customer')
                ->selectRaw('customer_id, COUNT(*) as order_count, SUM(final_amount) as total_spent, MAX(created_at) as last_order')
                ->groupBy('customer_id')
                ->orderByDesc('total_spent')
                ->limit(20)
                ->get()
                ->map(function ($order) {
                    return [
                        'customer_id' => $order->customer_id,
                        'customer_name' => $order->customer->name ?? 'Unknown',
                        'order_count' => $order->order_count,
                        'total_spent' => $order->total_spent,
                        'average_order_value' => $order->total_spent / $order->order_count,
                        'last_order' => $order->last_order
                    ];
                });

            // Customer segmentation
            $segmentation = [
                'new_customers' => $newCustomers,
                'returning_customers' => User::where('role', 'customer')
                    ->whereHas('orders', function ($q) use ($startDate, $endDate) {
                        $q->where('status', 'completed')
                          ->whereBetween('created_at', [$startDate, $endDate]);
                    })
                    ->where('created_at', '<', $startDate)
                    ->count(),
                'top_customers' => $customerStats->where('order_count', '>=', 3)->count()
            ];

            return $this->successResponse([
                'period' => [
                    'start_date' => $startDate->toDateString(),
                    'end_date' => $endDate->toDateString()
                ],
                'customer_acquisition' => [
                    'new_customers' => $newCustomers,
                    'growth_rate' => $this->calculateGrowthRate('customers', $startDate, $endDate)
                ],
                'customer_segmentation' => $segmentation,
                'top_customers' => $customerStats,
                'customer_metrics' => [
                    'average_order_frequency' => $customerStats->avg('order_count') ?? 0,
                    'average_customer_value' => $customerStats->avg('total_spent') ?? 0,
                    'repeat_purchase_rate' => $segmentation['returning_customers'] / max($segmentation['new_customers'] + $segmentation['returning_customers'], 1) * 100
                ]
            ], 'Customer report generated successfully');
        } catch (\Exception $e) {
            return $this->errorResponse('Failed to generate customer report', 500, $e->getMessage());
        }
    }

    /**
     * Get inventory report
     */
    public function inventoryReport(Request $request)
    {
        try {
            // Low stock items
            $lowStock = Menu::where('stock', '<', 10)
                ->where('stock', '>', 0)
                ->where('is_available', true)
                ->orderBy('stock')
                ->get()
                ->map(function ($menu) {
                    return [
                        'id' => $menu->id,
                        'name' => $menu->name,
                        'stock' => $menu->stock,
                        'price' => $menu->price,
                        'category' => $menu->category->name ?? 'Unknown',
                        'status' => $menu->stock == 0 ? 'Out of Stock' : 'Low Stock'
                    ];
                });

            // Out of stock items
            $outOfStock = Menu::where('stock', 0)
                ->where('is_available', true)
                ->get()
                ->map(function ($menu) {
                    return [
                        'id' => $menu->id,
                        'name' => $menu->name,
                        'price' => $menu->price,
                        'category' => $menu->category->name ?? 'Unknown',
                        'last_ordered' => $menu->orderItems()->latest()->first()->created_at ?? null
                    ];
                });

            // Best selling items
            $bestSellers = DB::table('order_items')
                ->join('menus', 'order_items.menu_id', '=', 'menus.id')
                ->join('orders', 'order_items.order_id', '=', 'orders.id')
                ->where('orders.status', 'completed')
                ->select(
                    'menus.id',
                    'menus.name',
                    'menus.category_id',
                    DB::raw('SUM(order_items.quantity) as total_sold'),
                    DB::raw('SUM(order_items.subtotal) as total_revenue')
                )
                ->groupBy('menus.id', 'menus.name', 'menus.category_id')
                ->orderByDesc('total_sold')
                ->limit(10)
                ->get();

            // Inventory valuation
            $inventoryValuation = Menu::select(
                DB::raw('SUM(stock * price) as total_value'),
                DB::raw('COUNT(*) as total_items'),
                DB::raw('SUM(CASE WHEN stock = 0 THEN 1 ELSE 0 END) as out_of_stock_count'),
                DB::raw('SUM(CASE WHEN stock < 10 AND stock > 0 THEN 1 ELSE 0 END) as low_stock_count')
            )->first();

            return $this->successResponse([
                'inventory_summary' => [
                    'total_items' => $inventoryValuation->total_items ?? 0,
                    'total_value' => $inventoryValuation->total_value ?? 0,
                    'out_of_stock' => $inventoryValuation->out_of_stock_count ?? 0,
                    'low_stock' => $inventoryValuation->low_stock_count ?? 0
                ],
                'low_stock_items' => $lowStock,
                'out_of_stock_items' => $outOfStock,
                'best_selling_items' => $bestSellers,
                'stock_turnover' => $this->calculateStockTurnover()
            ], 'Inventory report generated successfully');
        } catch (\Exception $e) {
            return $this->errorResponse('Failed to generate inventory report', 500, $e->getMessage());
        }
    }

    /**
     * Get comprehensive dashboard report
     */
    public function dashboardReport()
    {
        try {
            $today = Carbon::today();
            $yesterday = Carbon::yesterday();
            $thisMonth = Carbon::now()->startOfMonth();
            $lastMonth = Carbon::now()->subMonth()->startOfMonth();

            // Today's statistics
            $todayStats = Order::whereDate('created_at', $today)
                ->select(
                    DB::raw('COUNT(*) as total_orders'),
                    DB::raw('SUM(final_amount) as total_sales'),
                    DB::raw('SUM(CASE WHEN status = "completed" THEN final_amount ELSE 0 END) as completed_sales'),
                    DB::raw('SUM(CASE WHEN status = "pending" OR status = "confirmed" THEN 1 ELSE 0 END) as active_orders')
                )
                ->first();

            // Monthly comparison
            $currentMonthStats = Order::whereBetween('created_at', [$thisMonth, Carbon::now()])
                ->where('status', 'completed')
                ->select(
                    DB::raw('COUNT(*) as orders'),
                    DB::raw('SUM(final_amount) as revenue')
                )
                ->first();

            $lastMonthStats = Order::whereBetween('created_at', [
                $lastMonth,
                Carbon::now()->subMonth()->endOfMonth()
            ])
            ->where('status', 'completed')
            ->select(
                DB::raw('COUNT(*) as orders'),
                DB::raw('SUM(final_amount) as revenue')
            )
            ->first();

            // Payment status
            $paymentStats = Payment::select('status', DB::raw('COUNT(*) as count'))
                ->groupBy('status')
                ->get()
                ->pluck('count', 'status');

            // Recent activities
            $recentOrders = Order::with('customer')
                ->orderBy('created_at', 'desc')
                ->limit(5)
                ->get()
                ->map(function ($order) {
                    return [
                        'order_number' => $order->order_number,
                        'customer_name' => $order->customer->name ?? 'Unknown',
                        'total_amount' => $order->final_amount,
                        'status' => $order->status,
                        'order_type' => $order->order_type,
                        'created_at' => $order->created_at
                    ];
                });

            return $this->successResponse([
                'today_stats' => [
                    'total_orders' => $todayStats->total_orders ?? 0,
                    'total_sales' => $todayStats->total_sales ?? 0,
                    'completed_sales' => $todayStats->completed_sales ?? 0,
                    'active_orders' => $todayStats->active_orders ?? 0
                ],
                'monthly_comparison' => [
                    'current_month' => [
                        'orders' => $currentMonthStats->orders ?? 0,
                        'revenue' => $currentMonthStats->revenue ?? 0
                    ],
                    'last_month' => [
                        'orders' => $lastMonthStats->orders ?? 0,
                        'revenue' => $lastMonthStats->revenue ?? 0
                    ],
                    'growth' => [
                        'orders_growth' => $this->calculateGrowth($currentMonthStats->orders ?? 0, $lastMonthStats->orders ?? 0),
                        'revenue_growth' => $this->calculateGrowth($currentMonthStats->revenue ?? 0, $lastMonthStats->revenue ?? 0)
                    ]
                ],
                'payment_status' => $paymentStats,
                'recent_orders' => $recentOrders,
                'quick_stats' => [
                    'total_customers' => User::where('role', 'customer')->count(),
                    'total_menus' => Menu::count(),
                    'active_promos' => DB::table('promos')
                        ->where('is_active', true)
                        ->where('start_date', '<=', now())
                        ->where('end_date', '>=', now())
                        ->count(),
                    'pending_payments' => Payment::where('status', 'waiting_confirmation')->count()
                ]
            ], 'Dashboard report generated successfully');
        } catch (\Exception $e) {
            return $this->errorResponse('Failed to generate dashboard report', 500, $e->getMessage());
        }
    }

    // ========== HELPER METHODS ==========

    private function getTopSellingMenus($startDate, $endDate, $limit = 10)
    {
        return DB::table('order_items')
            ->join('menus', 'order_items.menu_id', '=', 'menus.id')
            ->join('orders', 'order_items.order_id', '=', 'orders.id')
            ->where('orders.status', 'completed')
            ->whereBetween('orders.created_at', [$startDate, $endDate])
            ->select(
                'menus.id',
                'menus.name',
                'menus.category_id',
                DB::raw('SUM(order_items.quantity) as total_quantity'),
                DB::raw('SUM(order_items.subtotal) as total_revenue')
            )
            ->groupBy('menus.id', 'menus.name', 'menus.category_id')
            ->orderByDesc('total_quantity')
            ->limit($limit)
            ->get();
    }

    private function calculateGrowthRate($metric, $startDate, $endDate)
    {
        $previousPeriodStart = $startDate->copy()->subDays($startDate->diffInDays($endDate));
        $previousPeriodEnd = $startDate->copy()->subDay();

        $currentCount = match($metric) {
            'customers' => User::where('role', 'customer')
                ->whereBetween('created_at', [$startDate, $endDate])
                ->count(),
            'orders' => Order::whereBetween('created_at', [$startDate, $endDate])
                ->count(),
            default => 0
        };

        $previousCount = match($metric) {
            'customers' => User::where('role', 'customer')
                ->whereBetween('created_at', [$previousPeriodStart, $previousPeriodEnd])
                ->count(),
            'orders' => Order::whereBetween('created_at', [$previousPeriodStart, $previousPeriodEnd])
                ->count(),
            default => 0
        };

        if ($previousCount == 0) {
            return $currentCount > 0 ? 100 : 0;
        }

        return (($currentCount - $previousCount) / $previousCount) * 100;
    }

    private function calculateStockTurnover()
    {
        // Simplified stock turnover calculation
        $averageInventory = Menu::avg('stock') ?? 1;
        $costOfGoodsSold = DB::table('order_items')
            ->join('orders', 'order_items.order_id', '=', 'orders.id')
            ->where('orders.status', 'completed')
            ->whereMonth('orders.created_at', Carbon::now()->month)
            ->sum('order_items.subtotal');

        return $costOfGoodsSold / max($averageInventory, 1);
    }

    private function calculateGrowth($current, $previous)
    {
        if ($previous == 0) {
            return $current > 0 ? 100 : 0;
        }
        return (($current - $previous) / $previous) * 100;
    }
}