<?php

namespace App\Http\Controllers\API\Auth;

use App\Http\Controllers\API\BaseApiController;
use App\Models\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use App\Mail\PasswordResetMail;
use App\Mail\VerifyEmailMail;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Str;
use Illuminate\Validation\Rules\Password;

class AuthController extends BaseApiController
{
    public function login(Request $request): JsonResponse
    {
        $request->validate([
            'login'    => 'required|string',
            'password' => 'required|string',
        ]);

        $user = User::where('email', $request->login)
            ->orWhere('nuit', $request->login)
            ->first();

        if (!$user || !Hash::check($request->password, $user->password)) {
            return $this->errorResponse('Credenciais inválidas', 401);
        }

        if ($user->status !== 'active') {
            return $this->errorResponse('Conta inactiva ou bloqueada. Contacte o suporte.', 403);
        }

        // Block unverified investors
        if ($user->hasRole('investor') && $user->email && !$user->email_verified_at) {
            return response()->json([
                'success' => false,
                'message' => 'Email não verificado. Verifique a sua caixa de entrada.',
                'data'    => ['requires_verification' => true, 'email' => $user->email],
            ], 403);
        }

        $user->update([
            'last_login_at' => now(),
            'last_login_ip' => $request->ip(),
        ]);

        $token = $user->createToken('auth_token')->plainTextToken;

        return $this->successResponse([
            'user'  => $this->userResource($user),
            'token' => $token,
        ], 'Login efectuado com sucesso');
    }

    public function register(Request $request): JsonResponse
    {
        $request->validate([
            'name'             => 'required|string|max:255',
            'email'            => 'nullable|email|unique:users,email',
            'nuit'             => 'nullable|string|size:9|unique:users,nuit',
            'password'         => ['required', 'confirmed', Password::min(8)],
            'phone'            => 'nullable|string|max:20',
            'account_type'     => 'required|in:singular,colectiva,estrangeiro',
            'company_name'     => 'nullable|string|max:255',
            'country'          => 'nullable|string|size:3',
        ]);

        if (!$request->email && !$request->nuit) {
            return $this->errorResponse('É necessário fornecer email ou NUIT', 422);
        }

        $user = User::create([
            'name'         => $request->name,
            'email'        => $request->email,
            'nuit'         => $request->nuit,
            'password'     => $request->password,
            'phone'        => $request->phone,
            'account_type' => $request->account_type,
            'company_name' => $request->company_name,
            'country'      => $request->country ?? 'MOZ',
        ]);

        $user->assignRole('investor');

        // If email provided, require email verification before login
        if ($user->email) {
            DB::table('email_verification_tokens')->where('email', $user->email)->delete();
            $verifyToken = Str::random(64);
            DB::table('email_verification_tokens')->insert([
                'email'      => $user->email,
                'token'      => Hash::make($verifyToken),
                'created_at' => now(),
            ]);
            $verifyUrl = config('app.frontend_url', 'http://localhost:5173')
                . '/verify-email/confirm?token=' . $verifyToken
                . '&email=' . urlencode($user->email);
            Mail::to($user->email, $user->name)->send(new VerifyEmailMail($user, $verifyUrl));

            return $this->successResponse([
                'requires_verification' => true,
                'email'                 => $user->email,
            ], 'Conta criada com sucesso. Verifique o seu email para activar a conta.', 201);
        }

        // NUIT-only registration — login directly
        $token = $user->createToken('auth_token')->plainTextToken;

        return $this->successResponse([
            'user'  => $this->userResource($user),
            'token' => $token,
        ], 'Conta criada com sucesso', 201);
    }

    public function logout(Request $request): JsonResponse
    {
        $request->user()->currentAccessToken()->delete();
        return $this->successResponse(null, 'Sessão terminada com sucesso');
    }

    public function me(Request $request): JsonResponse
    {
        return $this->successResponse($this->userResource($request->user()));
    }

    public function updateProfile(Request $request): JsonResponse
    {
        $user = $request->user();

        $request->validate([
            'name'         => 'sometimes|string|max:255',
            'phone'        => 'sometimes|nullable|string|max:20',
            'company_name' => 'sometimes|nullable|string|max:255',
            'address'      => 'sometimes|nullable|string|max:500',
            'country'      => 'sometimes|nullable|string|size:3',
        ]);

        $user->update($request->only(['name', 'phone', 'company_name', 'address', 'country']));

        return $this->successResponse($this->userResource($user), 'Perfil actualizado com sucesso');
    }

    public function changePassword(Request $request): JsonResponse
    {
        $user = $request->user();

        $request->validate([
            'current_password' => 'required|string',
            'password'         => ['required', 'confirmed', Password::min(8)],
        ]);

        if (!Hash::check($request->current_password, $user->password)) {
            return $this->errorResponse('Palavra-passe actual incorrecta', 422);
        }

        $user->update(['password' => $request->password]);

        return $this->successResponse(null, 'Palavra-passe alterada com sucesso');
    }

