<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Models\Order;
use App\Models\Product;
use App\Models\User;
use App\Models\OrderItem;
use App\Services\ProfitService;
use Carbon\Carbon;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\View\View;
use App\Services\OtpService;
use App\Models\WhatsappStoreCredits;

class DashboardController extends Controller
{
    protected $otpService;

    public function __construct(OtpService $otpService)
    {
        $this->otpService = $otpService;
    }

    public function index(): View
    {
        // Today's statistics
        $todaySales = Order::paid()
            ->whereDate('created_at', today())
            ->sum('total_payable');
        
        $todayOrders = Order::whereDate('created_at', today())->count();
        
        // This month's statistics
        $monthSales = Order::paid()
            ->whereMonth('created_at', now()->month)
            ->whereYear('created_at', now()->year)
            ->sum('total_payable');
        
        $monthOrders = Order::whereMonth('created_at', now()->month)
            ->whereYear('created_at', now()->year)
            ->count();
        
        // Last month for comparison
        $lastMonthSales = Order::paid()
            ->whereMonth('created_at', now()->subMonth()->month)
            ->whereYear('created_at', now()->subMonth()->year)
            ->sum('total_payable');
        
        $salesGrowth = $lastMonthSales > 0 
            ? (($monthSales - $lastMonthSales) / $lastMonthSales) * 100 
            : 0;

        // Total statistics
        $totalRevenue = Order::paid()->sum('total_payable');
        $totalOrders = Order::count();
        $totalCustomers = User::whereDoesntHave('roles')->count();
        $totalProducts = Product::count();
        $activeProducts = Product::active()->count();
        $lowStockProducts = Product::where('current_stock', '<=', 10)->count();

        // Orders by status
        $ordersByStatus = Order::select('status', DB::raw('count(*) as count'))
            ->groupBy('status')
            ->pluck('count', 'status');

        // Payment status statistics
        $paymentStats = Order::select('payment_status', DB::raw('count(*) as count'))
            ->groupBy('payment_status')
            ->pluck('count', 'payment_status');

        // Revenue last 7 days
        $revenueData = Order::paid()
            ->where('created_at', '>=', now()->subDays(7))
            ->select(DB::raw('DATE(created_at) as date'), DB::raw('SUM(total_payable) as revenue'))
            ->groupBy('date')
            ->orderBy('date')
            ->get();

        // Revenue last 30 days for monthly chart
        $monthlyRevenueData = Order::paid()
            ->where('created_at', '>=', now()->subDays(30))
            ->select(DB::raw('DATE(created_at) as date'), DB::raw('SUM(total_payable) as revenue'))
            ->groupBy('date')
            ->orderBy('date')
            ->get();

        // Average order value
        $avgOrderValue = Order::paid()->avg('total_payable') ?? 0;

        // Top selling products (last 30 days)
        $topProducts = OrderItem::select('product_id', DB::raw('SUM(qty) as total_sold'), DB::raw('SUM(line_total) as total_revenue'))
            ->whereHas('order', function($query) {
                $query->where('created_at', '>=', now()->subDays(30))
                      ->where('payment_status', 'paid');
            })
            ->with('product:id,name,image_path')
            ->groupBy('product_id')
            ->orderByDesc('total_sold')
            ->take(5)
            ->get();

        // Pending orders count
        $pendingOrders = Order::where('status', 'placed')->count();

        // Low stock products
        $lowStockItems = Product::where('current_stock', '<=', 10)
            ->where('is_active', true)
            ->select('id', 'name', 'current_stock', 'image_path')
            ->orderBy('current_stock')
            ->take(5)
            ->get();

        // Profit Analytics
        $profitService = app(ProfitService::class);
        
        // Today's Profit
        $todayProfitData = $profitService->getProfitReport([
            'start_date' => today()->format('Y-m-d'),
            'end_date' => today()->format('Y-m-d'),
            'payment_status' => 'paid'
        ]);
        
        // This Month's Profit
        $monthProfitData = $profitService->getProfitReport([
            'start_date' => now()->startOfMonth()->format('Y-m-d'),
            'end_date' => now()->format('Y-m-d'),
            'payment_status' => 'paid'
        ]);
        
        // Total Profit
        $totalProfitData = $profitService->getProfitReport([
            'payment_status' => 'paid'
        ]);
        
        // Top Profitable Products
        $topProfitableProducts = $profitService->getTopProfitableProducts(5, [
            'start_date' => now()->subDays(30)->format('Y-m-d'),
            'end_date' => now()->format('Y-m-d'),
            'payment_status' => 'paid'
        ]);
        
        // Purchase Price Coverage (sellable products only: singles + variant children)
        $activeSingleProductsCount = Product::active()
            ->whereNull('parent_id')
            ->where('product_type', 'single')
            ->count();

        $activeVariantChildrenCount = Product::active()
            ->whereNotNull('parent_id')
            ->count();

        $totalProductsCount = $activeSingleProductsCount + $activeVariantChildrenCount;

        $singleProductsWithPrice = Product::active()
            ->whereNull('parent_id')
            ->where('product_type', 'single')
            ->withPurchasePrice()
            ->count();

        $variantProductsWithPrice = Product::active()
            ->whereNotNull('parent_id')
            ->withPurchasePrice()
            ->count();

        $productsWithPurchasePrice = $singleProductsWithPrice + $variantProductsWithPrice;
        $purchasePriceCoverage = $totalProductsCount > 0 ?
            round(($productsWithPurchasePrice / $totalProductsCount) * 100, 1) : 0;
        $productsMissingPurchasePrice = $totalProductsCount - $productsWithPurchasePrice;

        $whatsApp = WhatsappStoreCredits::where('id', 1)->first(); 

        $response = $this->otpService->smsWalletBalance();
        $SMScount = !empty($response['sms_count']) ? (int) $response['sms_count'] : 0;
        $SmsWallet = !empty($response['wallet']) ? number_format($response['wallet'], 2) : 0;
        $smsUrl = !empty($response['smsUrl']) ? $response['smsUrl'] : 'https://sms.kiyosolutions.com/';

        // Profit Trend (Last 30 days for chart)
        $profitTrendData = [];
        try {
            $profitTrendData = OrderItem::whereHas('order', function($query) {
                    $query->where('created_at', '>=', now()->subDays(30))
                          ->where('payment_status', 'paid');
                })
                ->whereNotNull('purchase_price')
                ->select(
                    DB::raw('DATE(orders.created_at) as date'),
                    DB::raw('SUM(COALESCE((order_items.price * order_items.qty) - COALESCE(order_items.allocated_discount, 0), 0)) as revenue'),
                    DB::raw('SUM(COALESCE((order_items.purchase_price * order_items.qty) + COALESCE(order_items.allocated_extra_costs, 0), 0)) as cogs'),
                    DB::raw('SUM(COALESCE(((order_items.price * order_items.qty) - COALESCE(order_items.allocated_discount, 0)) - ((order_items.purchase_price * order_items.qty) + COALESCE(order_items.allocated_extra_costs, 0)), 0)) as profit')
                )
                ->join('orders', 'order_items.order_id', '=', 'orders.id')
                ->groupBy('date')
                ->orderBy('date')
                ->get()
                ->map(function($item) {
                    return [
                        'date' => $item->date,
                        'revenue' => (float) $item->revenue,
                        'cogs' => (float) $item->cogs,
                        'profit' => (float) $item->profit
                    ];
                });
        } catch (\Exception $e) {
            \Log::error('Error generating profit trend data: ' . $e->getMessage());
            $profitTrendData = [];
        }

        return view('admin.dashboard', compact(
            'todaySales',
            'todayOrders',
            'monthSales',
            'monthOrders',
            'salesGrowth',
            'totalRevenue',
            'totalOrders',
            'totalCustomers',
            'totalProducts',
            'activeProducts',
            'lowStockProducts',
            'ordersByStatus',
            'paymentStats',
            'revenueData',
            'monthlyRevenueData',
            'avgOrderValue',
            'topProducts',
            'pendingOrders',
            'lowStockItems',
            'todayProfitData',
            'monthProfitData',
            'totalProfitData',
            'topProfitableProducts',
            'purchasePriceCoverage',
            'productsMissingPurchasePrice',
            'profitTrendData',
            'whatsApp',
            'SMScount',
            'SmsWallet',
            'smsUrl'
        ));
    }

