<?php

namespace App\Http\Controllers;

use App\Models\Customer;
use App\Models\EtimsConfig;
use App\Models\EtimsInvoice;
use App\Models\InventoryLog;
use App\Models\MpesaConfig;
use App\Models\OpeningBalance;
use App\Models\Order;
use App\Models\OrderItem;
use App\Models\Product;
use App\Models\TaxConfig;
use App\Models\UserActivityLog;
use Carbon\Carbon;
use Dompdf\Dompdf;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

class OrderController extends Controller
{
    public function home()
    {
        return view('pos.index');
    }

    public function sales()
    {
        $products = Product::active()->with('unitOfMeasure')->orderBy('name')->get(['id', 'name', 'sku', 'barcode', 'image', 'cost_price', 'selling_price', 'price_2', 'price_3', 'price_2_name', 'price_3_name', 'stock_quantity', 'expiry_date', 'category_id', 'unit_of_measure_id']);
        $customers = Customer::active()->orderBy('name')->get();
        $taxConfigs = TaxConfig::active()->get();

        $today = now()->toDateString();
        $openingBalance = OpeningBalance::where('user_id', auth()->id())
            ->where('date', $today)
            ->first();

        $cashierName = auth()->user()->name ?? 'Cashier';

        $mpesaConfig = MpesaConfig::getActiveConfig();
        if (! $mpesaConfig) {
            $mpesaConfig = MpesaConfig::where('manual_recording', true)->first();
        }
        $mpesaManualRecording = $mpesaConfig ? $mpesaConfig->manual_recording : false;

        return view('pos.sales', compact('products', 'customers', 'openingBalance', 'taxConfigs', 'cashierName', 'mpesaManualRecording'));
    }

    public function products()
    {
        $products = Product::active()
            ->where(function ($query) {
                $query->whereNull('expiry_date')
                    ->orWhereDate('expiry_date', '>=', now());
            })
            ->orderBy('name')
            ->get(['id', 'name', 'stock_quantity', 'selling_price']);

        return response()->json($products);
    }

