<?php

declare(strict_types=1);

namespace App\Controllers;

use App\Helpers\Response;
use App\Services\AuthService;
use App\Models\Event;
use App\Middlewares\AuditMiddleware;

class AuthController extends BaseController
{
    private AuthService $authService;

    public function __construct($request)
    {
        parent::__construct($request);
        $this->authService = new AuthService();
    }

    public function login(): void
    {
        $data = $this->request->body();

        $validation = $this->validate($data, function ($v) {
            $v->required('email', 'Correo electrónico')
              ->email('email', 'Correo electrónico');
            $v->required('password', 'Contraseña')
              ->minLength('password', 8, 'Contraseña');
        });

        if ($validation->fails()) {
            Response::error($validation->firstError(), 422);
        }

        try {
            $result = $this->authService->login(
                $data['email'],
                $data['password'],
                $this->request->getClientIp(),
                $this->request->header('User-Agent', '')
            );

            if (!empty($result['requires_activation'])) {
                Response::json([
                    'success' => true,
                    'message' => $result['message'],
                    'requires_activation' => true,
                    'data' => [
                        'activation_token' => $result['activation_token'],
                    ],
                ], 200);
            }

            AuditMiddleware::log((int) $result['user']['id'], 'login', 'user', (int) $result['user']['id']);
            Response::success($result, 'Inicio de sesión exitoso');
        } catch (\Throwable $e) {
            Response::error($e->getMessage(), $e->getCode() ?: 500);
        }
    }

    public function logout(): void
    {
        $token = $this->request->bearerToken();

        if ($token) {
            $this->authService->logout($token);
        }

        Response::success(null, 'Sesión cerrada correctamente');
    }

    public function forgotPassword(): void
    {
        $data = $this->request->body();

        $validation = $this->validate($data, function ($v) {
            $v->required('email', 'Correo electrónico')
              ->email('email', 'Correo electrónico');
        });

        if ($validation->fails()) {
            Response::error($validation->firstError(), 422);
        }

        $this->authService->forgotPassword($data['email']);

        Response::success(null, 'Si el correo existe, recibirá instrucciones para restablecer su contraseña');
    }

    public function resetPassword(): void
    {
        $data = $this->request->body();

        $validation = $this->validate($data, function ($v) {
            $v->required('token', 'Token');
            $v->required('password', 'Nueva contraseña')
              ->minLength('password', 8, 'Nueva contraseña');
            $v->required('password_confirm', 'Confirmación de contraseña')
              ->matches('password_confirm', 'password', 'Confirmación de contraseña');
        });

        if ($validation->fails()) {
            Response::error($validation->firstError(), 422);
        }

        try {
            $this->authService->resetPassword($data['token'], $data['password']);
            Response::success(null, 'Contraseña actualizada correctamente');
        } catch (\RuntimeException $e) {
            Response::error($e->getMessage(), $e->getCode() ?: 400);
        }
    }

    public function activateAccount(): void
    {
        $data = $this->request->body();

        $validation = $this->validate($data, function ($v) {
            $v->required('activation_token', 'Token de activación');
            $v->required('password', 'Nueva contraseña')
              ->minLength('password', 8, 'Nueva contraseña');
            $v->required('password_confirm', 'Confirmación de contraseña')
              ->matches('password_confirm', 'password', 'Confirmación de contraseña');
        });

        if ($validation->fails()) {
            Response::error($validation->firstError(), 422);
        }

        try {
            $result = $this->authService->activateAccount(
                $data['activation_token'],
                $data['password']
            );

            Response::success($result, 'Cuenta activada');
        } catch (\RuntimeException $e) {
            Response::error($e->getMessage(), $e->getCode() ?: 400);
        }
    }

    public function me(): void
    {
        $eventId = $this->getAuthUserEventId();
        $eventName = null;

        if ($eventId) {
            $eventModel = new Event();
            $event = $eventModel->findById((int) $eventId);
            $eventName = $event['name'] ?? null;
        }

        Response::success([
            'id' => $this->getAuthUserId(),
            'role' => $this->getAuthUserRole(),
            'event_id' => $eventId,
            'event_name' => $eventName,
        ]);
    }

    public function register(): void
    {
        $data = $this->request->body();

        $validation = $this->validate($data, function ($v) {
            $v->required('name', 'Nombre');
            $v->required('email', 'Correo electrónico')
              ->email('email', 'Correo electrónico');
            $v->required('password', 'Contraseña')
              ->minLength('password', 8, 'Contraseña');
            $v->required('password_confirm', 'Confirmación de contraseña')
              ->matches('password_confirm', 'password', 'Confirmación de contraseña');
        });

        if ($validation->fails()) {
            Response::error($validation->firstError(), 422);
        }

        try {
            $result = $this->authService->register(
                $data['name'],
                $data['email'],
                $data['password']
            );
            Response::created($result, 'Usuario registrado correctamente');
        } catch (\RuntimeException $e) {
            Response::error($e->getMessage(), $e->getCode() ?: 400);
        }
    }
}
