<?php

declare(strict_types=1);

namespace App\Http\Controllers;

use App\Models\Outlet;
use App\Models\OutletIngredient;
use App\Models\OutletProduct;
use App\Models\Product;
use App\Models\Supplier;
use App\Models\Transaction;
use App\Models\TransactionItem;
use App\Services\SettingService;
use Illuminate\Http\Request;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\DB;
use Inertia\Inertia;
use Inertia\Response;

class DashboardController extends Controller
{
    public function __construct(
        protected SettingService $settingService
    ) {}

    public function index(Request $request): Response
    {
        return Inertia::render('Dashboard', $this->getDashboardData($request));
    }

    public function print(Request $request): Response
    {
        return Inertia::render('DashboardPrint', $this->getDashboardData($request));
    }

    protected function getDashboardData(Request $request): array
    {
        // ── Resolve filters ─────────────────────────────────────────────────
        $outletId  = $request->input('outlet_id') ? (int) $request->input('outlet_id') : null;

        // month input: "YYYY-MM", defaults to current month
        $monthInput = $request->input('month', now()->format('Y-m'));
        try {
            $periodStart = Carbon::createFromFormat('Y-m', $monthInput)->startOfMonth();
        } catch (\Exception) {
            $periodStart = now()->startOfMonth();
            $monthInput  = now()->format('Y-m');
        }
        $periodEnd   = $periodStart->copy()->endOfMonth();
        $monthStart  = $periodStart->toDateString();
        $monthEnd    = $periodEnd->toDateString();

        // "Today" is always real today — only used for KPIs that compare vs yesterday
        $today     = now()->toDateString();
        $yesterday = now()->subDay()->toDateString();
        $weekStart = now()->startOfWeek()->toDateString();

        // ── Helper closure: base query filtered by outlet ────────────────────
        $base = fn() => Transaction::where('status', 'success')
            ->when($outletId, fn($q) => $q->where('outlet_id', $outletId));

        // ── KPI: Revenue Today (always real today) ───────────────────────────
        $revenueToday = (float) $base()->whereDate('created_at', $today)->sum('total_amount');
        $revenueYesterday = (float) $base()->whereDate('created_at', $yesterday)->sum('total_amount');
        $revenueTodayPct = $revenueYesterday > 0
            ? round((($revenueToday - $revenueYesterday) / $revenueYesterday) * 100, 1)
            : ($revenueToday > 0 ? 100 : 0);

        // ── KPI: Transactions Today ───────────────────────────────────────────
        $txToday     = $base()->whereDate('created_at', $today)->count();
        $txYesterday = $base()->whereDate('created_at', $yesterday)->count();
        $txTodayPct  = $txYesterday > 0
            ? round((($txToday - $txYesterday) / $txYesterday) * 100, 1)
            : ($txToday > 0 ? 100 : 0);

        // ── KPI: Average Ticket Today ─────────────────────────────────────────
        $avgTicketToday     = $txToday > 0 ? round($revenueToday / $txToday, 0) : 0;
        $avgTicketYesterday = $txYesterday > 0 ? round($revenueYesterday / $txYesterday, 0) : 0;
        $avgTicketPct       = $avgTicketYesterday > 0
            ? round((($avgTicketToday - $avgTicketYesterday) / $avgTicketYesterday) * 100, 1)
            : ($avgTicketToday > 0 ? 100 : 0);

        // ── Secondary: Revenue this week / selected month ─────────────────────
        $revenueWeek  = (float) $base()
            ->whereBetween(DB::raw('DATE(created_at)'), [$weekStart, $today])
            ->sum('total_amount');

        $revenueMonth = (float) $base()
            ->whereBetween(DB::raw('DATE(created_at)'), [$monthStart, $monthEnd])
            ->sum('total_amount');

        $txMonth = $base()
            ->whereBetween(DB::raw('DATE(created_at)'), [$monthStart, $monthEnd])
            ->count();

        // ── Counts (not filtered by outlet/month) ────────────────────────────
        $activeOutlets  = Outlet::count();
        $activeProducts = Product::where('is_active', true)->count();
        $totalSuppliers = Supplier::count();

        // ── Low Stock Alerts (outlet-filtered) ───────────────────────────────
        $lowIngredients = OutletIngredient::with(['outlet', 'ingredient'])
            ->whereColumn('stock_qty', '<=', 'threshold_qty')
            ->when($outletId, fn($q) => $q->where('outlet_id', $outletId))
            ->get()
            ->map(fn($i) => [
                'type'          => 'Ingredient',
                'name'          => $i->ingredient->name,
                'outlet_name'   => $i->outlet->name,
                'stock_qty'     => (float) $i->stock_qty,
                'threshold_qty' => (float) $i->threshold_qty,
                'unit'          => $i->ingredient->unit,
            ]);

        $lowProducts = OutletProduct::with(['outlet', 'product'])
            ->whereColumn('stock_qty', '<=', 'threshold_qty')
            ->when($outletId, fn($q) => $q->where('outlet_id', $outletId))
            ->get()
            ->map(fn($i) => [
                'type'          => 'Retail',
                'name'          => $i->product->name,
                'outlet_name'   => $i->outlet->name,
                'stock_qty'     => (float) $i->stock_qty,
                'threshold_qty' => (float) $i->threshold_qty,
                'unit'          => 'pcs',
            ]);

        $lowStockAlerts = $lowIngredients->concat($lowProducts)->values();

        // ── Sales Trend: daily for selected month ─────────────────────────────
        $salesTrend = $base()
            ->whereBetween(DB::raw('DATE(created_at)'), [$monthStart, $monthEnd])
            ->select(
                DB::raw('DATE(created_at) as date'),
                DB::raw('SUM(total_amount) as total'),
                DB::raw('COUNT(id) as count')
            )
            ->groupBy(DB::raw('DATE(created_at)'))
            ->orderBy('date')
            ->get()
            ->map(fn($r) => [
                'date'  => $r->date,
                'total' => (float) $r->total,
                'count' => (int) $r->count,
            ]);

        // ── Top 5 Products for selected month ─────────────────────────────────
        $topProducts = TransactionItem::whereHas('transaction', function ($q) use ($monthStart, $monthEnd, $outletId) {
                $q->where('status', 'success')
                  ->whereBetween(DB::raw('DATE(created_at)'), [$monthStart, $monthEnd]);
                if ($outletId) $q->where('outlet_id', $outletId);
            })
            ->select('product_id', DB::raw('SUM(qty) as total_qty'), DB::raw('SUM(subtotal) as total_sales'))
            ->groupBy('product_id')
            ->orderByDesc('total_qty')
            ->limit(5)
            ->with('product')
            ->get()
            ->map(fn($r) => [
                'name'     => $r->product?->name ?? 'Unknown',
                'category' => $r->product?->category ?? '-',
                'qty'      => (int) $r->total_qty,
                'sales'    => (float) $r->total_sales,
            ]);

        // ── Payment Method Split for selected month ───────────────────────────
        $paymentSplit = $base()
            ->whereBetween(DB::raw('DATE(created_at)'), [$monthStart, $monthEnd])
            ->select('payment_method', DB::raw('COUNT(id) as count'), DB::raw('SUM(total_amount) as total'))
            ->groupBy('payment_method')
            ->get()
            ->map(fn($r) => [
                'method' => $r->payment_method,
                'count'  => (int) $r->count,
                'total'  => (float) $r->total,
            ]);

        // ── Revenue by Outlet for selected month ──────────────────────────────
        $revenueByOutlet = Transaction::where('status', 'success')
            ->whereBetween(DB::raw('DATE(created_at)'), [$monthStart, $monthEnd])
            ->when($outletId, fn($q) => $q->where('outlet_id', $outletId))
            ->select('outlet_id', DB::raw('SUM(total_amount) as total'), DB::raw('COUNT(id) as count'))
            ->groupBy('outlet_id')
            ->with('outlet')
            ->get()
            ->map(fn($r) => [
                'outlet' => $r->outlet?->name ?? 'Unknown',
                'total'  => (float) $r->total,
                'count'  => (int) $r->count,
            ]);

        // ── Recent 8 Transactions (outlet-filtered, always latest) ────────────
        $recentTransactions = Transaction::with(['outlet', 'user', 'items.product'])
            ->where('status', 'success')
            ->when($outletId, fn($q) => $q->where('outlet_id', $outletId))
            ->latest()
            ->limit(8)
            ->get()
            ->map(fn($tx) => [
                'id'                 => $tx->id,
                'transaction_number' => $tx->transaction_number,
                'outlet_name'        => $tx->outlet?->name ?? '-',
                'cashier_name'       => $tx->user?->name ?? '-',
                'total_amount'       => (float) $tx->total_amount,
                'payment_method'     => $tx->payment_method,
                'items_count'        => $tx->items->count(),
                'created_at'         => $tx->created_at->format('d M Y H:i'),
            ]);

        // ── Outlets list (for filter dropdown) ────────────────────────────────
        $outlets = Outlet::select('id', 'name')->orderBy('name')->get();

        $appName = $this->settingService->get('app_name', config('app.name'));

        return [
            'kpi' => [
                'revenue_today'     => $revenueToday,
                'revenue_today_pct' => $revenueTodayPct,
                'revenue_week'      => $revenueWeek,
                'revenue_month'     => $revenueMonth,
                'tx_today'          => $txToday,
                'tx_today_pct'      => $txTodayPct,
                'tx_month'          => $txMonth,
                'avg_ticket_today'  => $avgTicketToday,
                'avg_ticket_pct'    => $avgTicketPct,
                'low_stock_count'   => $lowStockAlerts->count(),
                'active_outlets'    => $activeOutlets,
                'active_products'   => $activeProducts,
                'total_suppliers'   => $totalSuppliers,
            ],
            'salesTrend'         => $salesTrend,
            'topProducts'        => $topProducts,
            'paymentSplit'       => $paymentSplit,
            'revenueByOutlet'    => $revenueByOutlet,
            'recentTransactions' => $recentTransactions,
            'lowStockAlerts'     => $lowStockAlerts,
            'outlets'            => $outlets,
            'appName'            => $appName,
            'filters'            => [
                'month'     => $monthInput,
                'outlet_id' => $outletId,
            ],
        ];
    }
}
