<?php

namespace App\Filament\Central\Pages\Auth;

use App\Models\Central\CentralAdmin;
use App\Services\LoginThrottle;
use Filament\Auth\Http\Responses\Contracts\LoginResponse;
use Filament\Auth\MultiFactor\Contracts\HasBeforeChallengeHook;
use Filament\Auth\Pages\Login as BaseLogin;
use Filament\Facades\Filament;
use Illuminate\Auth\SessionGuard;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;
use Illuminate\Validation\ValidationException;

/**
 * Ported from leolanka-inertia's Central\CentralAuthController@store
 * (docs/migration-plan.md §5). No rate limiting/lockout on this side — the
 * source app has none for central admins (small, trusted operator pool, no
 * RBAC layer either). TOTP-only MFA via Filament's native AppAuthentication,
 * matching the source app's Google2FA-direct, email-OTP-free design.
 */
class Login extends BaseLogin
{
    public function authenticate(): ?LoginResponse
    {
        $data = $this->form->getState();

        $email = Str::lower(trim((string) $data['email']));
        $password = (string) $data['password'];
        $remember = (bool) ($data['remember'] ?? false);

        $admin = CentralAdmin::query()->where('email', $email)->first();

        if (! $admin || ! $admin->is_active || ! Hash::check($password, $admin->password ?? LoginThrottle::DUMMY_HASH)) {
            throw ValidationException::withMessages([
                'data.email' => __('These credentials do not match our records.'),
            ]);
        }

        if ($this->needsMultiFactorChallenge($admin)) {
            return null;
        }

        /** @var SessionGuard $authGuard */
        $authGuard = Filament::auth();
        $authGuard->login($admin, $remember);

        session()->regenerate();

        $admin->forceFill(['last_login_at' => now()])->save();

        return app(LoginResponse::class);
    }

    protected function needsMultiFactorChallenge(CentralAdmin $admin): bool
    {
        if (
            filled($this->userUndertakingMultiFactorAuthentication) &&
            (decrypt($this->userUndertakingMultiFactorAuthentication) === $admin->getAuthIdentifier())
        ) {
            if ($this->isMultiFactorChallengeRateLimited($admin)) {
                return true;
            }

            $this->multiFactorChallengeForm->validate();

            return false;
        }

        foreach (Filament::getMultiFactorAuthenticationProviders() as $provider) {
            if (! $provider->isEnabled($admin)) {
                continue;
            }

            $this->userUndertakingMultiFactorAuthentication = encrypt($admin->getAuthIdentifier());

            if ($provider instanceof HasBeforeChallengeHook) {
                $provider->beforeChallenge($admin);
            }

            break;
        }

        if (filled($this->userUndertakingMultiFactorAuthentication)) {
            $this->multiFactorChallengeForm->fill();

            return true;
        }

        return false;
    }

    protected function getCredentialsFromFormData(array $data): array
    {
        return [
            'email' => $data['email'],
            'password' => $data['password'],
        ];
    }
}
