<?php

declare(strict_types=1);

namespace apexl\Io\modules\product\Controller;

use apexl\Io\includes\Controller;
use apexl\Io\interfaces\OutputManagerInterface;
use apexl\Io\modules\product\Entity\Product;
use apexl\Io\modules\product\Service\ProductService;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;

/**
 * REST surface for catalogue products (V3). Routes gate on
 * ProductPermission (view for reads, manage for writes).
 */
final readonly class ProductController extends Controller
{
    public function __construct(
        private ProductService $products,
        OutputManagerInterface $output,
    ) {
        parent::__construct($output);
    }

    public function index(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface
    {
        $active = !empty($request->getQueryParams()['active']);
        $list   = $active ? $this->products->listActive() : $this->products->list();
        return $this->json($response, [
            'products' => array_map(fn(Product $p) => $this->products->serialise($p), $list),
            'kinds'    => ProductService::KINDS,
        ]);
    }

    public function get(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface
    {
        $p = $this->products->find((int) $request->getAttribute('id'));
        if ($p === null) return $this->json($response, ['error' => 'Product not found'], 404);
        return $this->json($response, ['product' => $this->products->serialise($p)]);
    }

    public function create(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface
    {
        try {
            $p = $this->products->create((array) ($request->getParsedBody() ?? []));
        } catch (\InvalidArgumentException $e) {
            return $this->json($response, ['error' => $e->getMessage()], 400);
        }
        return $this->json($response, [
            'product'  => $this->products->serialise($p),
            'messages' => [['type' => 'success', 'content' => 'Product created.']],
        ]);
    }

    public function update(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface
    {
        $p = $this->products->find((int) $request->getAttribute('id'));
        if ($p === null) return $this->json($response, ['error' => 'Product not found'], 404);
        try {
            $this->products->update($p, (array) ($request->getParsedBody() ?? []));
        } catch (\InvalidArgumentException $e) {
            return $this->json($response, ['error' => $e->getMessage()], 400);
        }
        return $this->json($response, [
            'product'  => $this->products->serialise($p),
            'messages' => [['type' => 'success', 'content' => 'Product saved.']],
        ]);
    }

    public function delete(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface
    {
        $p = $this->products->find((int) $request->getAttribute('id'));
        if ($p === null) return $this->json($response, ['error' => 'Product not found'], 404);
        $this->products->delete($p);
        return $this->json($response, ['messages' => [['type' => 'success', 'content' => 'Product deleted.']]]);
    }
}
