<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Models\Branch;
use App\Models\CashierShift;
use App\Models\Coupon;
use App\Models\GiftCard;
use App\Models\Product;
use App\Models\Sale;
use App\Models\SaleHold;
use App\Models\SaleMeta;
use App\Models\SalePayment;
use App\Services\SaleService;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;

class SaleController extends Controller
{
    public function __construct(private SaleService $saleService)
    {
    }

    public function index(Request $request): View
    {
        $q = Sale::query();
        if ($request->filled('type')) {
            $invoiceNos = SaleMeta::where('document_type', $request->type)->pluck('invoice_no');
            $q->whereIn('invoice_no', $invoiceNos);
        }
        $sales = $q->latest('id')->paginate(30);
        return view('admin.sales.index', compact('sales'));
    }

    public function create(Request $request): View
    {
        $products = Product::orderBy('product_name')->get();
        $hold = null;
        if ($request->filled('hold_id')) {
            $hold = SaleHold::where('status', 'Active')->find($request->integer('hold_id'));
        }
        return view('admin.sales.form', [
            'products' => $products,
            'invoice' => null,
            'coupons' => Coupon::where('status','Active')->orderBy('code')->get(),
            'giftCards' => GiftCard::where('status','Active')->orderBy('code')->get(),
            'openShift' => CashierShift::where('admin_id', session('admin_id'))->where('status','Open')->latest('id')->first(),
            'hold' => $hold,
            'branches' => Branch::orderBy('name')->get(),
        ]);
    }

    public function store(Request $request): RedirectResponse
    {
        $validated = $this->validated($request);
        if (($validated['document_type'] ?? 'Invoice') === 'Hold' || ($validated['sale_status'] ?? null) === 'Suspended') {
            $hold = SaleHold::create([
                'hold_no' => 'HLD-' . now()->format('YmdHis'),
                'hold_type' => $validated['document_type'] ?? 'Hold',
                'customer_name' => $validated['customer_name'] ?? null,
                'customer_phone' => $validated['customer_phone'] ?? null,
                'customer_address' => $validated['customer_address'] ?? null,
                'payload' => $validated,
                'status' => 'Active',
            ]);
            return redirect()->route('admin.sales.holds')->with('success', 'Sale parked successfully. Hold no: '.$hold->hold_no);
        }

        $invoiceNo = $this->saleService->store($validated);

        if (!empty($validated['hold_id'])) {
            SaleHold::where('id', $validated['hold_id'])->where('status', 'Active')->update(['status' => 'Released']);
        }

        return redirect()->route('admin.sales.invoice', Sale::where('invoice_no', $invoiceNo)->firstOrFail())
            ->with('success', ($validated['document_type'] ?? 'Invoice').' saved. Invoice: ' . $invoiceNo);
    }

    public function invoice(Sale $sale): View
    {
        $invoiceNo = $sale->invoice_no;
        $sales = Sale::where('invoice_no', $invoiceNo)->orderBy('id')->get();
        $summary = $sales->first();
        $meta = SaleMeta::where('invoice_no', $invoiceNo)->first();
        $payments = SalePayment::where('invoice_no', $invoiceNo)->get();
        abort_if(!$summary, 404);
        return view('admin.sales.invoice', compact('sales', 'invoiceNo', 'summary', 'meta', 'payments'));
    }

    public function edit(string $invoiceNo): View
    {
        $products = Product::orderBy('product_name')->get();
        $sales = Sale::where('invoice_no', $invoiceNo)->orderBy('id')->get();
        $invoice = $sales->first();
        abort_if(!$invoice, 404);
        $invoice->setRelation('lines', $sales);
        $meta = SaleMeta::where('invoice_no', $invoiceNo)->first();
        $payments = SalePayment::where('invoice_no', $invoiceNo)->get();
        return view('admin.sales.form', [
            'products' => $products,
            'invoice' => $invoice,
            'meta' => $meta,
            'payments' => $payments,
            'coupons' => Coupon::where('status','Active')->orderBy('code')->get(),
            'giftCards' => GiftCard::where('status','Active')->orderBy('code')->get(),
            'openShift' => CashierShift::where('admin_id', session('admin_id'))->where('status','Open')->latest('id')->first(),
            'hold' => null,
            'branches' => Branch::orderBy('name')->get(),
        ]);
    }

    public function update(Request $request, string $invoiceNo): RedirectResponse
    {
        $validated = $this->validated($request);
        $invoice = Sale::where('invoice_no', $invoiceNo)->first();
        abort_if(!$invoice, 404);
        $this->saleService->updateInvoice($invoiceNo, $validated);
        return redirect()->route('admin.sales.invoice', Sale::where('invoice_no', $invoiceNo)->firstOrFail())->with('success', 'Invoice updated successfully.');
    }

