<?php

declare(strict_types=1);

use App\Models\User;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;

/**
 * Login user
 */
function loginUserUsingApi(string $email, string $password): array
{
    $response = [];
    try {
        $response = getHttpClient(false)->post(config('app.api_url').'/merchants/login', [
            'email' => $email,
            'password' => $password,
        ]);
        $response = $response->json();
        if (! $response['success']) {
            return [
                'success' => false,
                'message' => 'Identifiants API invalides. Connexion locale requise...',
                'status' => 401,
            ];
        }

        return [
            'success' => true,
            'user' => $response['user'] ?? null,
            'merchant_code' => $response['merchant_code'] ?? null,
            'token' => $response['token'] ?? null,
            'status' => $response['status'] ?? null,
        ];
    } catch (\Exception $e) {
        Log::error('Login API exception', [
            'error' => $e->getMessage(),
            'api_url' => config('app.api_url'),
            'email' => $email,
        ]);

        return [
            'success' => false,
            'message' => 'Une erreur est survenue lors de la connexion. Veuillez réessayer plus tard.',
            'status' => 500,
        ];
    }
}

/**
 * Authenticate user against the local SQLite database.
 *
 * @return array{success: bool, message?: string, status?: int, user?: User, requires_otp?: bool}
 */
function loginUserLocally(string $email, string $password): array
{
    try {
        $user = User::where('email', $email)->first();

        if (! $user) {
            return [
                'success' => false,
                'message' => 'Aucun utilisateur trouvé pour cet email.',
                'status' => 401,
            ];
        }

        if ($user->isLocked()) {
            return [
                'success' => false,
                'message' => $user->getLockoutMessage(),
                'status' => 423,
            ];
        }

        if (! Hash::check($password, $user->password)) {
            $user->incrementFailedLoginAttempts();

            return [
                'success' => false,
                'message' => 'Mot de passe incorrect.',
                'status' => 401,
            ];
        }

        // User inactive: require OTP verification
        if ($user->status === User::STATUS_INACTIVE) {
            session([
                'pending_user_id' => $user->id,
                'pending_user_email' => $user->email,
                'pending_user_token' => $user->api_token ?? null,
            ]);

            Auth::login($user, false);

            return [
                'success' => true,
                'message' => 'Connexion locale réussie.',
                'status' => 200,
                'user' => $user,
                'requires_otp' => true,
            ];
        }

        if (! $user->loginUser(false)) {
            return [
                'success' => false,
                'message' => 'Erreur de connexion locale.',
                'status' => 500,
            ];
        }

        return [
            'success' => true,
            'message' => 'Connexion locale réussie.',
            'status' => 200,
            'user' => $user,
        ];
    } catch (\Exception $e) {
        Log::error('Local login exception', [
            'error' => $e->getMessage(),
            'email' => $email,
        ]);

        return [
            'success' => false,
            'message' => 'Une erreur est survenue lors de la connexion. Veuillez réessayer.',
            'status' => 500,
        ];
    }
}

/**
 * Register user function
 *
 * @param  string  $firstname
 * @param  string  $lastname
 * @param  string  $email
 * @param  string  $password
 */
function register($firstname, $lastname, $merchant_name, $email, $password): array
{
    try {
        $response = getHttpClient(false)->post(config('app.api_url').'/merchants/register', [
            'first_name' => $firstname,
            'last_name' => $lastname,
            'merchant_name' => $merchant_name,
            'email' => $email,
            'password' => $password,
        ]);

        $response = $response->json();
        if (! $response['success']) {
            return [
                'success' => false,
                'message' => $response['message'],
                'status' => $response['status'],
            ];
        }

        $user = $response['user'];
        if (! $user) {
            return [
                'success' => false,
                'message' => 'Utilisateur API invalide',
                'status' => 404,
            ];
        }

        $token = $response['token'];
        if (! $token) {
            return [
                'success' => false,
                'message' => 'Token API invalide',
                'status' => 404,
            ];
        }

        return [
            'success' => true,
            'message' => 'Utilisateur enregistré avec succès',
            'user' => $user,
            'token' => $token,
            'requires_otp' => $response['requires_otp'],
            'status' => 200,
        ];
    } catch (\Exception $e) {
        Log::error('Register API exception', [
            'error' => $e->getMessage(),
        ]);

        return [
            'success' => false,
            'message' => 'Poire Une erreur est survenue lors de l\'enregistrement de l\'utilisateur. Veuillez réessayer plus tard.',
            'status' => 500,
        ];
    }
}

