<?php

namespace App\Http\Controllers;

use App\Models\Category;
use App\Models\Customer;
use App\Models\Order;
use App\Models\Product;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

class OrderController extends Controller
{
    public function index(Request $request)
    {
        $filter = $request->get('filter', 'today');
        $from = $request->get('from');
        $to = $request->get('to');

        $query = Order::with('items.product.category', 'items.product.weight', 'customer')->latest();

        switch ($filter) {
            case 'today':
                $query->whereDate('date', today());
                $label = 'Today (' . today()->format('d M Y') . ')';
                break;
            case 'yesterday':
                $query->whereDate('date', today()->subDay());
                $label = 'Yesterday (' . today()->subDay()->format('d M Y') . ')';
                break;
            case 'week':
                $query->whereBetween('date', [now()->startOfWeek(), now()->endOfWeek()]);
                $label = 'This Week (' . now()->startOfWeek()->format('d M') . ' - ' . now()->endOfWeek()->format('d M Y') . ')';
                break;
            case 'month':
                $query->whereMonth('date', now()->month)->whereYear('date', now()->year);
                $label = 'This Month (' . now()->format('F Y') . ')';
                break;
            case 'custom':
                if ($from) $query->whereDate('date', '>=', $from);
                if ($to) $query->whereDate('date', '<=', $to);
                $label = 'Custom: ' . ($from ?: '...') . ' to ' . ($to ?: '...');
                break;
            default:
                $query->whereDate('date', today());
                $label = 'Today';
                $filter = 'today';
        }

        $orders = $query->paginate(30)->appends($request->query());

        $sumQuery = Order::query();
        switch ($filter) {
            case 'today': $sumQuery->whereDate('date', today()); break;
            case 'yesterday': $sumQuery->whereDate('date', today()->subDay()); break;
            case 'week': $sumQuery->whereBetween('date', [now()->startOfWeek(), now()->endOfWeek()]); break;
            case 'month': $sumQuery->whereMonth('date', now()->month)->whereYear('date', now()->year); break;
            case 'custom':
                if ($from) $sumQuery->whereDate('date', '>=', $from);
                if ($to) $sumQuery->whereDate('date', '<=', $to);
                break;
        }
        $totalSales = $sumQuery->sum('total');
        $totalPaid = $sumQuery->sum('paid');

        return view('orders.index', compact('orders', 'filter', 'from', 'to', 'label', 'totalSales', 'totalPaid'));
    }

    public function create()
    {
        $categories = Category::orderBy('name')->get();
        $products = Product::with('weight')->orderBy('category_id')->orderBy('weight_id')->get();
        $customers = Customer::orderBy('name')->get();
        return view('orders.form', compact('categories', 'products', 'customers'));
    }

    public function store(Request $request)
    {
        $validated = $this->validateOrder($request);
        $stockError = $this->checkStock($validated['items']);
        if ($stockError) {
            return back()->withInput()->with('error', $stockError);
        }

        // Walk-in: force full payment
        if (empty($validated['customer_id'])) {
            $validated['paid'] = null; // will be set to total in saveOrder
        }

        DB::transaction(function () use ($validated) {
            $order = $this->saveOrder(new Order(), $validated);
            if ($order->customer_id) {
                $order->customer->recalculateBalance();
            }
        });

        return redirect()->route('orders.index')->with('success', 'Order created.');
    }

    public function show(Order $order)
    {
        $order->load('items.product.category', 'items.product.weight', 'customer');
        return view('orders.show', compact('order'));
    }

    public function edit(Order $order)
    {
        $order->load('items');
        $categories = Category::orderBy('name')->get();
        $products = Product::with('weight')->orderBy('category_id')->orderBy('weight_id')->get();
        $customers = Customer::orderBy('name')->get();
        return view('orders.form', compact('order', 'categories', 'products', 'customers'));
    }

    public function update(Request $request, Order $order)
    {
        $validated = $this->validateOrder($request);

        // Check stock (add back current order quantities first)
        $currentItems = $order->items->pluck('quantity', 'product_id')->toArray();
        $stockError = $this->checkStock($validated['items'], $currentItems);
        if ($stockError) {
            return back()->withInput()->with('error', $stockError);
        }

        if (empty($validated['customer_id'])) {
            $validated['paid'] = null;
        }

        $oldCustomerId = $order->customer_id;

        DB::transaction(function () use ($order, $validated, $oldCustomerId) {
            foreach ($order->items as $item) {
                Product::where('id', $item->product_id)->increment('stock', $item->quantity);
            }
            $order->items()->delete();

            $this->saveOrder($order, $validated);

            if ($oldCustomerId) {
                Customer::find($oldCustomerId)?->recalculateBalance();
            }
            if ($order->customer_id && $order->customer_id != $oldCustomerId) {
                $order->customer->recalculateBalance();
            }
        });

        return redirect()->route('orders.show', $order)->with('success', 'Order updated.');
    }

    public function destroy(Order $order)
    {
        $customerId = $order->customer_id;

        DB::transaction(function () use ($order, $customerId) {
            foreach ($order->items as $item) {
                Product::where('id', $item->product_id)->increment('stock', $item->quantity);
            }
            $order->delete();

            if ($customerId) {
                Customer::find($customerId)?->recalculateBalance();
            }
        });

        return redirect()->route('orders.index')->with('success', 'Order deleted and stock restored.');
    }

    private function validateOrder(Request $request): array
    {
        return $request->validate([
            'customer_id' => 'nullable|exists:customers,id',
            'customer_name' => 'nullable|string|max:255',
            'paid' => 'nullable|numeric|min:0',
            'notes' => 'nullable|string',
            'items' => 'required|array|min:1',
            'items.*.product_id' => 'required|exists:products,id',
            'items.*.quantity' => 'required|integer|min:1',
        ]);
    }

    /**
     * Check if all items have enough stock.
     * $existingItems = [product_id => qty] from current order (for edit mode)
     */
    private function checkStock(array $items, array $existingItems = []): ?string
    {
        foreach ($items as $item) {
            $product = Product::with('category', 'weight')->find($item['product_id']);
            $available = $product->stock + ($existingItems[$item['product_id']] ?? 0);
            if ($item['quantity'] > $available) {
                return ($product->category->name ?? '') . ' ' . ($product->weight->label ?? '') . ' — only ' . $available . ' bags in stock, you requested ' . $item['quantity'];
            }
        }
        return null;
    }

    private function saveOrder(Order $order, array $validated): Order
    {
        $total = 0;
        $items = [];

        foreach ($validated['items'] as $item) {
            $product = Product::find($item['product_id']);
            $subtotal = $item['quantity'] * $product->price;
            $total += $subtotal;
            $items[] = [
                'product_id' => $item['product_id'],
                'quantity' => $item['quantity'],
                'price' => $product->price,
                'subtotal' => $subtotal,
            ];
        }

        // Walk-in = full payment, B2B = partial allowed
        $isB2B = !empty($validated['customer_id']);
        $paid = $isB2B ? ($validated['paid'] ?? $total) : $total;

        $order->fill([
            'customer_id' => $validated['customer_id'] ?? null,
            'customer_name' => $validated['customer_name'] ?? null,
            'customer_phone' => null,
            'date' => $order->date ?? today(),
            'total' => $total,
            'paid' => $paid,
            'extra_payment' => 0,
            'status' => 'completed',
            'notes' => $validated['notes'] ?? null,
        ]);
        $order->save();

        foreach ($items as $item) {
            $order->items()->create($item);
            Product::where('id', $item['product_id'])->decrement('stock', $item['quantity']);
        }

        return $order;
    }
}
