<?php

namespace App\Http\Controllers\Admin;

use App\Actions\Inventory\ExportBatches;
use App\Http\Controllers\Controller;
use App\Models\Product;
use App\Models\ProductBatch;
use App\Models\Store;
use Illuminate\Http\Request;
use Illuminate\View\View;
use Symfony\Component\HttpFoundation\StreamedResponse;

/**
 * Product Batches admin — read-only list of every batch the inventory
 * module knows about. Batches themselves are created/incremented via
 * `ReceivePurchase` and decremented via `RecordStockMovement`; this
 * controller is the visibility surface for owners + pharmacists:
 *
 *   - which batches are live (qty > 0)
 *   - which are expiring soon (configurable window, default 30 days)
 *   - which are expired (and therefore non-sellable when the
 *     `block_expired_batch_sale` company setting is on)
 *
 * Permission: `products.view` — same as the stock-levels page.
 */
class ProductBatchController extends Controller
{
    public function index(Request $request): View
    {
        $this->authorize('viewAny', Product::class);

        $storeId   = enforce_store_access($request->integer('store_id') ?: null);
        $productId = $request->integer('product_id') ?: null;
        $status    = (string) $request->query('status', '');
        $days      = (int) $request->query('days', 30);
        if ($days <= 0 || $days > 365) $days = 30;
        $q = trim((string) $request->query('q', ''));

        $query = ProductBatch::query()
            ->with(['store:id,name', 'product:id,sku,name', 'variant:id,sku'])
            ->when($storeId,   fn ($qb) => $qb->where('store_id',   $storeId))
            ->when($productId, fn ($qb) => $qb->where('product_id', $productId))
            ->when($q !== '', fn ($qb) => $qb->where(function ($w) use ($q) {
                $w->where('batch_number', 'like', "%{$q}%")
                  ->orWhereHas('product', fn ($p) => $p->where('name', 'like', "%{$q}%")->orWhere('sku', 'like', "%{$q}%"));
            }))
            // Nulls (no expiry) last; nearest expiry first.
            ->orderByRaw('expiry_date IS NULL')
            ->orderBy('expiry_date')
            ->orderBy('id');

        if ($status === 'live')          $query->live();
        if ($status === 'expiring_soon') $query->expiringWithin($days);
        if ($status === 'expired')       $query->expired();

        $batches = $query->limit(500)->get();

        // Counters for the status tabs — driven by the same query
        // shape (minus the status filter) so the user sees up-to-date
        // tallies when they switch filters.
        $base = ProductBatch::query()
            ->when($storeId,   fn ($qb) => $qb->where('store_id',   $storeId))
            ->when($productId, fn ($qb) => $qb->where('product_id', $productId));

        $counts = [
            'all'           => (clone $base)->count(),
            'live'          => (clone $base)->live()->count(),
            'expiring_soon' => (clone $base)->expiringWithin($days)->count(),
            'expired'       => (clone $base)->expired()->count(),
        ];

        $summaryCards = [
            ['label' => __('batches.summary.total'),         'value' => number_format($counts['all'])],
            ['label' => __('batches.summary.expiring_soon'), 'value' => number_format($counts['expiring_soon']), 'tone' => 'warning'],
            ['label' => __('batches.summary.expired'),       'value' => number_format($counts['expired']), 'tone' => 'danger'],
        ];

        return view('admin.inventory.batches.index', [
            'batches'      => $batches,
            'summaryCards' => $summaryCards,
            'stores'       => accessible_stores(),
            'counts'       => $counts,
            'filters'      => compact('storeId', 'productId', 'status', 'days', 'q'),
        ]);
    }

    public function export(Request $request, ExportBatches $export): StreamedResponse
    {
        $this->authorize('viewAny', Product::class);

        return $export([
            'store_id'   => enforce_store_access($request->integer('store_id') ?: null),
            'product_id' => $request->integer('product_id') ?: null,
            'status'     => (string) $request->query('status', ''),
            'days'       => (int) $request->query('days', 30),
            'format'     => (string) $request->query('format', 'csv'),
        ]);
    }
}