function createOrUpdateUserToLocalDatabase(array $userData, string $password): bool
{
    $email = $userData['email'] ?? null;
    if (empty($email)) {
        throw new \InvalidArgumentException('Email requis pour synchroniser l\'utilisateur.');
    }

    $existingUser = User::where('email', $email)->first();
    $firstName = $userData['first_name'] ?? $userData['firstname'] ?? '';
    $lastName = $userData['last_name'] ?? $userData['lastname'] ?? '';
    $baseName = trim("{$firstName} {$lastName}") ?: 'user';
    $username = $existingUser?->username ?? User::generateUniqueUsername($baseName);
    $slug = $existingUser?->slug ?? (string) Str::orderedUuid();

    try {
        User::updateOrCreate(
            ['email' => $email],
            [
                'firstname' => $firstName,
                'lastname' => $lastName,
                'username' => $username,
                'slug' => $slug,
                'photo_path' => $userData['photo_path'] ?? null,
                'status' => ($userData['status'] ?? 'inactive') === 'active',
                'role' => 'owner',
                'last_login_at' => now(),
                'password' => Hash::make($password),
            ]
        );
    } catch (\Exception $e) {
        Log::error('Create or update user exception', [
            'error' => $e->getMessage(),
            'email' => $email,
        ]);

        return false;
    }

    return true;
}

function initializeUserSession(array $userData, string $token): bool
{
    if (empty($userData) || empty($token)) {
        return false;
    }

    $email = $userData['email'] ?? null;
    $id = $userData['id'] ?? null;
    $firstname = $userData['first_name'] ?? $userData['firstname'] ?? null;
    $lastname = $userData['last_name'] ?? $userData['lastname'] ?? null;
    $status = $userData['status'] ?? 'inactive';
    $otpExpiresAt = $userData['otp_expires_at'] ?? null;

    if (empty($email) || empty($id) || empty($firstname) || empty($lastname) || empty($status)) {
        return false;
    }

    try {
        session([
            'pending_user_id' => $id,
            'pending_user_firstname' => $firstname,
            'pending_user_lastname' => $lastname,
            'pending_user_email' => $email,
            'pending_user_status' => $status,
            'pending_user_token' => $token,
            'otp_expires_at' => $otpExpiresAt,
        ]);

        return true;
    } catch (\Exception $e) {
        Log::error('Initialize user session exception', [
            'error' => $e->getMessage(),
            'user_data' => $userData,
        ]);

        return false;
    }
}

function initializeMerchantSession(string $merchantName): bool
{
    if (empty($merchantName)) {
        return false;
    }

    try {
        $settings = \App\Models\Setting::first();
        if ($settings) {
            $settings->update([
                'merchant_name' => $merchantName,
                'merchant_slug' => \Illuminate\Support\Str::slug($merchantName),
            ]);
        }
        session(['pending_merchant_name' => $merchantName]);

        return true;
    } catch (\Exception $e) {
        Log::error('Initialize merchant session exception', [
            'error' => $e->getMessage(),
            'merchant_name' => $merchantName,
        ]);

        return false;
    }
}

function cleanDatabase(): bool
{
    try {
        resetDatabase();
        runFirstTimeSetup();

        return true;
    } catch (\Exception $e) {
        Log::error('Clean database exception', [
            'error' => $e->getMessage(),
        ]);

        return false;
    }
}

/**
 * Verify token
 *
 * @param  string  $phone
 * @param  string  $otp
 * @param  string  $token
 */