    public function store(Request $request)
    {
        $request->validate([
            'items' => 'required|array|min:1',
            'items.*.id' => 'required|exists:products,id',
            'items.*.qty' => 'required|numeric|min:0.1',
            'customer_id' => 'nullable|exists:customers,id',
            'discount_value' => 'nullable|numeric|min:0',
            'discount_type' => 'required|in:percentage,fixed',
            'paid_amount' => 'required|numeric|min:0',
            'payment_type' => 'nullable|in:cash,credit,partial',
            'due_date' => 'nullable|date',
        ]);

        foreach ($request->items as $item) {
            $product = Product::findOrFail($item['id']);
            $price = $item['price'] ?? $product->selling_price;
            if ($product->cost_price && $price < $product->cost_price) {
                return response()->json([
                    'message' => "Cannot sell {$product->name} below buying price (Kes {$product->cost_price})",
                ], 422);
            }
        }

        $order = null;
        DB::transaction(function () use ($request, &$order) {
            $items = $request->items;
            $subtotal = 0;

            foreach ($items as $item) {
                $product = Product::findOrFail($item['id']);
                $price = $item['price'] ?? $product->selling_price;
                $subtotal += $price * $item['qty'];
            }

            $discount = 0;
            $discountValue = $request->discount_value ?? 0;
            if ($discountValue > 0) {
                if ($request->discount_type === 'percentage') {
                    $discount = $subtotal * ($discountValue / 100);
                } else {
                    $discount = $discountValue;
                }
            }

            $afterDiscount = $subtotal - $discount;
            $taxResult = TaxConfig::calculateTax($afterDiscount);
            $tax = $taxResult['total_tax'];
            $taxDetailsJson = json_encode($taxResult['tax_details']);
            $total = $afterDiscount + $tax;

            $paymentType = $request->payment_type ?? 'cash';
            $paidAmount = $request->paid_amount;
            $creditAmount = 0;
            $creditStatus = null;

            if ($paymentType === 'credit') {
                $creditAmount = $total;
                $paidAmount = 0;
                $creditStatus = 'pending';
            } elseif ($paymentType === 'partial') {
                $creditAmount = $total - $paidAmount;
                if ($creditAmount > 0) {
                    $creditStatus = 'partial';
                }
            } else {
                $changeAmount = $paidAmount - $total;
                if ($changeAmount < 0) {
                    throw new \Exception('Insufficient payment amount.');
                }
            }

            if (in_array($paymentType, ['credit', 'partial']) && ! $request->customer_id) {
                throw new \Exception('Customer is required for credit sales.');
            }

            $invoiceNumber = 'INV-'.date('Ymd').'-'.str_pad(Order::count() + 1, 6, '0', STR_PAD_LEFT);

            $paymentMethodsJson = $request->payment_methods ?: '[]';
            $paymentMethods = json_decode($paymentMethodsJson, true) ?: [];
            $primaryPayment = count($paymentMethods) > 0 ? $paymentMethods[0]['method'] : 'cash';

            $totalTaxRate = collect($taxResult['tax_details'])->sum('tax_rate');

            $order = Order::create([
                'invoice_number' => $invoiceNumber,
                'user_id' => auth()->id(),
                'customer_id' => $request->customer_id,
                'client_time' => $request->client_time ? Carbon::parse($request->client_time) : null,
                'subtotal' => $subtotal,
                'discount' => $discount,
                'discount_type' => $request->discount_type === 'percentage' ? $discountValue : 0,
                'tax' => $tax,
                'tax_rate' => $totalTaxRate,
                'tax_details' => $taxDetailsJson,
                'total' => $total,
                'paid_amount' => $paidAmount,
                'change_amount' => max(0, $paidAmount - $total),
                'payment_method' => $primaryPayment,
                'payment_methods' => $paymentMethodsJson,
                'payment_type' => $paymentType,
                'credit_amount' => $creditAmount,
                'due_date' => $request->due_date,
                'credit_status' => $creditStatus,
                'status' => 'completed',
                'notes' => $request->notes,
            ]);

            if ($creditAmount > 0 && $request->customer_id) {
                $customer = Customer::find($request->customer_id);
                if ($customer) {
                    $customer->balance = ($customer->balance ?? 0) + $creditAmount;
                    $customer->save();
                }
            }

            $this->createEtimsInvoice($order);

            $this->createEtimsInvoice($order);

            foreach ($items as $item) {
                $product = Product::findOrFail($item['id']);

                $price = $item['price'] ?? $product->selling_price;
                $priceType = 'default';
                if ($product->price_2 && $price == $product->price_2) {
                    $priceType = $product->price_2_name ?: 'Price 2';
                } elseif ($product->price_3 && $price == $product->price_3) {
                    $priceType = $product->price_3_name ?: 'Price 3';
                }

                OrderItem::create([
                    'order_id' => $order->id,
                    'product_id' => $product->id,
                    'product_name' => $product->name,
                    'product_sku' => $product->sku,
                    'price' => $price,
                    'price_type' => $priceType,
                    'unit_cost' => $product->cost_price,
                    'quantity' => $item['qty'],
                    'subtotal' => $price * $item['qty'],
                ]);

                $previousStock = $product->stock_quantity;
                $newStock = $previousStock - $item['qty'];

                $product->update(['stock_quantity' => $newStock]);

                InventoryLog::create([
                    'product_id' => $product->id,
                    'user_id' => auth()->id(),
                    'type' => 'stock_out',
                    'quantity' => $item['qty'],
                    'previous_stock' => $previousStock,
                    'new_stock' => $newStock,
                    'reference_number' => $invoiceNumber,
                    'notes' => 'Sale',
                ]);
            }

            if ($request->customer_id) {
                // Customer processing would go here
            }

            try {
                UserActivityLog::logActivity(
                    auth()->user(),
                    'sale',
                    "Completed sale - Invoice: {$invoiceNumber}, Total: {$total}",
                    [
                        'order_id' => $order->id,
                        'invoice_number' => $invoiceNumber,
                        'total' => $total,
                        'items_count' => count($items),
                    ],
                    $request,
                    $request->client_time
                );
            } catch (\Exception $e) {
                // Log activity failed, but don't break checkout
            }
        });

        if (! $order) {
            return response()->json(['success' => false, 'message' => 'Failed to create order'], 500);
        }

        return response()->json([
            'success' => true,
            'message' => 'Order completed successfully.',
            'order_id' => $order->id,
        ]);
    }

