<?php

namespace App\Http\Controllers\Api\V1\Admin;

use App\Http\Controllers\Controller;
use App\Models\Product;
use App\Models\ProductVariant;
use App\Models\User;
use App\Models\Order;
use App\Models\OrderItem;
use App\Models\Payment;
use App\Models\Voucher;
use App\Models\Setting;
use App\Services\ProductService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;

class AdminPOSController extends Controller
{
    protected $productService;

    public function __construct(ProductService $productService)
    {
        $this->productService = $productService;
    }

    private function checkAdmin()
    {
        if (auth()->user()->role !== 'admin') {
            abort(response()->json(['error' => 'Forbidden'], 403));
        }
    }

    /**
     * Get active products list for POS with search and category filter.
     */
    public function indexProducts(Request $request)
    {
        $this->checkAdmin();

        $query = Product::with(['category', 'images', 'variants'])
            ->where('status', 'active');

        // Search by name or SKU
        if ($request->filled('search')) {
            $search = $request->search;
            $query->where(function ($q) use ($search) {
                $q->where('name', 'like', "%{$search}%")
                  ->orWhere('sku', 'like', "%{$search}%");
            });
        }

        // Filter by category
        if ($request->filled('category_id')) {
            $query->where('category_id', $request->category_id);
        }

        $products = $query->latest()->paginate(16);

        // Map final prices for variants if they apply
        $products->getCollection()->each(function($product) {
            $product->variants->each(function($variant) use ($product) {
                $basePrice = $variant->price ?? $product->price;
                if ($product->discount_percent > 0) {
                    $variant->final_price = (float)($basePrice - ($basePrice * $product->discount_percent / 100));
                } else {
                    $variant->final_price = (float)$basePrice;
                }
            });
        });

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

    /**
     * Get list of customers (role = customer).
     */
    public function indexCustomers(Request $request)
    {
        $this->checkAdmin();

        $query = User::where('role', 'customer');

        if ($request->filled('search')) {
            $search = $request->search;
            $query->where(function ($q) use ($search) {
                $q->where('name', 'like', "%{$search}%")
                  ->orWhere('email', 'like', "%{$search}%")
                  ->orWhere('whatsapp', 'like', "%{$search}%");
            });
        }

        $customers = $query->latest()->limit(50)->get(['id', 'name', 'email', 'whatsapp']);

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

    /**
     * Register a customer quickly from POS dashboard.
     */
    public function storeCustomer(Request $request)
    {
        $this->checkAdmin();

        $request->validate([
            'name' => 'required|string|max:255',
            'email' => 'nullable|email|unique:users,email',
            'whatsapp' => 'nullable|string|max:20',
        ]);

        $email = $request->email ?: 'pos_' . Str::random(5) . '_' . time() . '@toko.lrv';
        $whatsapp = $request->whatsapp ? preg_replace('/[^0-9]/', '', $request->whatsapp) : null;

        $customer = User::create([
            'name' => $request->name,
            'email' => $email,
            'whatsapp' => $whatsapp,
            'password' => Hash::make(Str::random(16)),
            'role' => 'customer',
        ]);

        return response()->json([
            'success' => true,
            'message' => 'Pelanggan berhasil ditambahkan.',
            'customer' => $customer->only(['id', 'name', 'email', 'whatsapp']),
        ], 201);
    }

    /**
     * Submit POS checkout transaction.
     */
    public function storeOrder(Request $request)
    {
        $this->checkAdmin();

        $request->validate([
            'customer_id' => 'nullable|exists:users,id',
            'items' => 'required|array|min:1',
            'items.*.product_id' => 'required|exists:products,id',
            'items.*.variant_id' => 'nullable|exists:product_variants,id',
            'items.*.qty' => 'required|integer|min:1',
            'voucher_code' => 'nullable|string',
            'manual_discount' => 'nullable|numeric|min:0',
            'payment_method' => 'required|string|in:cash,bank_transfer,qris',
            'amount_paid' => 'required_if:payment_method,cash|numeric|nullable',
            'notes' => 'nullable|string',
        ]);

        try {
            return DB::transaction(function() use ($request) {
                // Resolve customer (default to Walk-in if none selected)
                $userId = $request->customer_id;
                if (!$userId) {
                    $walkin = User::where('email', 'walkin@toko.lrv')->first();
                    if (!$walkin) {
                        $walkin = User::create([
                            'name' => 'Walk-in Customer',
                            'email' => 'walkin@toko.lrv',
                            'password' => Hash::make(Str::random(16)),
                            'role' => 'customer',
                        ]);
                    }
                    $userId = $walkin->id;
                }

                $user = User::find($userId);

                // Calculate totals and validate stocks
                $subtotal = 0;
                $orderItemsData = [];

                foreach ($request->items as $itemData) {
                    $product = Product::findOrFail($itemData['product_id']);
                    $variant = null;
                    $price = $product->price;

                    if (!empty($itemData['variant_id'])) {
                        $variant = ProductVariant::where('product_id', $product->id)->findOrFail($itemData['variant_id']);
                        $price = $variant->price ?? $product->price;
                    }

                    // Apply product discount percent
                    if ($product->discount_percent > 0) {
                        $price = $price - ($price * $product->discount_percent / 100);
                    }

                    // Validate stock
                    $qty = (int)$itemData['qty'];
                    $availableStock = $variant ? $variant->stock : $product->stock;
                    if ($availableStock < $qty) {
                        throw new \Exception("Stok tidak mencukupi untuk {$product->name}" . ($variant ? " ({$variant->name}: {$variant->value})" : "") . ". Stok tersedia: {$availableStock}.");
                    }

                    $subtotal += ($price * $qty);

                    $orderItemsData[] = [
                        'product_id' => $product->id,
                        'variant_id' => $variant ? $variant->id : null,
                        'qty' => $qty,
                        'price' => $price,
                    ];
                }

                // Voucher application
                $discount = 0;
                $voucherId = null;
                if ($request->filled('voucher_code')) {
                    $voucher = Voucher::where('code', $request->voucher_code)->first();
                    if ($voucher && $voucher->isValid()) {
                        if ($subtotal >= $voucher->min_spend) {
                            $discount = $voucher->calculateDiscount($subtotal);
                            if ($discount > 0) {
                                $voucherId = $voucher->id;
                                $voucher->decrement('stock');
                            }
                        } else {
                            throw new \Exception("Minimal belanja untuk voucher {$voucher->code} adalah " . number_format($voucher->min_spend, 0, ',', '.') . ".");
                        }
                    } else {
                        throw new \Exception("Kode voucher tidak valid, kedaluwarsa, atau habis.");
                    }
                } else if ($request->filled('manual_discount')) {
                    $discount = (float)$request->manual_discount;
                }

                // Calculate Tax
                $taxAmount = 0.00;
                $taxActive = Setting::get('tax_active', 'true') === 'true';
                if ($taxActive) {
                    $taxPercent = (float) Setting::get('tax_percent', '11');
                    $taxableAmount = max(0.00, $subtotal - $discount);
                    $taxAmount = round(($taxableAmount * $taxPercent) / 100, 2);
                }

                $grandTotal = max(0, $subtotal - $discount + $taxAmount);

                // Calculate change for cash payment
                $amountPaid = $request->amount_paid;
                if ($request->payment_method === 'cash') {
                    if ($amountPaid < $grandTotal) {
                        throw new \Exception("Jumlah uang dibayar kurang dari total transaksi.");
                    }
                    $changeAmount = $amountPaid - $grandTotal;
                } else {
                    $amountPaid = $grandTotal;
                    $changeAmount = 0;
                }

                // Generate unique invoice number
                $invoiceNumber = 'INV/' . date('Ymd') . '/' . strtoupper(Str::random(6));

                // Create Order
                $shippingAddressText = "POS In-Store Purchase (" . ($request->customer_id ? $user->name : 'Walk-in') . ")";
                $order = Order::create([
                    'user_id' => $user->id,
                    'invoice_number' => $invoiceNumber,
                    'status' => 'completed', // Direct complete since it's POS checkout
                    'total' => $grandTotal,
                    'shipping_cost' => 0,
                    'tax_amount' => $taxAmount,
                    'voucher_id' => $voucherId,
                    'discount_amount' => $discount,
                    'shipping_address' => $shippingAddressText,
                    'payment_type' => 'full',
                    'cancel_reason' => null
                ]);

                // Save order items & deduct stock
                foreach ($orderItemsData as $item) {
                    OrderItem::create([
                        'order_id' => $order->id,
                        'product_id' => $item['product_id'],
                        'variant_id' => $item['variant_id'],
                        'qty' => $item['qty'],
                        'price' => $item['price'],
                        'is_flash_sale' => false,
                        'custom_form_data' => $request->notes ? ['notes' => $request->notes] : null
                    ]);

                    // Adjust stock in db and record history
                    $this->productService->adjustStock(
                        $item['product_id'],
                        $item['variant_id'],
                        -$item['qty'],
                        'out',
                        "POS Order: {$invoiceNumber}"
                    );
                }

                // Create Payment record
                $paymentMethodLabel = 'POS - Uang Tunai';
                if ($request->payment_method === 'bank_transfer') {
                    $paymentMethodLabel = 'POS - Transfer Bank';
                } elseif ($request->payment_method === 'qris') {
                    $paymentMethodLabel = 'POS - QRIS';
                }

                Payment::create([
                    'order_id' => $order->id,
                    'payment_method' => $paymentMethodLabel,
                    'transaction_id' => 'POS-' . strtoupper(Str::random(10)),
                    'status' => 'settlement',
                    'raw_response' => json_encode([
                        'amount_paid' => $amountPaid,
                        'change_amount' => $changeAmount,
                        'payment_method' => $request->payment_method,
                        'notes' => $request->notes
                    ])
                ]);

                return response()->json([
                    'success' => true,
                    'message' => 'Transaksi POS berhasil diselesaikan.',
                    'order' => [
                        'id' => $order->id,
                        'invoice_number' => $order->invoice_number,
                        'total' => $grandTotal,
                        'subtotal' => $subtotal,
                        'discount' => $discount,
                        'tax' => $taxAmount,
                        'amount_paid' => $amountPaid,
                        'change' => $changeAmount,
                        'payment_method' => $request->payment_method,
                    ]
                ]);
            });
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => $e->getMessage()
            ], 422);
        }
    }

