<?php

// SPDX-FileCopyrightText: 2025 Icinga GmbH <https://icinga.com>
// SPDX-License-Identifier: GPL-3.0-or-later

namespace Icinga\Module\Notifications\Api;

use GuzzleHttp\Psr7\Response;
use Icinga\Module\Notifications\Common\HttpMethod;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\StreamInterface;

/**
 * Abstract base class for API endpoints.
 *
 * This class provides the base functionality for handling API requests.
 *
 * @internal
 */
abstract class ApiCore
{
    /**
     * Endpoint-based request handling.
     *
     * @param ServerRequestInterface $request
     *
     * @return ResponseInterface
     */
    abstract protected function handleRequest(ServerRequestInterface $request): ResponseInterface;

    /**
     * Get the name of the API endpoint.
     *
     * @return string
     */
    abstract public function getEndpoint(): string;

    /**
     * The main entry point for processing API requests.
     *
     * @param ServerRequestInterface $request The incoming server request.
     *
     * @return ResponseInterface The response generated by the invoked method.
     */
    public function handle(ServerRequestInterface $request): ResponseInterface
    {
        $this->assertValidRequest($request);

        return $this->handleRequest($request);
    }

    /**
     * Get allowed HTTP methods for the API.
     *
     * @return array
     */
    public function getAllowedMethods(): array
    {
        $methods = [];

        foreach (HttpMethod::cases() as $method) {
            if (method_exists($this, $method->lowercase())) {
                $methods[] = $method->uppercase();
            }
        }

        return $methods;
    }

    /**
     * Validate the incoming request.
     *
     * Override to implement specific request validation logic.
     *
     * @param ServerRequestInterface $request The incoming server-request to validate.
     *
     * @return void
     */
    protected function assertValidRequest(ServerRequestInterface $request): void
    {
    }

    /**
     * Create a Response object.
     *
     * @param int $status The HTTP status code.
     * @param array $headers An associative array of HTTP headers.
     * @param ?(StreamInterface|resource|string) $body The response body.
     * @param string $version The HTTP version.
     * @param ?string $reason The reason phrase (optional).
     *
     * @return ResponseInterface
     */
    protected function createResponse(
        int $status = 200,
        array $headers = [],
        $body = null,
        string $version = '1.1',
        ?string $reason = null
    ): ResponseInterface {
        $headers['Content-Type'] = 'application/json';

        return new Response($status, $headers, $body, $version, $reason);
    }
}
