<?php

namespace App\Http\Controllers;

use App\Models\Catalog\Product;
use App\Models\Inventory\BarcodeLabel;
use App\Support\BarcodeGenerator;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Symfony\Component\HttpFoundation\Response as SymfonyResponse;

/**
 * Renders a product's barcode as an image.
 *
 * A bare controller rather than a Filament page/action because the barcode
 * grid thumbnails in the Products table and the "View Barcode" modal both hot-
 * link images off this endpoint, and an authenticated Filament request is not
 * the right shape for an <img src>. The route is auth-guarded (see web.php),
 * so the same cookies the panel uses keep it private.
 *
 * The value rendered is the product's barcode when set, falling back to its
 * SKU (every product is auto-assigned a SKU at creation, so every row can show
 * a scannable code). ?download=1 returns Content-Disposition: attachment for
 * the "Download barcode" action.
 */
class BarcodeController extends Controller
{
    public const FORMATS = ['png', 'svg'];

    public function show(mixed $product, mixed $format, Request $request): Response
    {
        // With path tenancy the {workspace} prefix parameter is the first
        // route parameter and the dispatcher assigns method arguments
        // positionally, so typed model parameters receive the workspace slug.
        // Untyped on purpose; resolved through the tenant-scoped query below
        // (docs/path-based-tenancy-plan.md Phase 4).
        $product = Product::query()->findOrFail((int) $request->route('product'));
        $format = (string) ($request->route('format') ?? 'svg');

        $value = $product->barcode ?: $product->sku;

        if (blank($value)) {
            abort(SymfonyResponse::HTTP_NOT_FOUND, 'This product has no barcode value to render.');
        }

        return $this->render($value, $format, $request);
    }

    /**
     * The same image for a label the shop printed itself — its own code, not
     * the product's, because that code is what carries the lot, the serial and
     * the quantity through a scan.
     */
    public function label(mixed $barcodeLabel, mixed $format, Request $request): Response
    {
        // Same positional-dispatcher note as show().
        $barcodeLabel = BarcodeLabel::query()->findOrFail((int) $request->route('barcodeLabel'));

        return $this->render($barcodeLabel->code, (string) ($request->route('format') ?? 'svg'), $request);
    }

    private function render(string $value, string $format, Request $request): Response
    {
        $rendered = app(BarcodeGenerator::class)->render($value, $format);

        $headers = [
            'Content-Type' => $rendered['content-type'],
            'Cache-Control' => 'public, max-age=86400',
        ];

        if ($request->query->has('download')) {
            $filename = 'barcode-'.preg_replace('/[^A-Za-z0-9_-]+/', '-', $value).'.'.$format;
            $headers['Content-Disposition'] = 'attachment; filename="'.$filename.'"';
        }

        return response($rendered['bytes'], SymfonyResponse::HTTP_OK, $headers);
    }
}