    /**
     * Salesman performance chart data (line chart: one line per staff, POS only).
     * Query params: period (day|week|month|year|custom), start_date, end_date (for custom).
     */
    public function salesmanChartData(Request $request): JsonResponse
    {
        $period = $request->input('period', 'week');
        $startDate = $request->input('start_date', now()->subDays(6)->format('Y-m-d'));
        $endDate = $request->input('end_date', now()->format('Y-m-d'));

        switch ($period) {
            case 'day':
                $startDateTime = now()->startOfDay();
                $endDateTime = now()->endOfDay();
                break;
            case 'week':
                $startDateTime = now()->copy()->startOfWeek();
                $endDateTime = now()->copy()->endOfWeek();
                break;
            case 'month':
                $startDateTime = now()->copy()->startOfMonth();
                $endDateTime = now()->copy()->endOfMonth();
                break;
            case 'year':
                $startDateTime = now()->copy()->startOfYear();
                $endDateTime = now()->copy()->endOfYear();
                break;
            default:
                $startDateTime = Carbon::parse($startDate)->startOfDay();
                $endDateTime = Carbon::parse($endDate)->endOfDay();
        }

        $staff = User::whereIn('user_type', ['admin', 'staff'])
            ->select('id', 'name')
            ->orderBy('name')
            ->get();

        $labels = [];
        $bucketKey = 'bucket';
        $dateFormat = 'Y-m-d';

        if ($period === 'day') {
            for ($h = 0; $h < 24; $h++) {
                $labels[] = sprintf('%02d:00', $h);
            }
            $dateFormat = 'H';
        } else {
            $cursor = $startDateTime->copy();
            while ($cursor->lte($endDateTime)) {
                if ($period === 'year') {
                    $labels[] = $cursor->format('M');
                    $cursor->addMonth();
                } else {
                    $labels[] = $cursor->format('M j');
                    $cursor->addDay();
                }
            }
        }

        $baseQuery = Order::query()
            ->where('source', 'pos')
            ->where('payment_status', Order::PAYMENT_PAID)
            ->whereNotIn('status', [Order::STATUS_CANCELLED, Order::STATUS_RETURNED])
            ->whereBetween('created_at', [$startDateTime, $endDateTime]);

        if ($period === 'day') {
            $raw = $baseQuery->select('staff_id', DB::raw('HOUR(created_at) as ' . $bucketKey), DB::raw('SUM(total_payable) as total'))
                ->groupBy('staff_id', $bucketKey)
                ->get();
        } elseif ($period === 'year') {
            $raw = $baseQuery->select('staff_id', DB::raw('MONTH(created_at) as ' . $bucketKey), DB::raw('SUM(total_payable) as total'))
                ->groupBy('staff_id', $bucketKey)
                ->get();
        } else {
            $raw = $baseQuery->select('staff_id', DB::raw('DATE(created_at) as ' . $bucketKey), DB::raw('SUM(total_payable) as total'))
                ->groupBy('staff_id', $bucketKey)
                ->get();
        }

        $byStaff = $raw->groupBy('staff_id');
        $staffNames = $staff->keyBy('id');

        $colorPalette = [
            'rgb(59, 130, 246)',   'rgb(16, 185, 129)',   'rgb(245, 158, 11)',
            'rgb(239, 68, 68)',    'rgb(139, 92, 246)',   'rgb(236, 72, 153)',
            'rgb(20, 184, 166)',   'rgb(251, 146, 60)',
        ];

        $datasets = [];
        $idx = 0;
        foreach ($staff as $s) {
            $sid = $s->id;
            $name = $s->name;
            $bucketValues = $byStaff->get($sid, collect())->keyBy($bucketKey);

            if ($period === 'day') {
                $data = [];
                for ($h = 0; $h < 24; $h++) {
                    $data[] = (float) ($bucketValues->get($h)?->total ?? 0);
                }
            } elseif ($period === 'year') {
                $data = [];
                $cursor = $startDateTime->copy();
                while ($cursor->lte($endDateTime)) {
                    $m = (int) $cursor->format('n');
                    $data[] = (float) ($bucketValues->get($m)?->total ?? 0);
                    $cursor->addMonth();
                }
            } else {
                $data = [];
                $cursor = $startDateTime->copy();
                while ($cursor->lte($endDateTime)) {
                    $d = $cursor->format($dateFormat);
                    $data[] = (float) ($bucketValues->get($d)?->total ?? 0);
                    $cursor->addDay();
                }
            }

            $color = $colorPalette[$idx % count($colorPalette)];
            $bg = str_replace(')', ', 0.1)', str_replace('rgb', 'rgba', $color));
            $datasets[] = [
                'staff_id' => $sid,
                'staff_name' => $name,
                'data' => $data,
                'borderColor' => $color,
                'backgroundColor' => $bg,
            ];
            $idx++;
        }

        return response()->json([
            'labels' => $labels,
            'datasets' => $datasets,
        ]);
    }
}
