<?php

namespace App\Http\Controllers\Epelcon;

use App\Http\Controllers\Controller;
use App\Models\Booking;
use App\Models\InventoryItem;
use App\Models\PurchaseOrder;
use App\Models\StockMovement;
use Carbon\Carbon;
use Illuminate\Http\Request;

class ReportController extends Controller
{
    protected function range(Request $request): array
    {
        $from = $request->filled('from') ? Carbon::parse($request->from)->startOfDay() : now()->startOfMonth();
        $to = $request->filled('to') ? Carbon::parse($request->to)->endOfDay() : now()->endOfDay();

        return [$from, $to];
    }

    public function bookings(Request $request)
    {
        [$from, $to] = $this->range($request);

        $bookings = Booking::with(['customer', 'room', 'roomType'])
            ->whereBetween('created_at', [$from, $to])
            ->latest()
            ->get();

        $totals = [
            'count' => $bookings->count(),
            'nights' => $bookings->sum(fn ($b) => $b->nights()),
            'billed' => (float) $bookings->sum('total_amount'),
            'collected' => (float) $bookings->sum('paid_amount'),
        ];
        $totals['outstanding'] = $totals['billed'] - $totals['collected'];

        $byStatus = $bookings->groupBy('status')->map(fn ($group) => [
            'count' => $group->count(),
            'total' => (float) $group->sum('total_amount'),
        ])->sortByDesc('count');

        $bySource = $bookings->groupBy('source')->map(fn ($group) => [
            'count' => $group->count(),
            'total' => (float) $group->sum('total_amount'),
        ])->sortByDesc('count');

        return view('epelcon.reports.bookings', compact('bookings', 'totals', 'byStatus', 'bySource', 'from', 'to'));
    }

    public function purchases(Request $request)
    {
        [$from, $to] = $this->range($request);

        $orders = PurchaseOrder::with('supplier')
            ->whereBetween('order_date', [$from->toDateString(), $to->toDateString()])
            ->latest('order_date')
            ->get();

        $byStatus = $orders->groupBy('status')->map(fn ($group) => [
            'count' => $group->count(),
            'total' => (float) $group->sum('total'),
        ])->sortByDesc('total');

        $totals = [
            'count' => $orders->count(),
            'value' => (float) $orders->sum('total'),
            'spend' => (float) $orders->where('status', 'received')->sum('total'),
        ];

        $bySupplier = $orders->groupBy(fn ($po) => $po->supplier->name ?? '—')
            ->map(fn ($group) => [
                'count' => $group->count(),
                'total' => (float) $group->sum('total'),
                'received' => (float) $group->where('status', 'received')->sum('total'),
            ])->sortByDesc('total');

        return view('epelcon.reports.purchases', compact('orders', 'byStatus', 'bySupplier', 'totals', 'from', 'to'));
    }

    public function stock(Request $request)
    {
        [$from, $to] = $this->range($request);

        $stockValue = (float) InventoryItem::selectRaw('COALESCE(SUM(quantity * cost_price), 0) as v')->value('v');
        $itemCount = InventoryItem::count();

        $lowStock = InventoryItem::whereColumn('quantity', '<=', 'reorder_level')
            ->orderBy('quantity')
            ->get();

        $movements = StockMovement::selectRaw('type, COUNT(*) as cnt, COALESCE(SUM(quantity), 0) as qty')
            ->whereBetween('created_at', [$from, $to])
            ->groupBy('type')
            ->get()
            ->keyBy('type');

        $expiring = InventoryItem::whereNotNull('expiry_date')
            ->whereBetween('expiry_date', [today(), today()->addDays(30)])
            ->orderBy('expiry_date')
            ->get();

        return view('epelcon.reports.stock', compact('stockValue', 'itemCount', 'lowStock', 'movements', 'expiring', 'from', 'to'));
    }
}
