<?php

namespace App\Http\Controllers;

use App\Core\Request;
use App\Core\Response;
use App\Domain\Services\AuthService;
use App\Domain\Services\TokenService;
use App\Exceptions\ValidationException;
use App\Http\Requests\LoginRequest;
use App\Http\Requests\RefreshTokenRequest;
use App\Http\Requests\RegisterRequest;
use App\Http\Responses\ApiResponse;

class AuthController
{
    public function __construct(
        private AuthService $auth,
        private TokenService $tokens
    ) {
    }

    public function register(Request $request): Response
    {
        $result = $this->auth->register(RegisterRequest::validate($request));
        return $this->compat($result + ['message' => 'Registration successful'], 201);
    }

    public function login(Request $request): Response
    {
        $data = LoginRequest::validate($request);
        $result = $this->auth->login($data['email'], $data['password']);
        $tokens = $result['tokens'];

        return $this->compat([
            'message' => 'Login successful',
            'user' => $result['user'],
            'token' => $tokens['token'],
            'access_token' => $tokens['access_token'],
            'refresh_token' => $tokens['refresh_token'],
            'token_type' => $tokens['token_type'],
            'expires_in' => $tokens['expires_in'],
        ]);
    }

    public function refresh(Request $request): Response
    {
        $data = RefreshTokenRequest::validate($request);
        return ApiResponse::success($this->tokens->refresh($data['refresh_token']));
    }

    public function logout(Request $request): Response
    {
        $token = $request->attribute('token') ?? $request->bearerToken();
        if (!$token) {
            throw new ValidationException('Bearer token is required');
        }

        $this->tokens->revoke($token);
        return ApiResponse::success(null, 200, 'Logout successful');
    }

    public function validateToken(Request $request): Response
    {
        $token = $request->input('token') ?: $request->bearerToken();
        if (!$token) {
            throw new ValidationException('Token is required');
        }

        $decoded = $this->tokens->validate($token);
        return $this->compat([
            'message' => 'Token is valid',
            'valid' => true,
            'claims' => json_decode(json_encode($decoded), true),
        ]);
    }

    public function publicKey(Request $request): Response
    {
        return ApiResponse::success(['public_key' => $this->tokens->publicKey()]);
    }

    public function jwks(Request $request): Response
    {
        return Response::json($this->tokens->jwks());
    }

    private function compat(array $data, int $status = 200): Response
    {
        return Response::json($data + ['success' => $status >= 200 && $status < 300], $status);
    }
}