function verifyToken($email, $otp, $token): array
{
    try {
        $response = getHttpClient(false)->post(config('app.api_url').'/merchants/verify-guest-otp', [
            'email' => $email,
            'otp' => $otp,
        ]);

        $data = $response->json();

        if (! $data['success']) {
            $message = $data['message'] ?? 'Code OTP invalide.';
            $message = decodeUnicodeString($message);

            return [
                'success' => false,
                'message' => $message,
                'status' => $response->status(),
            ];
        }

        // Find the user by email
        $user = User::where('email', $email)->first();
        if (! $user) {
            return [
                'success' => false,
                'message' => 'User not found',
                'status' => 404,
            ];
        }

        // Update user status to active
        $user->update(['status' => User::STATUS_ACTIVE]);

        // Update auth token
        session(['auth_token' => $data['token'] ?? $token]);

        // Make sure user is logged in
        Auth::login($user);

        return [
            'success' => true,
            'message' => 'OTP verified successfully',
            'status' => 200,
            'user' => $user,
            'token' => $data['token'] ?? $token,
        ];
    } catch (\Exception $e) {
        ['message' => $friendlyMessage, 'status' => $status] = extractApiExceptionMessage($e, 'Erreur de vérification');

        return [
            'success' => false,
            'message' => $friendlyMessage,
            'status' => $status,
        ];
    }
}

/**
 * Resend OTP
 *
 * @param  string  $phone
 * @param  string  $token
 */
function resendOtp($email, $token): array
{
    if (empty($email) || empty($token)) {
        return [
            'success' => false,
            'message' => 'Session OTP invalide.',
            'status' => 401,
        ];
    }
    try {
        $response = getHttpClient(false)->withHeaders([
            'Authorization' => 'Bearer '.$token,
        ])->post(config('app.api_url').'/merchants/resend-otp', [
            'email' => $email,
        ]);

        $data = $response->json();

        if (! $data['success']) {
            $message = $data['message'] ?? 'Impossible de renvoyer le code OTP.';
            $message = decodeUnicodeString($message);

            return [
                'success' => false,
                'message' => $message,
                'status' => $response->status(),
            ];
        }

        return [
            'success' => true,
            'message' => 'Code OTP renvoyé avec succès.',
            'status' => 200,
            'data' => $data,
        ];
    } catch (\Exception $e) {
        return [
            'success' => false,
            'message' => 'Impossible de se connecter au serveur distant. Veuillez réessayer plus tard.',
            'status' => 500,
        ];
    }
}

/**
 * Check if a valid authentication token exists
 */
function hasValidAuthToken(): bool
{
    $token = session('auth_token') ?? Auth::user()?->api_token ?? session('pending_user_token') ?? '';

    return ! empty($token);
}

/**
 * Update user password via API
 */
function updateApiPassword(string $newPassword): array
{
    try {
        $response = getHttpClient(true)->put(config('app.api_url').'/merchants/users/update-password', [
            'password' => $newPassword,
        ]);

        if (! $response->successful() && $response->status() == 401) {
            Auth::logout();
            session()->invalidate();
            session()->regenerateToken();

            Log::warning('API password update failed: Session expired', [
                'status' => $response->status(),
            ]);

            return ['success' => false, 'message' => 'Session expirée', 'status' => 401];
        }

        if ($response->successful()) {
            $responseData = $response->json();

            Log::info('API password updated successfully', [
                'api_response' => $responseData,
            ]);

            return [
                'success' => true,
                'message' => $responseData['message'] ?? 'Mot de passe mis à jour avec succès',
                'status' => 200,
            ];
        }

        $errorData = $response->json();
        $errorMessage = $errorData['message'] ?? 'Échec de la mise à jour du mot de passe';

        Log::error('API password update failed', [
            'status' => $response->status(),
            'error' => $errorMessage,
        ]);

        return ['success' => false, 'message' => $errorMessage, 'status' => $response->status()];
    } catch (\Exception $e) {
        Log::error('API password update exception', [
            'error' => $e->getMessage(),
        ]);

        ['message' => $friendlyMessage, 'status' => $status] = extractApiExceptionMessage($e);

        return ['success' => false, 'message' => $friendlyMessage, 'status' => $status];
    }
}