    public function verifyEmail(Request $request): JsonResponse
    {
        $request->validate([
            'email' => 'required|email',
            'token' => 'required|string',
        ]);

        $record = DB::table('email_verification_tokens')
            ->where('email', $request->email)
            ->first();

        if (!$record || !Hash::check($request->token, $record->token)) {
            return $this->errorResponse('Link de verificação inválido ou expirado.', 422);
        }

        // Expire after 24 hours
        if (now()->diffInHours($record->created_at) > 24) {
            DB::table('email_verification_tokens')->where('email', $request->email)->delete();
            return $this->errorResponse('O link de verificação expirou. Solicite um novo.', 422);
        }

        $user = User::where('email', $request->email)->first();

        if (!$user) {
            return $this->errorResponse('Utilizador não encontrado.', 404);
        }

        $user->email_verified_at = now();
        $user->save();
        DB::table('email_verification_tokens')->where('email', $request->email)->delete();

        // Auto-login after verification
        $authToken = $user->createToken('auth_token')->plainTextToken;

        return $this->successResponse([
            'user'  => $this->userResource($user),
            'token' => $authToken,
        ], 'Email verificado com sucesso! Bem-vindo ao Portal do Investidor.');
    }

    public function resendVerification(Request $request): JsonResponse
    {
        $request->validate([
            'email' => 'required|email',
        ]);

        $user = User::where('email', $request->email)->first();

        if ($user && !$user->email_verified_at) {
            DB::table('email_verification_tokens')->where('email', $request->email)->delete();
            $verifyToken = Str::random(64);
            DB::table('email_verification_tokens')->insert([
                'email'      => $request->email,
                'token'      => Hash::make($verifyToken),
                'created_at' => now(),
            ]);
            $verifyUrl = config('app.frontend_url', 'http://localhost:5173')
                . '/verify-email/confirm?token=' . $verifyToken
                . '&email=' . urlencode($request->email);
            Mail::to($user->email, $user->name)->send(new VerifyEmailMail($user, $verifyUrl));
        }

        return $this->successResponse(null, 'Se o email existir e não estiver verificado, receberá um novo link de activação.');
    }

    public function forgotPassword(Request $request): JsonResponse
    {
        $request->validate([
            'email' => 'required|email',
        ]);

        // Always return success to prevent email enumeration
        $user = User::where('email', $request->email)->first();

        if ($user) {
            // Delete any existing token for this email
            DB::table('password_reset_tokens')->where('email', $request->email)->delete();

            $token = Str::random(64);

            DB::table('password_reset_tokens')->insert([
                'email'      => $request->email,
                'token'      => Hash::make($token),
                'created_at' => now(),
            ]);

            // Build reset URL (frontend)
            $resetUrl = config('app.frontend_url', 'http://localhost:5174')
                . '/reset-password?token=' . $token
                . '&email=' . urlencode($request->email);

            Mail::to($user->email, $user->name)
                ->send(new PasswordResetMail($user, $resetUrl));
        }

        return $this->successResponse(null, 'Se o email existir, receberá instruções para recuperar a palavra-passe.');
    }

    public function resetPassword(Request $request): JsonResponse
    {
        $request->validate([
            'email'    => 'required|email',
            'token'    => 'required|string',
            'password' => ['required', 'confirmed', Password::min(8)],
        ]);

        $record = DB::table('password_reset_tokens')
            ->where('email', $request->email)
            ->first();

        if (!$record || !Hash::check($request->token, $record->token)) {
            return $this->errorResponse('Token inválido ou expirado.', 422);
        }

        // Expire after 60 minutes
        if (now()->diffInMinutes($record->created_at) > 60) {
            DB::table('password_reset_tokens')->where('email', $request->email)->delete();
            return $this->errorResponse('O link de recuperação expirou. Solicite um novo.', 422);
        }

        $user = User::where('email', $request->email)->first();

        if (!$user) {
            return $this->errorResponse('Utilizador não encontrado.', 404);
        }

        $user->update(['password' => $request->password]);

        DB::table('password_reset_tokens')->where('email', $request->email)->delete();

        return $this->successResponse(null, 'Palavra-passe redefinida com sucesso. Pode agora iniciar sessão.');
    }

    private function userResource(User $user): array
    {
        return [
            'id'           => $user->id,
            'uid'          => $user->uid,
            'name'         => $user->name,
            'email'        => $user->email,
            'nuit'         => $user->nuit,
            'phone'        => $user->phone,
            'account_type' => $user->account_type,
            'status'       => $user->status,
            'company_name' => $user->company_name,
            'country'      => $user->country,
            'address'      => $user->address,
            'avatar_url'   => $user->avatar_url,
            'roles'        => $user->getRoleNames(),
            'last_login_at'=> $user->last_login_at,
        ];
    }
}
