<?php

namespace App\Http\Controllers;

use App\Events\ProfileSwitchEvent;
use App\Models\Bank;
use App\Models\User;
use App\Traits\SwitchGuardTrait;
use Hash;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

class BankLoginController extends Controller
{
    use SwitchGuardTrait;

    /**
     * Direct link to bank login - can be used in emails
     * Handles the layered authentication flow:
     * 1. If user not authenticated -> redirect to user login first
     * 2. If user authenticated -> set intent and redirect to bank login
     * 3. After bank login -> redirect to intended URL or main page
     */
    public function directLogin(Request $request, $bankId)
    {
        // Validate bank exists and load managers
        $bank = Bank::with('managers')->find($bankId);
        if (!$bank) {
            abort(404, __('Bank not found'));
        }

        // Get optional intended destination after successful bank login
        $intendedUrl = $request->query('intended');

        // Store intended URL in session if provided
        if ($intendedUrl) {
            session(['bank_login_intended_url' => $intendedUrl]);
        }

        // Check if user is authenticated on web guard
        if (!Auth::guard('web')->check()) {
            // User not logged in - redirect to user login with return URL
            $returnUrl = route('bank.direct-login', ['bankId' => $bankId]);
            if ($intendedUrl) {
                $returnUrl .= '?intended=' . urlencode($intendedUrl);
            }
            // Store in session for Laravel to redirect after login
            session()->put('url.intended', $returnUrl);

            // Get the first manager's name to pre-populate the login form
            $firstManager = $bank->managers()->first();

            if ($firstManager) {
                // Build the login URL with the name parameter and localization
                $loginRoute = route('login') . '?name=' . urlencode($firstManager->name);
                $loginUrl = \Mcamara\LaravelLocalization\Facades\LaravelLocalization::getLocalizedURL(null, $loginRoute);
                return redirect($loginUrl);
            }

            return redirect()->route('login');
        }

        // User is authenticated - verify they manage this bank
        $user = Auth::guard('web')->user();
        $userWithRelations = User::with('banksManaged')->find($user->id);

        if (!$userWithRelations || !$userWithRelations->banksManaged->contains('id', $bankId)) {
            abort(403, __('You do not have access to this bank'));
        }

        // Set the profile switch intent in session
        session([
            'intended_profile_switch_type' => 'Bank',
            'intended_profile_switch_id' => $bankId,
        ]);

        // Redirect to bank login form
        return redirect()->route('bank.login');
    }

    public function showLoginForm()
    {
        $user = Auth::guard('web')->user();
        $type = session('intended_profile_switch_type');
        $id = session('intended_profile_switch_id');
        $profile = $this->getTargetProfileByTypeAndId($user, $type, $id);
    
        return view('profile-bank.login', ['profile' => $profile]);
    }


    public function login(Request $request)
    {
        $request->validate([
            'password' => 'required',
        ]);

        $user = Auth::guard('web')->user();
        $type = session('intended_profile_switch_type');
        $id = session('intended_profile_switch_id');
        $bank = $this->getTargetProfileByTypeAndId($user, $type, $id);

        if (!$bank) {
            return back()->withErrors(['index' => __('Bank not found')]);
        }

        // Legacy Cyclos password support
        if (!empty($bank->cyclos_salt)) {
            info('Auth attempt using original Cyclos password');
            $concatenated = $bank->cyclos_salt . $request->password;
            $hashedInputPassword = hash("sha256", $concatenated);

            if (strtolower($hashedInputPassword) === strtolower($bank->password)) {
                info('Auth success: Password is verified');
                // Rehash to Laravel hash and remove salt
                $bank->password = \Hash::make($request->password);
                $bank->cyclos_salt = null;
                $bank->save();
                info('Auth success: Cyclos password has been rehashed for next login');
            }
        }

        // Check if the provided password matches the hashed password in the database
        if (\Hash::check($request->password, $bank->password)) {
            
            $this->switchGuard('bank', $bank);  // Log in as bank

            // Remove intended switch from session
            session()->forget(['intended_profile_switch_type', 'intended_profile_switch_id']);

            // Set active profile session as before
            session([
                'activeProfileType'  => get_class($bank),
                'activeProfileId'    => $bank->id,
                'activeProfileName'  => $bank->name,
                'activeProfilePhoto' => $bank->profile_photo_path,
                'last_activity' => now(),
                'profile-switched-notification' => true,
            ]);

            
            // Re-activate profile if inactive
            if (timebank_config('profile_inactive.re-activate_at_login')) {
                if (!$bank->isActive()) {
                    $bank->inactive_at = null;
                    $bank->save();
                    info('Bank re-activated: ' . $bank->name);
                }
            }

            event(new \App\Events\ProfileSwitchEvent($bank));

            // Check for intended URL from direct login flow
            $intendedUrl = session('bank_login_intended_url');
            if ($intendedUrl) {
                session()->forget('bank_login_intended_url');
                return redirect($intendedUrl);
            }

            return redirect()->route('main'); // TODO: Or special bank main page
        }

        info('Auth failed: Input password does not match stored password');
        return back()->withErrors(['password' => __('Invalid bank password')]);
    }

    //TODO: Move to Trait as suggested below.
    /**
     * Helper method to get the target profile model based on the index.
     * Note: This duplicates logic from ProfileSelect::mount. Consider refactoring
     * this logic into a service or trait if used in multiple places.
     */
    private function getTargetProfileByTypeAndId($user, $type, $id)
    {
        if (!$type || !$id) {
            return null;
        }
    
        $userWithRelations = User::with(['organizations', 'banksManaged', 'admins'])->find($user->id);
        if (!$userWithRelations) return null;
    
        if (strtolower($type) === 'organization') {
            return $userWithRelations->organizations->firstWhere('id', $id);
        } elseif (strtolower($type) === 'bank') {
            return $userWithRelations->banksManaged->firstWhere('id', $id);
        } elseif (strtolower($type) === 'admin') {
            return $userWithRelations->admins->firstWhere('id', $id);
        }
        return null;
    }
}
