<?php

namespace App\Http\Controllers;

use App\Models\User;
use App\Http\Requests\LoginRequest;
use App\Services\AuthService;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\View;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Redirect;
use Illuminate\Support\Facades\Response;
use Illuminate\Support\Facades\Hash;
use App\Facades\DBconfig;
use App\Modules\Adldap\Facades\Adldap as LDAP;
use Illuminate\Support\Facades\Log;

class LoginController extends BaseController
{
    /**
     *	The layout that should be used for responses.
     */
    protected $layout = 'layouts.master';

    /**
     * The auth service instance.
     */
    protected AuthService $authService;

    /**
     * Create a new controller instance.
     */
    public function __construct(AuthService $authService)
    {
        $this->authService = $authService;
    }

    /*
    |--------------------------------------------------------------------------
    | Default Home Controller
    |--------------------------------------------------------------------------
    |
    | You may wish to use controllers instead of, or in addition to, Closure
    | based routes. That's great! Here is an example controller method to
    | get you started. To route to this controller, just add the route:
    |
    |	Route::get('/', 'HomeController@showWelcome');
    |
    */

    public function getIndex()
    {
        $this->layout->content = View::make('login');
    }

    public function postIndex(LoginRequest $request)
    {
        Log::info('=== LOGIN ATTEMPT STARTED ===', [
            'username' => $request->input('username'),
            'has_password' => !empty($request->input('password')),
            'ip' => $request->ip(),
            'user_agent' => $request->header('User-Agent')
        ]);

        // Search for the username
        $user = User::where('username', '=', $request->input('username'))->first();

        if (! $user) {
            Log::info('User not found in database', ['username' => $request->input('username')]);
            
            // Attempt an LDAP login
            $ldapEnabled = DBconfig::get('ldap.enabled', false);
            Log::info('LDAP settings', ['ldap_enabled' => $ldapEnabled]);
            
            $login = $ldapEnabled ? LDAP::auth($request->input('username'), $request->input('password')) : false;

            if ($login) {
                Log::info('LDAP authentication successful', ['username' => $request->input('username'), 'ldap_data' => $login]);
                
                // Login Successful, but the user doesn't exist in the archDB database yet
                // so we will create it now
                $user = User::create([
                    'first_name'   => $login['name'],
                    'last_name'    => '',
                    'password'     => '',
                    'mobile'       => '',
                    'email'        => $login['email'],
                    'username'     => $request->input('username'),
                    'account_type' => 'ldap',
                    'last_login'   => date('Y-m-d H:i:s'),
                ]);

                if (! $user->id) {
                    Log::error('Failed to create user in database', ['username' => $request->input('username')]);
                    return Redirect::route('login')->withErrors(['Whoops, I was unable to create your account locally.']);
                }

                Log::info('New LDAP user created', ['user_id' => $user->id, 'username' => $user->username]);
                
                Auth::loginUsingId($user->id, true);
                
                Log::info('User logged in via LDAP', ['user_id' => $user->id, 'auth_check' => Auth::check()]);

                // Clear intended URL and force redirect to dashboard
                session()->forget('url.intended');
                return Redirect::to('/');
            } else {
                Log::warning('LDAP authentication failed', ['username' => $request->input('username')]);
                return Redirect::route('login')->withErrors(['Invalid username or password']);
            }
        }

        Log::info('User found in database', [
            'user_id' => $user->id,
            'username' => $user->username,
            'account_type' => $user->account_type,
            'suspended' => $user->suspended,
            'active' => $user->active ?? 'no active field'
        ]);

        // Username exists in the database
        // If this is a local account, then use the Auth library
        if ($user->account_type == 'local') {
            Log::info('Attempting local authentication', ['user_id' => $user->id]);
            
            $credentials = [
                'username' => $request->input('username'), 
                'password' => $request->input('password'), 
                'account_type' => 'local', 
                'suspended' => 0
            ];
            
            Log::info('Auth credentials prepared', [
                'username' => $credentials['username'],
                'account_type' => $credentials['account_type'],
                'suspended' => $credentials['suspended'],
                'password_provided' => !empty($credentials['password'])
            ]);
            
            // Let's also test the password hash directly
            $passwordCheck = Hash::check($request->input('password'), $user->password);
            Log::info('Direct password check', [
                'password_check_result' => $passwordCheck,
                'password_hash_length' => strlen($user->password),
                'password_starts_with_dollar2y' => substr($user->password, 0, 3) === '$2y'
            ]);
            
            if (Auth::attempt($credentials, true)) {
                Log::info('Local authentication successful', ['user_id' => $user->id, 'auth_check' => Auth::check()]);
                
                $user->last_login = date('Y-m-d H:i:s');
                $user->save();

                // Clear intended URL and force redirect to dashboard
                session()->forget('url.intended');
                Log::info('Redirecting to dashboard', ['redirect_url' => '/']);
                return Redirect::to('/');
            } else {
                Log::warning('Local authentication failed', ['user_id' => $user->id, 'credentials_check' => 'failed']);
                return Redirect::route('login')->withErrors(['Invalid username or password. Please check your credentials and try again.']);
            }
        } else {
            Log::info('Attempting LDAP authentication for existing user', ['user_id' => $user->id]);
            
            // This is an active directory account, using LDAP library
            $ldapEnabled = DBconfig::get('ldap.enabled', false);
            Log::info('LDAP settings for existing user', ['ldap_enabled' => $ldapEnabled]);
            
            // Wrap LDAP authentication in try-catch to handle any configuration errors gracefully
            $login = false;
            if ($ldapEnabled) {
                try {
                    $login = LDAP::auth($request->input('username'), $request->input('password'));
                } catch (\Exception $e) {
                    Log::error('LDAP authentication exception caught in LoginController', [
                        'user_id' => $user->id,
                        'username' => $request->input('username'),
                        'error' => $e->getMessage(),
                        'trace' => $e->getTraceAsString()
                    ]);
                    $login = false;
                }
            }

            if ($login) {
                Log::info('LDAP authentication successful for existing user', ['user_id' => $user->id, 'ldap_data' => $login]);
                
                // Check for changes
                if ($login['email'] != $user->email) {
                    Log::info('Updating user email from LDAP', ['old_email' => $user->email, 'new_email' => $login['email']]);
                    $user->email = $login['email'];
                }

                Auth::loginUsingId($user->id, true);
                
                Log::info('User logged in via LDAP (existing user)', ['user_id' => $user->id, 'auth_check' => Auth::check()]);

                $user->last_login = date('Y-m-d H:i:s');
                $user->save();

                Log::info('Redirecting to dashboard (LDAP)', ['intended_url' => Redirect::to('/')->getTargetUrl()]);
                return Redirect::to('/');
            } else {
                Log::warning('LDAP authentication failed for existing user', ['user_id' => $user->id]);
                return Redirect::route('login')->withErrors(['Invalid username or password. Please check your credentials and try again.']);
            }
        }
        
        Log::info('=== LOGIN ATTEMPT COMPLETED ===');
    }

    /**
     * Validates login credentials.
     *
     * @return Boolean
     */
    public function postValidate(Request $request): JsonResponse
    {
        if (! $request->input('username')) {
            return Response::json(['error' => 'No username provided.'], 400);
        }

        if (! $request->input('password')) {
            return Response::json(['error' => 'No password provided.'], 400);
        }

        $success = $this->authService->validateCredentials(
            $request->input('username'),
            $request->input('password'),
            $request->input('login', false)
        );

        return Response::json(['success' => $success]);
    }
}
