<?php

namespace App\Services;

use App\Models\Purchase;
use App\Models\PurchaseItem;
use App\Models\PurchaseReturn;
use App\Models\PurchaseReturnItem;
use App\Models\ProductStock;
use App\Models\User;
use Illuminate\Support\Facades\DB;

class PurchaseReturnService
{
    /**
     * Create a purchase return in pending status.
     * Inventory is NOT yet deducted at this stage.
     */
    public function create(array $data, User $user): PurchaseReturn
    {
        return DB::transaction(function () use ($data, $user) {
            $purchase = Purchase::with('items.product')->findOrFail($data['purchase_id']);

            if ($purchase->status !== 'received') {
                throw new \Exception('Only received purchases can be returned.');
            }

            // Build validated items and calculate total
            $totalAmount = 0;
            $resolvedItems = [];

            foreach ($data['items'] as $item) {
                $purchaseItem = $purchase->items()->where('id', $item['purchase_item_id'])->first();

                if (! $purchaseItem) {
                    throw new \Exception("Item #{$item['purchase_item_id']} does not belong to this purchase.");
                }

                // Validate that the requested return qty doesn't exceed original purchase qty
                if ($item['quantity'] > $purchaseItem->quantity) {
                    throw new \Exception(
                        "Return quantity ({$item['quantity']}) exceeds purchased quantity ({$purchaseItem->quantity}) for '{$purchaseItem->product->name}'."
                    );
                }

                $subtotal     = $purchaseItem->unit_cost * $item['quantity'];
                $totalAmount += $subtotal;

                $resolvedItems[] = [
                    'purchase_item_id' => $purchaseItem->id,
                    'product_id'       => $purchaseItem->product_id,
                    'quantity'         => $item['quantity'],
                    'unit_cost'        => $purchaseItem->unit_cost,
                    'subtotal'         => $subtotal,
                    'reason'           => $item['reason'] ?? null,
                ];
            }

            $purchaseReturn = PurchaseReturn::create([
                'return_number' => $this->generateReturnNumber(),
                'purchase_id'   => $purchase->id,
                'supplier_id'   => $purchase->supplier_id,
                'user_id'       => $user->id,
                'total_amount'  => $totalAmount,
                'status'        => 'pending',
                'reason'        => $data['reason'],
                'notes'         => $data['notes'] ?? null,
                'branch_id'     => $purchase->branch_id,
            ]);

            foreach ($resolvedItems as $item) {
                PurchaseReturnItem::create(array_merge($item, [
                    'purchase_return_id' => $purchaseReturn->id,
                    'branch_id'          => $purchase->branch_id,
                ]));
            }

            return $purchaseReturn->load('items.product', 'supplier', 'purchase');
        });
    }

    /**
     * Complete a purchase return: deduct items from inventory.
     */
    public function complete(PurchaseReturn $purchaseReturn): PurchaseReturn
    {
        if ($purchaseReturn->status !== 'pending') {
            throw new \Exception('Only pending purchase returns can be completed.');
        }

        return DB::transaction(function () use ($purchaseReturn) {
            $purchaseReturn->load('items.product');

            $branchId = $purchaseReturn->branch_id;

            foreach ($purchaseReturn->items as $item) {
                $product = $item->product;

                // Deduct from branch-level ProductStock
                if ($branchId) {
                    ProductStock::deductStock(
                        $product->id,
                        $branchId,
                        $item->quantity,
                        $product->name
                    );
                }

                // Deduct from global product stock_quantity
                $product->decrement('stock_quantity', $item->quantity);
            }

            $purchaseReturn->update([
                'status'       => 'completed',
                'completed_at' => now(),
            ]);

            return $purchaseReturn->fresh();
        });
    }

    /**
     * Cancel a pending purchase return.
     */
    public function cancel(PurchaseReturn $purchaseReturn): PurchaseReturn
    {
        if ($purchaseReturn->status !== 'pending') {
            throw new \Exception('Only pending purchase returns can be cancelled.');
        }

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

        return $purchaseReturn->fresh();
    }

    protected function generateReturnNumber(): string
    {
        $prefix = 'PRN';
        $date   = now()->format('Ymd');
        $count  = PurchaseReturn::whereDate('created_at', today())->count() + 1;

        return $prefix . $date . str_pad($count, 4, '0', STR_PAD_LEFT);
    }
}