    /**
     * Get list of POS transactions history.
     */
    public function indexHistory(Request $request)
    {
        $this->checkAdmin();

        $query = Order::with(['user', 'payment', 'items.product'])
            ->where('shipping_address', 'like', 'POS In-Store Purchase%');

        if ($request->filled('search')) {
            $search = $request->search;
            $query->where(function ($q) use ($search) {
                $q->where('invoice_number', 'like', "%{$search}%")
                  ->orWhereHas('user', function($qu) use ($search) {
                      $qu->where('name', 'like', "%{$search}%");
                  });
            });
        }

        $history = $query->latest()->paginate(15);
        
        // Include payment details decoding
        $history->getCollection()->transform(function($order) {
            if ($order->payment && $order->payment->raw_response) {
                $order->payment_details = json_decode($order->payment->raw_response, true);
            } else {
                $order->payment_details = null;
            }
            return $order;
        });

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

    /**
     * Get thermal print settings.
     */
    public function getPrintSettings()
    {
        $this->checkAdmin();

        return response()->json([
            'pos_paper_width' => Setting::get('pos_paper_width', '76mm'),
            'pos_font_size' => Setting::get('pos_font_size', '12px'),
            'pos_printer_type' => Setting::get('pos_printer_type', 'standard'),
            'pos_receipt_header' => Setting::get('pos_receipt_header', ''),
            'pos_receipt_footer' => Setting::get('pos_receipt_footer', ''),
        ]);
    }

    /**
     * Save thermal print settings.
     */
    public function savePrintSettings(Request $request)
    {
        $this->checkAdmin();

        $request->validate([
            'pos_paper_width' => 'required|string|max:20',
            'pos_font_size' => 'required|string|max:20',
            'pos_printer_type' => 'required|string|in:standard,compact,bold',
            'pos_receipt_header' => 'nullable|string|max:500',
            'pos_receipt_footer' => 'nullable|string|max:500',
        ]);

        Setting::set('pos_paper_width', $request->pos_paper_width);
        Setting::set('pos_font_size', $request->pos_font_size);
        Setting::set('pos_printer_type', $request->pos_printer_type);
        Setting::set('pos_receipt_header', $request->pos_receipt_header ?? '');
        Setting::set('pos_receipt_footer', $request->pos_receipt_footer ?? '');

        return response()->json([
            'success' => true,
            'message' => 'Pengaturan printer thermal berhasil diperbarui.'
        ]);
    }
}