    public function destroy(string $invoiceNo): RedirectResponse
    {
        abort_if(Sale::where('invoice_no', $invoiceNo)->doesntExist(), 404);
        $this->saleService->deleteInvoice($invoiceNo);

        return redirect()->route('admin.sales.index')->with('success', 'Invoice deleted successfully.');
    }

    public function holds(): View
    {
        $holds = SaleHold::latest('id')->paginate(20);
        return view('admin.sales.holds', compact('holds'));
    }

    public function releaseHold(SaleHold $hold): RedirectResponse
    {
        abort_if($hold->status !== 'Active', 404);

        return redirect()->route('admin.sales.create', ['hold_id' => $hold->id]);
    }

    public function removeHold(SaleHold $hold): RedirectResponse
    {
        $hold->delete();
        return back()->with('success', 'Hold deleted successfully.');
    }

    public function shifts(Request $request)
    {
        if ($request->isMethod('post')) {
            $data = $request->validate([
                'action' => ['required','in:open,close'],
                'opening_cash' => ['nullable','numeric','min:0'],
                'closing_cash' => ['nullable','numeric','min:0'],
                'notes' => ['nullable','string'],
            ]);
            $adminId = session('admin_id');
            if ($data['action'] === 'open') {
                CashierShift::updateOrCreate(
                    ['admin_id' => $adminId, 'status' => 'Open'],
                    ['shift_no' => 'SFT-'.now()->format('YmdHis'), 'opened_at' => now(), 'opening_cash' => $data['opening_cash'] ?? 0, 'notes' => $data['notes'] ?? null]
                );
            } else {
                $open = CashierShift::where('admin_id', $adminId)->where('status','Open')->latest('id')->first();
                if ($open) $open->update(['closed_at' => now(), 'closing_cash' => $data['closing_cash'] ?? 0, 'status' => 'Closed', 'notes' => trim(($open->notes ? $open->notes."\n" : '').($data['notes'] ?? ''))]);
            }
            return back()->with('success', 'Shift updated successfully.');
        }
        $shifts = CashierShift::latest('id')->paginate(20);
        $openShift = CashierShift::where('admin_id', session('admin_id'))->where('status','Open')->latest('id')->first();
        return view('admin.sales.shifts', compact('shifts','openShift'));
    }

    private function validated(Request $request): array
    {
        return $request->validate([
            'customer_name' => ['nullable', 'string', 'max:100'],
            'customer_phone' => ['nullable', 'string', 'max:20'],
            'customer_address' => ['nullable', 'string', 'max:255'],
            'branch_id' => ['nullable','integer'],
            'hold_id' => ['nullable', 'integer', 'exists:sale_holds,id'],
            'customer_group' => ['nullable', 'string', 'max:40'],
            'sale_date' => ['nullable', 'date'],
            'payment_method' => ['nullable', 'in:Cash,Bank,Mobile Banking,Card,Due,bKash,Nagad,Rocket'],
            'paid_amount' => ['nullable', 'numeric', 'min:0'],
            'invoice_discount' => ['nullable', 'numeric', 'min:0'],
            'tax_percent' => ['nullable', 'numeric', 'min:0'],
            'coupon_code' => ['nullable', 'string', 'max:60'],
            'gift_card_code' => ['nullable', 'string', 'max:60'],
            'bundle_discount' => ['nullable', 'numeric', 'min:0'],
            'bogo_discount' => ['nullable', 'numeric', 'min:0'],
            'time_discount' => ['nullable', 'numeric', 'min:0'],
            'document_type' => ['nullable', 'in:Invoice,Quotation,Draft,Hold'],
            'sale_status' => ['nullable', 'in:Completed,Suspended,Draft,Quotation'],
            'approval_status' => ['nullable', 'in:Approved,Pending'],
            'refund_status' => ['nullable', 'in:N/A,Pending,Approved'],
            'exchange_status' => ['nullable', 'in:N/A,Pending,Completed'],
            'cashier_shift_id' => ['nullable', 'integer'],
            'delivery_charge' => ['nullable', 'numeric', 'min:0'],
            'courier_partner' => ['nullable', 'string', 'max:50'],
            'courier_tracking_no' => ['nullable', 'string', 'max:100'],
            'courier_status' => ['nullable', 'string', 'max:30'],
            'area_name' => ['nullable', 'string', 'max:80'],
            'language_mode' => ['nullable', 'in:English,Bangla'],
            'split_payment_method' => ['nullable', 'array'],
            'split_payment_amount' => ['nullable', 'array'],
            'split_gateway_name' => ['nullable', 'array'],
            'split_gateway_reference' => ['nullable', 'array'],
            'rows' => ['required', 'array', 'min:1'],
            'rows.*.product_id' => ['required', 'exists:products,id'],
            'rows.*.quantity_sold' => ['required', 'numeric', 'min:0.01'],
            'rows.*.selling_price' => ['required', 'numeric', 'min:0'],
            'rows.*.discount' => ['nullable', 'numeric', 'min:0'],
        ]);
    }
}
