<?php
namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Models\Product;
use App\Models\Sale;
use App\Models\SaleReturn;
use App\Models\SaleReturnItem;
use App\Models\StockMovement;
use App\Support\InventoryConsistency;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\View\View;

class SaleReturnController extends Controller
{
    public function index(): View
    {
        $returns = SaleReturn::withCount('items')->latest('id')->paginate(25);
        return view('admin.returns.sale_index', compact('returns'));
    }

    public function create(): View
    {
        $sales = Sale::query()->select('id', 'invoice_no', 'product_name', 'product_code', 'customer_name', 'quantity_sold', 'selling_price')
            ->latest('id')->limit(200)->get();
        return view('admin.returns.sale_form', compact('sales'));
    }

    public function store(Request $request): RedirectResponse
    {
        $data = $request->validate([
            'customer_name' => ['required', 'string', 'max:100'],
            'customer_phone' => ['nullable', 'string', 'max:20'],
            'customer_address' => ['nullable', 'string', 'max:255'],
            'return_date' => ['required', 'date'],
            'refund_method' => ['required', 'in:Cash,Bank,Mobile Banking,Adjustment'],
            'notes' => ['nullable', 'string'],
            'rows' => ['required', 'array', 'min:1'],
            'rows.*.sale_id' => ['nullable', 'exists:sales,id'],
            'rows.*.qty' => ['nullable', 'numeric', 'min:0.01'],
            'rows.*.restock' => ['nullable', 'boolean'],
        ]);

        $rows = collect($data['rows'])->filter(fn ($row) => !empty($row['sale_id']) && !empty($row['qty']));
        abort_if($rows->isEmpty(), 422, 'At least one return item is required.');

        DB::transaction(function () use ($data, $rows) {
            $return = SaleReturn::create([
                'return_no' => 'SR' . now()->format('YmdHis') . random_int(10, 99),
                'invoice_no' => Sale::find($rows->first()['sale_id'])->invoice_no,
                'customer_name' => $data['customer_name'],
                'customer_phone' => $data['customer_phone'] ?? null,
                'customer_address' => $data['customer_address'] ?? null,
                'return_date' => $data['return_date'],
                'notes' => $data['notes'] ?? null,
                'refund_method' => $data['refund_method'],
                'refund_total' => 0,
            ]);

            $refundTotal = 0;
            foreach ($rows as $row) {
                $sale = Sale::lockForUpdate()->findOrFail($row['sale_id']);
                $alreadyReturned = InventoryConsistency::totalPreviouslyReturnedForSale((int) $sale->id);
                $availableQty = max(0, (float) $sale->quantity_sold - $alreadyReturned);
                abort_if($availableQty <= 0, 422, $sale->product_name . ' has no returnable quantity left.');
                $qty = min((float) $row['qty'], $availableQty);
                $unitFactor = max(1, (int) ($sale->unit_factor ?? 1));
                $qtyInBase = (int) round($qty * $unitFactor);
                $lineTotal = $qty * (float) $sale->selling_price;
                $refundTotal += $lineTotal;

                SaleReturnItem::create([
                    'sale_return_id' => $return->id,
                    'sale_id' => $sale->id,
                    'product_id' => $sale->product_id,
                    'product_code' => $sale->product_code,
                    'product_name' => $sale->product_name,
                    'color' => $sale->color,
                    'qty' => $qty,
                    'qty_in_base' => $qtyInBase,
                    'entered_unit' => $sale->sale_unit ?: 'pcs',
                    'unit_factor' => $unitFactor,
                    'unit_price' => $sale->selling_price,
                    'discount' => 0,
                    'line_total' => $lineTotal,
                    'restock' => (bool) ($row['restock'] ?? true),
                ]);

                if (!empty($row['restock']) && $sale->product_id) {
                    $product = Product::find($sale->product_id);
                    if ($product) {
                        $product->increment('stock_quantity', $qtyInBase);
                        StockMovement::create([
                            'product_id' => $product->id,
                            'product_code' => $product->product_code,
                            'product_name' => $product->product_name,
                            'movement_type' => 'sale_return',
                            'reference_no' => $return->return_no,
                            'qty' => $qtyInBase,
                            'unit_price' => $sale->selling_price,
                            'notes' => 'Customer return restock',
                        ]);
                    }
                }
            }

            $return->update(['refund_total' => $refundTotal]);
        });

        return redirect()->route('admin.sale-returns.index')->with('success', 'Customer return added successfully.');
    }

    public function show(SaleReturn $saleReturn): View
    {
        $saleReturn->load('items');
        return view('admin.returns.sale_show', compact('saleReturn'));
    }

    public function destroy(SaleReturn $saleReturn): RedirectResponse
    {
        $saleReturn->load('items');

        DB::transaction(function () use ($saleReturn) {
            StockMovement::where('reference_no', $saleReturn->return_no)->where('movement_type', 'sale_return')->delete();
            foreach ($saleReturn->items as $item) {
                if ($item->restock && $item->product_id) {
                    $product = Product::find($item->product_id);
                    if ($product) {
                        $qtyInBase = (int) ($item->qty_in_base ?? $item->qty);
                        abort_if((int) $product->stock_quantity < $qtyInBase, 422, $product->product_name . ' stock is too low to reverse this customer return.');
                        $product->decrement('stock_quantity', $qtyInBase);
                        StockMovement::create([
                            'product_id' => $product->id,
                            'product_code' => $product->product_code,
                            'product_name' => $product->product_name,
                            'movement_type' => 'sale_return_delete',
                            'reference_no' => $saleReturn->return_no,
                            'qty' => -((int) ($item->qty_in_base ?? $item->qty)),
                            'unit_price' => (float) $item->unit_price,
                            'notes' => 'Customer return deleted stock reverse',
                        ]);
                    }
                }
                $item->delete();
            }

            $saleReturn->delete();
        });

        return redirect()->route('admin.sale-returns.index')->with('success', 'Customer return deleted successfully.');
    }
}