    public function index(Request $request)
    {
        $query = Order::with(['user', 'customer']);

        if ($request->date_from) {
            $query->whereDate('created_at', '>=', $request->date_from);
        }

        if ($request->date_to) {
            $query->whereDate('created_at', '<=', $request->date_to);
        }

        if ($request->status) {
            $query->where('status', $request->status);
        }

        if ($request->invoice_number) {
            $query->where('invoice_number', 'like', '%'.$request->invoice_number.'%');
        }

        $orders = $query->orderBy('created_at', 'desc')->paginate(20);

        return view('orders.index', compact('orders'));
    }

    public function show(Order $order)
    {
        $order->load(['user', 'customer', 'items.product']);

        return view('orders.show', compact('order'));
    }

    public function destroy(Order $order)
    {
        if ($order->status === 'cancelled') {
            return back()->with('error', 'Order is already cancelled.');
        }

        DB::transaction(function () use ($order) {
            foreach ($order->items as $item) {
                $product = $item->product;
                $product->update([
                    'stock_quantity' => $product->stock_quantity + $item->quantity,
                ]);

                InventoryLog::create([
                    'product_id' => $product->id,
                    'user_id' => auth()->id(),
                    'type' => 'stock_in',
                    'quantity' => $item->quantity,
                    'previous_stock' => $product->stock_quantity - $item->quantity,
                    'new_stock' => $product->stock_quantity,
                    'reference_number' => $order->invoice_number.'-CANCEL',
                    'notes' => 'Order cancellation - Stock returned',
                ]);
            }

            $order->update(['status' => 'cancelled']);
        });

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

    public function receipt(Order $order)
    {
        $order->load(['user', 'customer', 'items']);

        return view('orders.receipt', compact('order'));
    }

    public function receiptPdf(Order $order)
    {
        $order->load(['user', 'customer', 'items.product']);

        $receipt_header = DB::table('settings')->where('key', 'receipt_header')->value('value');
        $receipt_tagline = DB::table('settings')->where('key', 'receipt_tagline')->value('value');
        $receipt_address = DB::table('settings')->where('key', 'receipt_address')->value('value');
        $receipt_phone = DB::table('settings')->where('key', 'receipt_phone')->value('value');
        $receipt_footer = DB::table('settings')->where('key', 'receipt_footer')->value('value');
        $receipt_dev_ad = DB::table('settings')->where('key', 'receipt_dev_ad')->value('value');

        $dompdf = new Dompdf;
        $html = view('orders.receipt_pdf', compact('order', 'receipt_header', 'receipt_tagline', 'receipt_address', 'receipt_phone', 'receipt_footer', 'receipt_dev_ad'))->render();

        $dompdf->loadHtml($html);
        $dompdf->setPaper([0, 0, 226, 600], 'portrait');
        $dompdf->render();

        return $dompdf->stream('receipt_'.$order->invoice_number.'.pdf');
    }

    protected function createEtimsInvoice(Order $order)
    {
        if (! EtimsConfig::isConfigured()) {
            return;
        }

        EtimsInvoice::create([
            'order_id' => $order->id,
            'invoice_number' => $order->invoice_number,
            'etims_status' => 'pending',
        ]);
    }
}
