<?php

declare(strict_types=1);

namespace App\Application\Http;

use App\Framework\Attributes\Route;
use App\Framework\CommandBus\CommandBus;
use App\Framework\Http\HeaderKey;
use App\Framework\Http\Method;
use App\Framework\Http\Request;
use App\Framework\Http\Status;
use App\Framework\MagicLinks\Actions\ActionRegistry;
use App\Framework\MagicLinks\Commands\ExecuteMagicLinkCommand;
use App\Framework\MagicLinks\Commands\GenerateMagicLinkCommand;
use App\Framework\MagicLinks\Commands\GenerateMagicLinkHandler;
use App\Framework\MagicLinks\MagicLinkToken;
use App\Framework\MagicLinks\Services\MagicLinkService;
use App\Framework\MagicLinks\TokenAction;
use App\Framework\Meta\MetaData;
use App\Framework\Router\ActionResult;
use App\Framework\Router\Result\Redirect;
use App\Framework\Router\Result\ViewResult;

final readonly class MagicLink
{
    public function __construct(
        private CommandBus $commandBus,
        private ActionRegistry $actionRegistry,
        private MagicLinkService $magiclinkService,
        private GenerateMagicLinkHandler $handler,
    ) {
    }

    #[Route('/magiclink/{token}', method: Method::GET)]
    #[Route('/magiclink/{token}', method: Method::POST)]
    public function execute(string $token, Request $request): ActionResult
    {
        $command = new GenerateMagicLinkCommand(
            action: new TokenAction('email_verification'),
            payload: ['user_id' => 123, 'email' => 'user@example.com'],
            baseUrl: 'https://localhost'
        );

        #debug($this->handler->handle($command));

        try {
            $magiclinkToken = new MagicLinkToken($token);

            // Token validieren
            $magiclinkData = $this->magiclinkService->validate($magiclinkToken);
            if (! $magiclinkData) {
                return new ViewResult(
                    template: 'magiclinks-error',
                    metaData: new MetaData(
                        title: 'Ungültiger Link',
                        description: 'Der Link ist ungültig oder abgelaufen'
                    ),
                    data: [
                        'error' => 'Ungültiger oder abgelaufener Link',
                        'error_code' => 'INVALID_TOKEN',
                    ],
                    status: Status::NOT_FOUND
                );
            }

            // Action holen
            $action = $this->actionRegistry->get($magiclinkData->action);
            if (! $action) {
                return new ViewResult(
                    template: 'magiclinks-error',
                    metaData: new MetaData(
                        title: 'Unbekannte Aktion',
                        description: 'Die angeforderte Aktion ist nicht verfügbar'
                    ),
                    data: [
                        'error' => 'Unbekannte Aktion',
                        'error_code' => 'UNKNOWN_ACTION',
                    ],
                    status: Status::BAD_REQUEST
                );
            }

            // Context für Action vorbereiten
            $context = [
                'request_method' => $request->method->value,
                'request_data' => $request->parsedBody ?? [],
                'query_params' => $request->queryParameters ?? [],
                #'ip_address' => $request->serverEnvironment->ipAddress?->value,
                'user_agent' => $request->headers->getFirst(HeaderKey::USER_AGENT),
                'headers' => $request->headers,
            ];

            // Command ausführen
            $command = new ExecuteMagicLinkCommand($magiclinkToken, $context);
            $result = $this->commandBus->dispatch($command);

            // Ergebnis verarbeiten
            if (! $result->isSuccess()) {
                return new ViewResult(
                    template: $action->getErrorTemplate(),
                    metaData: new MetaData(
                        title: 'Fehler bei Ausführung',
                        description: $result->message
                    ),
                    data: [
                        'error' => $result->message,
                        'errors' => $result->errors,
                        'action' => $action->getName(),
                    ],
                    status: Status::BAD_REQUEST
                );
            }

            // Redirect oder View
            if ($result->hasRedirect()) {
                return new Redirect($result->redirectUrl);
            }

            return new ViewResult(
                template: $action->getViewTemplate(),
                metaData: new MetaData(
                    title: $action->getName(),
                    description: $result->message
                ),
                data: [
                    'result' => $result,
                    'action' => $action->getName(),
                    'token' => $token,
                ]
            );

        } catch (\Exception $e) {
            return new ViewResult(
                template: 'magiclinks-error',
                metaData: new MetaData(
                    title: 'Systemfehler',
                    description: 'Ein unerwarteter Fehler ist aufgetreten'
                ),
                data: [
                    'error' => 'Ein Fehler ist aufgetreten',
                    'error_code' => 'SYSTEM_ERROR',
                    'debug_message' => $e->getMessage(), // Nur für Development
                ],
                status: Status::INTERNAL_SERVER_ERROR
            );
        }
    }
}
