<?php

declare(strict_types=1);

namespace App\Controllers;

use App\Repositories\UsuarioRepository;
use App\Services\JwtService;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;

class AuthController
{
    private UsuarioRepository $usuarios;
    private JwtService $jwt;

    public function __construct(UsuarioRepository $usuarios, JwtService $jwt)
    {
        $this->usuarios = $usuarios;
        $this->jwt = $jwt;
    }

    public function login(Request $request, Response $response): Response
    {
        $body = (array) $request->getParsedBody();
        $email = trim((string) ($body['email'] ?? ''));
        $password = (string) ($body['password'] ?? '');

        if ($email === '' || $password === '') {
            return $this->json($response, ['error' => 'email y password son requeridos'], 422);
        }

        $usuario = $this->usuarios->buscarPorEmail($email);

        if (!$usuario || !password_verify($password, $usuario['password_hash'])) {
            return $this->json($response, ['error' => 'Credenciales inválidas'], 401);
        }

        $accessToken = $this->jwt->issueAccessToken((int) $usuario['id'], $usuario['rol']);
        $refreshToken = $this->jwt->issueRefreshToken((int) $usuario['id']);

        return $this->json($response, [
            'access_token' => $accessToken,
            'refresh_token' => $refreshToken,
            'usuario' => [
                'id' => (int) $usuario['id'],
                'nombre' => $usuario['nombre'],
                'email' => $usuario['email'],
                'rol' => $usuario['rol'],
            ],
        ]);
    }

    public function refresh(Request $request, Response $response): Response
    {
        $body = (array) $request->getParsedBody();
        $refreshToken = (string) ($body['refresh_token'] ?? '');

        try {
            $payload = $this->jwt->decode($refreshToken);
        } catch (\Throwable $e) {
            return $this->json($response, ['error' => 'Refresh token inválido o expirado'], 401);
        }

        if (($payload['type'] ?? '') !== 'refresh') {
            return $this->json($response, ['error' => 'Token inválido'], 401);
        }

        $usuario = $this->usuarios->buscarPorId((int) $payload['sub']);
        if (!$usuario) {
            return $this->json($response, ['error' => 'Usuario no encontrado'], 401);
        }

        $accessToken = $this->jwt->issueAccessToken((int) $usuario['id'], $usuario['rol']);

        return $this->json($response, ['access_token' => $accessToken]);
    }

    public function registrarTokenPush(Request $request, Response $response): Response
    {
        $usuarioId = (int) $request->getAttribute('usuario_id');
        $body = (array) $request->getParsedBody();
        $token = (string) ($body['token'] ?? '');
        $plataforma = (string) ($body['plataforma'] ?? 'android');

        if ($token === '') {
            return $this->json($response, ['error' => 'token es requerido'], 422);
        }

        $this->usuarios->guardarTokenPush($usuarioId, $token, $plataforma);

        return $this->json($response, ['ok' => true]);
    }

    private function json(Response $response, array $data, int $status = 200): Response
    {
        $response->getBody()->write(json_encode($data));

        return $response->withHeader('Content-Type', 'application/json')->withStatus($status);
    }
}
