<?php

namespace App\Services;

use App\Models\PortalUser;
use Illuminate\Support\Facades\Hash;
use Illuminate\Validation\ValidationException;

class PortalAuthService
{
    public function __construct(
        private TwoFactorAuthService $twoFactorService
    ) {
    }
    /**
     * Authenticate portal user and return token with user data or 2FA challenge.
     */
    public function login(string $email, string $password): array
    {
        $portalUser = PortalUser::where('email', $email)->first();

        if (! $portalUser) {
            throw ValidationException::withMessages([
                'email' => ['The provided credentials are incorrect.'],
            ]);
        }

        if (! $portalUser->hasSetPassword()) {
            throw ValidationException::withMessages([
                'email' => ['Password not set. Please check your email for the invitation link.'],
            ]);
        }

        if (! Hash::check($password, $portalUser->password)) {
            throw ValidationException::withMessages([
                'email' => ['The provided credentials are incorrect.'],
            ]);
        }

        // Check if user needs 2FA
        if ($portalUser->needsTwoFactorSetup() || $portalUser->hasTwoFactorEnabled()) {
            // Generate and send 2FA code
            $sessionToken = $this->twoFactorService->generateAndSendCode($portalUser);

            return [
                'requires_2fa' => true,
                'session_token' => $sessionToken,
                'user' => [
                    'id' => $portalUser->id,
                    'email' => $portalUser->email,
                ],
                'message' => 'Verification code sent to your email.',
            ];
        }

        // If 2FA is not enabled, issue token directly
        return $this->issueToken($portalUser);
    }

    /**
     * Verify 2FA code and issue token.
     */
    public function verifyTwoFactor(string $email, string $code, string $sessionToken): array
    {
        $portalUser = PortalUser::where('email', $email)->first();

        if (! $portalUser) {
            throw ValidationException::withMessages([
                'email' => ['User not found.'],
            ]);
        }

        // Verify the code
        $this->twoFactorService->verifyCode($portalUser, $code, $sessionToken);

        // Issue the authentication token
        return $this->issueToken($portalUser);
    }

    /**
     * Issue an authentication token for the portal user.
     */
    protected function issueToken(PortalUser $portalUser): array
    {
        // Revoke existing tokens for security
        $portalUser->tokens()->delete();

        // Create new token — expires in 30 days
        $token = $portalUser->createToken('portal-access', ['*'], now()->addDays(30))->plainTextToken;

        // Load company employee relationship if exists
        $portalUser->load('companyEmployee');

        $userData = [
            'id' => $portalUser->id,
            'name' => $portalUser->name,
            'email' => $portalUser->email,
            'role' => $portalUser->role,
            'company_id' => $portalUser->company_id,
            'email_verified_at' => $portalUser->email_verified_at?->toIso8601String(),
            'created_at' => $portalUser->created_at->toIso8601String(),
            'two_factor_enabled' => $portalUser->two_factor_enabled,
        ];

        // Add employee-specific data if user is an employee
        if ($portalUser->role === 'employee' && $portalUser->companyEmployee) {
            $employee = $portalUser->companyEmployee;
            $userData['employee_id'] = $employee->id; // Use this ID in URLs like /api/portal/employees/{id}/...
            $userData['nin_verification'] = [
                'has_submitted_nin' => $employee->hasSubmittedNin(),
                'is_nin_verified' => $employee->isNinVerified(),
                'is_validated' => $employee->is_validated ?? false,
                'nin_verified_at' => $employee->nin_verified_at?->toIso8601String(),
            ];
        }

        return [
            'user' => $userData,
            'token' => $token,
        ];
    }

    /**
     * Logout the authenticated portal user.
     */
    public function logout(PortalUser $portalUser): void
    {
        $portalUser->tokens()->delete();
    }
}

