<?php

namespace App\Services;

use App\Models\User;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Log;
use App\Facades\DBconfig;
use App\Modules\Adldap\Facades\Adldap as LDAP;

class AuthService
{
    /**
     * Attempt to authenticate a user with the given credentials.
     */
    public function attemptLogin(string $username, string $password): array
    {
        Log::info('=== LOGIN ATTEMPT STARTED ===', [
            'username' => $username,
            'has_password' => !empty($password),
        ]);

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

        if (!$user) {
            Log::info('User not found in database', ['username' => $username]);
            return $this->handleNewUserLogin($username, $password);
        }

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

        return $this->handleExistingUserLogin($user, $username, $password);
    }

    /**
     * Handle login for a new user (not in database).
     */
    private function handleNewUserLogin(string $username, string $password): array
    {
        $ldapEnabled = DBconfig::get('ldap.enabled', false);
        Log::info('LDAP settings', ['ldap_enabled' => $ldapEnabled]);

        $login = $ldapEnabled ? LDAP::auth($username, $password) : false;

        if ($login) {
            Log::info('LDAP authentication successful', ['username' => $username]);
            
            $user = $this->createLdapUser($username, $login);
            
            if (!$user) {
                return [
                    'success' => false,
                    'message' => 'Whoops, I was unable to create your account locally.',
                    'redirect' => '/login'
                ];
            }

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

            return [
                'success' => true,
                'redirect' => '/'
            ];
        }

        Log::warning('LDAP authentication failed', ['username' => $username]);
        return [
            'success' => false,
            'message' => 'Invalid username or password',
            'redirect' => '/login'
        ];
    }

    /**
     * Handle login for an existing user.
     */
    private function handleExistingUserLogin(User $user, string $username, string $password): array
    {
        if ($user->account_type == 'local') {
            return $this->handleLocalUserLogin($user, $username, $password);
        }

        return $this->handleLdapUserLogin($user, $username, $password);
    }

    /**
     * Handle local user authentication.
     */
    private function handleLocalUserLogin(User $user, string $username, string $password): array
    {
        Log::info('Attempting local authentication', ['user_id' => $user->id]);

        $credentials = [
            'username' => $username,
            'password' => $password,
            'account_type' => 'local',
            'suspended' => 0
        ];

        if (Auth::attempt($credentials, true)) {
            Log::info('Local authentication successful', ['user_id' => $user->id]);
            
            $user->last_login = date('Y-m-d H:i:s');
            $user->save();

            return [
                'success' => true,
                'redirect' => '/'
            ];
        }

        Log::warning('Local authentication failed', ['user_id' => $user->id]);
        return [
            'success' => false,
            'redirect' => '/login'
        ];
    }

    /**
     * Handle LDAP user authentication.
     */
    private function handleLdapUserLogin(User $user, string $username, string $password): array
    {
        Log::info('Attempting LDAP authentication for existing user', ['user_id' => $user->id]);

        $ldapEnabled = DBconfig::get('ldap.enabled', false);
        $login = $ldapEnabled ? LDAP::auth($username, $password) : false;

        if ($login) {
            Log::info('LDAP authentication successful for existing user', ['user_id' => $user->id]);

            // 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);
            $user->last_login = date('Y-m-d H:i:s');
            $user->save();

            return [
                'success' => true,
                'redirect' => '/'
            ];
        }

        Log::warning('LDAP authentication failed for existing user', ['user_id' => $user->id]);
        return [
            'success' => false,
            'message' => 'Invalid username or password',
            'redirect' => '/login'
        ];
    }

    /**
     * Create a new LDAP user in the database.
     */
    private function createLdapUser(string $username, array $ldapData): ?User
    {
        $user = User::create([
            'first_name' => $ldapData['name'],
            'last_name' => '',
            'password' => '',
            'mobile' => '',
            'email' => $ldapData['email'],
            'username' => $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' => $username]);
            return null;
        }

        Log::info('New LDAP user created', ['user_id' => $user->id, 'username' => $user->username]);
        return $user;
    }

    /**
     * Validate login credentials without logging in.
     */
    public function validateCredentials(string $username, string $password, bool $login = false): bool
    {
        $user = User::where('username', '=', $username)->first();

        if (!$user) {
            return false;
        }

        if ($user->account_type == 'local') {
            if (Auth::validate(['username' => $username, 'password' => $password, 'account_type' => 'local', 'suspended' => 0])) {
                if ($login) {
                    Auth::loginUsingId($user->id, true);
                }
                return true;
            }
        } elseif ($user->account_type == 'ldap' && DBconfig::get('ldap.enabled')) {
            if (LDAP::auth($username, $password)) {
                if ($login) {
                    Auth::loginUsingId($user->id, true);
                }
                return true;
            }
        }

        return false;
    }
} 