<?php

namespace App\Http\Controllers;

use App\Http\Requests\CheckoutRequest;
use App\Models\Customer;
use App\Models\Product;
use App\Services\OrderService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Validation\ValidationException;

class PosController extends Controller
{
    public function create(Request $request)
    {
        return view('pos.create', [
            'products' => Product::query()->where('is_active', true)->orderBy('type')->orderBy('name')->get(),
            'customers' => Customer::query()->orderBy('name')->limit(50)->get(),
        ]);
    }

    public function store(CheckoutRequest $request, OrderService $orderService)
    {
        $order = $orderService->checkout($request->validated(), $request->user());

        return redirect()->route('orders.show', $order)->with('status', 'Transaksi berhasil dibuat.');
    }

    public function mobileIntake(Request $request)
    {
        $branchId = $request->user()->branch_id;

        return view('pos.mobile-intake', [
            'customers' => Customer::query()
                ->where(fn ($query) => $query->whereNull('branch_id')->orWhere('branch_id', $branchId))
                ->orderBy('name')
                ->limit(100)
                ->get(),
        ]);
    }

    public function mobileStore(Request $request, OrderService $orderService)
    {
        $items = collect($request->input('items', []))
            ->filter(fn ($item) => isset($item['quantity']) && (float) $item['quantity'] > 0)
            ->values()
            ->all();

        $request->merge(['items' => $items]);

        $data = $request->validate([
            'customer_mode' => ['required', 'in:existing,new,walkin'],
            'customer_id' => ['nullable', 'exists:customers,id'],
            'new_customer.name' => ['nullable', 'string', 'max:120'],
            'new_customer.phone' => ['nullable', 'string', 'max:30', 'unique:customers,phone'],
            'new_customer.address' => ['nullable', 'string', 'max:1000'],
            'estimated_done_at' => ['nullable', 'date'],
            'paid_amount' => ['nullable', 'numeric', 'min:0'],
            'delivery_fee' => ['nullable', 'numeric', 'min:0'],
            'payment_method' => ['nullable', 'in:cash,transfer,qris'],
            'note' => ['nullable', 'string', 'max:1000'],
            'items' => ['required', 'array', 'min:1'],
            'items.*.product_id' => ['required', 'exists:products,id'],
            'items.*.quantity' => ['required', 'numeric', 'min:0.001'],
            'items.*.discount' => ['nullable', 'numeric', 'min:0'],
            'items.*.staff_id' => ['nullable', 'exists:users,id'],
        ]);

        $customerId = $data['customer_id'] ?? null;

        if ($data['customer_mode'] === 'existing' && ! $customerId) {
            throw ValidationException::withMessages(['customer_id' => 'Pilih pelanggan terlebih dahulu.']);
        }

        if ($data['customer_mode'] === 'new') {
            $newCustomer = $data['new_customer'] ?? [];

            if (blank($newCustomer['name'] ?? null) || blank($newCustomer['phone'] ?? null)) {
                throw ValidationException::withMessages(['new_customer.name' => 'Nama dan nomor HP pelanggan baru wajib diisi.']);
            }

            $customer = Customer::query()->create([
                'branch_id' => $request->user()->branch_id,
                'name' => $newCustomer['name'],
                'phone' => $newCustomer['phone'],
                'address' => $newCustomer['address'] ?? null,
                'pin' => Hash::make('000000'),
            ]);
            $customerId = $customer->id;
        }

        if ($customerId) {
            $customer = Customer::query()->findOrFail($customerId);
            abort_unless($customer->branch_id === null || $request->user()->canAccessBranch((int) $customer->branch_id), 403);
        }

        $order = $orderService->checkout([
            'branch_id' => $request->user()->branch_id,
            'customer_id' => $customerId,
            'estimated_done_at' => $data['estimated_done_at'] ?? null,
            'delivery_fee' => $data['delivery_fee'] ?? 0,
            'paid_amount' => $data['paid_amount'] ?? 0,
            'payment_method' => $data['payment_method'] ?? 'cash',
            'note' => $data['note'] ?? null,
            'items' => array_map(fn ($item) => $item + ['staff_id' => $item['staff_id'] ?? $request->user()->id], $data['items']),
        ], $request->user());

        return redirect()->route('digital-forms.create', $order)->with('status', 'Nota dibuat. Lanjutkan foto evidence dan tanda tangan pelanggan.');
    }

    public function searchCustomers(Request $request)
    {
        $query = trim((string) $request->input('q'));

        if (mb_strlen($query) < 2) {
            return response()->json([]);
        }

        $branchId = $request->user()->branch_id;

        return Customer::query()
            ->select(['id', 'name', 'phone', 'address'])
            ->where(fn ($inner) => $inner->whereNull('branch_id')->orWhere('branch_id', $branchId))
            ->where(fn ($inner) => $inner
                ->where('name', 'like', "%{$query}%")
                ->orWhere('phone', 'like', "%{$query}%"))
            ->orderBy('name')
            ->limit(12)
            ->get()
            ->map(fn (Customer $customer) => [
                'id' => $customer->id,
                'name' => $customer->name,
                'phone' => $customer->phone,
                'address' => $customer->address,
                'label' => trim($customer->name.' - '.$customer->phone),
            ]);
    }

    public function searchProducts(Request $request)
    {
        $query = trim((string) $request->input('q'));

        if (mb_strlen($query) < 2) {
            return response()->json([]);
        }

        return Product::query()
            ->select(['id', 'name', 'sku', 'type', 'unit', 'price', 'track_stock'])
            ->where('is_active', true)
            ->where(fn ($inner) => $inner
                ->where('name', 'like', "%{$query}%")
                ->orWhere('sku', 'like', "%{$query}%")
                ->orWhere('type', 'like', "%{$query}%"))
            ->orderBy('type')
            ->orderBy('name')
            ->limit(15)
            ->get()
            ->map(fn (Product $product) => [
                'id' => $product->id,
                'name' => $product->name,
                'sku' => $product->sku,
                'type' => $product->type,
                'unit' => $product->unit,
                'price' => (float) $product->price,
                'track_stock' => (bool) $product->track_stock,
                'label' => trim($product->name.' - '.$product->sku),
            ]);
    }

    public function quickCustomer(Request $request)
    {
        $data = $request->validate([
            'name' => ['required', 'string', 'max:120'],
            'phone' => ['required', 'string', 'max:30', 'unique:customers,phone'],
            'address' => ['nullable', 'string', 'max:1000'],
        ]);

        $customer = Customer::query()->create($data + [
            'branch_id' => $request->user()->branch_id,
            'pin' => bcrypt('000000'),
        ]);

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