<?php

namespace App\Providers;

use App\Actions\Fortify\CreateNewUser;
use App\Actions\Fortify\ResetUserPassword;
use App\Actions\Fortify\UpdateUserPassword;
use App\Actions\Fortify\UpdateUserProfileInformation;
use App\Models\User;
use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Http\Request;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\ServiceProvider;
use Illuminate\Validation\ValidationException;
use Laravel\Fortify\Fortify;
use Laravel\Fortify\Http\Controllers\VerifyEmailController;
use Mcamara\LaravelLocalization\Facades\LaravelLocalization;

class FortifyServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
        //
    }

    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        // Disable Fortify route registration, a selection of the initial fortify routes are moved ot /routes/fortify.php.
        // Custom routes with the same name however are registered in web.php. This is done because Fortify does not allow to register routes with the same name.
        Fortify::ignoreRoutes();

        Fortify::createUsersUsing(CreateNewUser::class);
        Fortify::updateUserProfileInformationUsing(UpdateUserProfileInformation::class);
        Fortify::updateUserPasswordsUsing(UpdateUserPassword::class);
        Fortify::resetUserPasswordsUsing(ResetUserPassword::class);

        Fortify::verifyEmailView(fn () => view('auth.verify-email'));

        RateLimiter::for('login', function (Request $request) {
            $loginIdentifier = (string) $request->input('name'); // Changed from $request->email to $request->input('name')
            return Limit::perMinute(10)->by($loginIdentifier.$request->ip());
        });

        RateLimiter::for('two-factor', function (Request $request) {
            return Limit::perMinute(5)->by($request->session()->get('login.id'));
        });



        // Rehash Cyclos salted sha256 passwords on first login
        Fortify::authenticateUsing(function (Request $request) {
            // Attempt to find the user by email or name.
            $user = User::where('email', $request->name)
                        ->orWhere('name', $request->name)
                        ->first();

            if (!$user) {
                info('Auth failed: User not identified with login identifier: ' . $request->auth);
                return null;
            }
            if ($user->isRemoved()) {
                info('Auth failed: User ' . $user->name . ' is marked as removed (soft-deleted).');
                return null;
            }

            // If maintenance mode is enabled, check if user has admin relationship
            if (isMaintenanceMode()) {
                $hasAdminRelation = $user->admins()->exists();
                if (!$hasAdminRelation) {
                    info('Auth failed: Maintenance mode is active and user ' . $user->name . ' does not have admin relationship.');
                    session()->flash('maintenance_mode_active', true);
                    throw ValidationException::withMessages([
                        'name' => __('Login is currently disabled due to site maintenance. Only administrator accounts can access the site at this time. Please try again later.'),
                    ]);
                }
                info('Auth allowed during maintenance: User ' . $user->name . ' has admin relationship.');
            }

            info('User identified: ' . $user->name . ' (ID: ' . $user->id . ') attempting login with identifier: ' . $request->auth);
            $passwordVerified = false;

            // Check for Cyclos password first if salt exists
            if (!empty($user->cyclos_salt)) {
                info('Attempting Cyclos password verification for user: ' . $user->name);
                $concatenated = $user->cyclos_salt . $request->password;
                $hashedInputPassword = hash("sha256", $concatenated);

                if (strtolower($hashedInputPassword) === strtolower($user->password)) {
                    info('Cyclos password verified for user: ' . $user->name);
                    // Prepare user model for update: rehash password and clear salt
                    $user->password = Hash::make($request->password);
                    $user->cyclos_salt = null;
                    $passwordVerified = true;
                    info('Cyclos password prepared for rehashing for user: ' . $user->name);
                } else {
                    info('Cyclos password verification failed for user: ' . $user->name . '. Will attempt standard Laravel hash check.');
                }
            }

            // If not verified by Cyclos, or if cyclos_salt was empty, try Laravel's default hash check
            if (!$passwordVerified && Hash::check($request->password, $user->password)) {
                info('Laravel password verified for user: ' . $user->name);
                $passwordVerified = true;
            }

            if ($passwordVerified) {
                info('Auth success for user: ' . $user->name);
                // Update last login details
                $now = Carbon::now()->toDateTimeString();
                $user->last_login_at = $now;
                $user->last_login_ip = $request->getClientIp();
                if (timebank_config('profile_inactive.re-activate_at_login')) {
                    if (!$user->isActive()) {
                        $user->inactive_at = null;
                        $activated = true;
                    }
                }
                // Save all changes (rehashed password, cleared salt, login details)
                $user->save();

                if (isset($activated) && $activated) {
                    info('User re-activated: ' . $user->name);
                }

                return $user;
            }

            info('Auth failed: Password mismatch for user: ' . $user->name . ' with identifier: ' . $request->auth);
            return null;
        });


    }
}
