<?php

namespace App\Http\Livewire;

use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Mail;
use Livewire\Component;
use App\Http\Middleware\TenantMiddleware;
use Illuminate\Support\Facades\Auth;

class User extends Component
{
    public function boot()
    {
        app(TenantMiddleware::class)->setupTenantConnection();
        $this->logCurrentDatabase('After tenant connection setup in boot()');
    }

    public $records, $name, $cognome, $email, $password, $oldPassword, $level, $enabled, $dataId, $update = false, $add = false, $oldEmail = null;
    public $userExists = false;

    protected $rules = [
        'name' => 'required',
        'cognome' => 'required',
        'email' => 'required',
        'password' => 'required'
    ];

    protected $messages = [
        'name.required' => 'Il nome è obbligatorio',
        'cognome.required' => 'Il cognome è obbligatorio',
        'email.required' => 'La mail è obbligatoria',
        'password.required' => 'La password è obbligatoria',
    ];

    /**
     * Helper method to log current database information
     */
    private function logCurrentDatabase($context = '')
    {
        try {
            $currentConnection = DB::getDefaultConnection();
            $currentDatabase = DB::connection()->getDatabaseName();
            $user = Auth::user();

            Log::info('Database Connection Info', [
                'context' => $context,
                'current_connection' => $currentConnection,
                'current_database' => $currentDatabase,
                'user_id' => $user ? $user->id : null,
                'user_tenant_database' => $user ? $user->tenant_database : null,
                'user_tenant_username' => $user ? $user->tenant_username : null,
            ]);
        } catch (\Exception $e) {
            Log::error('Failed to get database info', [
                'context' => $context,
                'error' => $e->getMessage()
            ]);
        }
    }

    /**
     * Create or update user in master database
     */
    private function syncUserToMasterDatabase($userData, $action = 'create', $oldEmail = null)
    {
        try {
            Log::info('Syncing user to master database', [
                'action' => $action,
                'email' => $userData['email'],
                'old_email' => $oldEmail
            ]);

            $masterConfig = [
                'driver' => 'mysql',
                'host' => env('DB_HOST', '127.0.0.1'),
                'port' => env('DB_PORT', '3306'),
                'database' => env('DB_DATABASE'),
                'username' => env('DB_USERNAME'),
                'password' => env('DB_PASSWORD'),
                'charset' => 'utf8mb4',
                'collation' => 'utf8mb4_unicode_ci',
                'prefix' => '',
                'strict' => true,
                'engine' => null,
            ];

            config(['database.connections.master_sync' => $masterConfig]);

            $currentUser = Auth::user();

            $masterData = [
                'name' => $userData['name'],
                'email' => $userData['email'],
                'password' => $userData['password'],
                'tenant_database' => $currentUser->tenant_database,
                'tenant_username' => $currentUser->tenant_username,
                'tenant_password' => $currentUser->tenant_password,
                'tenant_host' => '127.0.0.1',
                'created_at' => now(),
                'updated_at' => now()
            ];

            if ($action === 'create') {
                $inserted = DB::connection('master_sync')
                    ->table('users')
                    ->insert($masterData);

                if ($inserted) {
                    Log::info('Successfully created user in master database', [
                        'email' => $userData['email'],
                        'tenant_database' => $currentUser->tenant_database
                    ]);
                    return true;
                } else {
                    Log::warning('Failed to create user in master database', [
                        'email' => $userData['email']
                    ]);
                    return false;
                }
            } elseif ($action === 'update') {
                $searchEmail = $oldEmail ?: $userData['email'];

                unset($masterData['created_at']);

                $updated = DB::connection('master_sync')
                    ->table('users')
                    ->where('email', $searchEmail)
                    ->update($masterData);

                if ($updated) {
                    Log::info('Successfully updated user in master database', [
                        'old_email' => $searchEmail,
                        'new_email' => $userData['email']
                    ]);
                    return true;
                } else {
                    Log::warning('No user found in master database to update', [
                        'search_email' => $searchEmail
                    ]);
                    return false;
                }
            }
        } catch (\Exception $e) {
            Log::error('Failed to sync user to master database', [
                'action' => $action,
                'email' => $userData['email'],
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString()
            ]);
            return false;
        } finally {
            // Clean up the temporary connection
            try {
                DB::purge('master_sync');
            } catch (\Exception $e) {
                // Ignore cleanup errors
            }
        }
    }

    /**
     * Delete user from master database
     */
    private function deleteUserFromMasterDatabase($email)
    {
        try {
            Log::info('Deleting user from master database', [
                'email' => $email
            ]);

            $masterConfig = [
                'driver' => 'mysql',
                'host' => env('DB_HOST', '127.0.0.1'),
                'port' => env('DB_PORT', '3306'),
                'database' => env('DB_DATABASE'),
                'username' => env('DB_USERNAME'),
                'password' => env('DB_PASSWORD'),
                'charset' => 'utf8mb4',
                'collation' => 'utf8mb4_unicode_ci',
                'prefix' => '',
                'strict' => true,
                'engine' => null,
            ];

            config(['database.connections.master_delete' => $masterConfig]);

            $deleted = DB::connection('master_delete')
                ->table('users')
                ->where('email', $email)
                ->delete();

            if ($deleted) {
                Log::info('Successfully deleted user from master database', [
                    'email' => $email,
                    'rows_affected' => $deleted
                ]);
                return true;
            } else {
                Log::warning('No user found in master database to delete', [
                    'email' => $email
                ]);
                return false;
            }
        } catch (\Exception $e) {
            Log::error('Failed to delete user from master database', [
                'email' => $email,
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString()
            ]);
            return false;
        } finally {
            try {
                DB::purge('master_delete');
            } catch (\Exception $e) {
            }
        }
    }

    /**
     * Send welcome email to new user
     */
    private function sendWelcomeEmail($userData, $plainPassword)
    {
        try {
            $currentUser = Auth::user();
            $companyName = 'Leezard';

            Log::info('Preparing to send welcome email', [
                'recipient' => $userData['email'],
                'company' => $companyName,
                'mail_from' => config('mail.from.address'),
                'mail_host' => config('mail.mailers.smtp.host'),
                'mail_port' => config('mail.mailers.smtp.port')
            ]);

            $emailData = [
                'name' => $userData['name'],
                'cognome' => $userData['cognome'],
                'email' => $userData['email'],
                'password' => $plainPassword,
                'level' => $userData['level'],
                'company' => $companyName,
                'login_url' => url('/'),
                'created_by' => $currentUser->name
            ];

            try {
                $viewContent = view('emails.welcome-user', $emailData)->render();
                Log::info('Email template rendered successfully', ['template_length' => strlen($viewContent)]);
            } catch (\Exception $viewException) {
                Log::error('Email template rendering failed', ['error' => $viewException->getMessage()]);
                throw new \Exception('Email template error: ' . $viewException->getMessage());
            }

            Mail::send('emails.welcome-user', $emailData, function ($message) use ($userData, $companyName) {
                $message->to($userData['email'], $userData['name'] . ' ' . $userData['cognome'])
                    ->subject('Benvenuto su Leezard - Account Creato')
                    ->from(config('mail.from.address'), config('mail.from.name'));

                if (env('MAIL_CCN')) {
                    $message->bcc(env('MAIL_CCN'));
                }
            });

            Log::info('Welcome email sent successfully', [
                'recipient' => $userData['email'],
                'company' => $companyName,
                'subject' => 'Benvenuto in ' . $companyName . ' - Account Creato'
            ]);

            return true;
        } catch (\Exception $e) {
            Log::error('SMTP Transport error when sending welcome email', [
                'recipient' => $userData['email'],
                'error' => $e->getMessage(),
                'mail_config' => [
                    'host' => config('mail.mailers.smtp.host'),
                    'port' => config('mail.mailers.smtp.port'),
                    'encryption' => config('mail.mailers.smtp.encryption'),
                    'username' => config('mail.mailers.smtp.username')
                ]
            ]);
            return false;
        } catch (\Exception $e) {
            Log::error('General error when sending welcome email', [
                'recipient' => $userData['email'],
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString()
            ]);
            return false;
        }
    }
    public function sendSimpleWelcomeEmail($email, $userData)
    {
        try {
            $subject = "Benvenuto su " . $userData['company'] . " – Account Creato";

            $message = "Ciao " . $userData['name'] . " " . $userData['cognome'] . ",\n\n";
            $message .= "Il tuo account è stato creato con successo su " . $userData['company'] . ".\n\n";
            $message .= "Le tue credenziali di accesso:\n";
            $message .= "Email: " . $userData['email'] . "\n";
            $message .= "Password: " . $userData['password'] . "\n\n";
            $message .= "Per motivi di sicurezza, dovrai cambiare la password al primo accesso.\n\n";
            $message .= "Accedi ora: " . $userData['login_url'] . "\n\n";
            $message .= "Grazie e benvenuto!\n";
            $message .= "Il team di " . $userData['company'];

            // Send simple text email
            mail($email, $subject, $message, [
                'From' => config('mail.from.address'),
                'Reply-To' => config('mail.from.address'),
                'Content-Type' => 'text/plain; charset=UTF-8'
            ]);

            return true;
        } catch (\Exception $e) {
            Log::error('Simple email sending failed', [
                'email' => $email,
                'error' => $e->getMessage()
            ]);
            return false;
        }
    }
    public function resetFields()
    {
        $this->name = '';
        $this->cognome = '';
        $this->email = '';
        $this->password = '';
        $this->oldPassword = '';
        $this->level = 0;
        $this->enabled = true;
        $this->emit('load-data-table');
    }

    public function render()
    {
        $this->logCurrentDatabase('Before fetching users in render()');

        $this->records = \App\Models\User::select('id', 'name', 'cognome', 'email', 'password', 'level', 'enabled')->get();

        $this->logCurrentDatabase('After fetching users in render()');

        return view('livewire.user');
    }

    public function add()
    {
        if (!$this->canAddUser()) {
            session()->flash('error', 'Non hai i permessi per aggiungere utenti.');
            return;
        }

        $this->logCurrentDatabase('In add() method');

        $this->resetFields();
        $this->add = true;
        $this->update = false;
        $this->enabled = true;
        $this->userExists = false;
    }

    public function store()
    {
        if (!$this->canAddUser()) {
            session()->flash('error', 'Non hai i permessi per aggiungere utenti.');
            return;
        }

        $this->logCurrentDatabase('Start of store() method');

        Log::info('User store', [
            'name' => $this->name,
            'cognome' => $this->cognome,
            'email' => $this->email,
            'level' => $this->level,
            'enabled' => $this->enabled
        ]);

        $rules = [
            'name' => 'required',
            'cognome' => 'required',
            'email' => 'required|email|unique:users,email',
            'password' => 'required|min:6'
        ];

        $messages = [
            'name.required' => 'Il nome è obbligatorio',
            'cognome.required' => 'Il cognome è obbligatorio',
            'email.required' => 'La mail è obbligatoria',
            'email.email' => 'La mail deve essere un indirizzo valido',
            'email.unique' => 'Questa mail è già stata utilizzata',
            'password.required' => 'La password è obbligatoria',
            'password.min' => 'La password deve essere di almeno 6 caratteri'
        ];

        $this->validate($rules, $messages);

        $this->logCurrentDatabase('Before creating user in store()');

        try {
            $plainPassword = $this->password;

            $hashedPassword = bcrypt($this->password);

            $user = \App\Models\User::create([
                'name' => $this->name,
                'cognome' => $this->cognome,
                'email' => $this->email,
                'password' => $hashedPassword,
                'level' => $this->level,
                'enabled' => $this->enabled
            ]);

            $this->logCurrentDatabase('After creating user in tenant database');

            Log::info('User created successfully in tenant database', [
                'user_id' => $user->id,
                'name' => $this->name,
                'cognome' => $this->cognome,
                'email' => $this->email,
                'level' => $this->level,
                'enabled' => $this->enabled,
                'database' => DB::connection()->getDatabaseName()
            ]);

            $masterSyncSuccess = $this->syncUserToMasterDatabase([
                'name' => $this->name,
                'cognome' => $this->cognome,
                'email' => $this->email,
                'password' => $hashedPassword,
                'level' => $this->level,
                'enabled' => $this->enabled
            ], 'create');

            if ($masterSyncSuccess) {
                $emailSent = $this->sendWelcomeEmail([
                    'name' => $this->name,
                    'cognome' => $this->cognome,
                    'email' => $this->email,
                    'level' => $this->level
                ], $plainPassword);

                if (!$emailSent) {
                    Log::info('HTML email failed, trying simple email', ['email' => $this->email]);
                    $emailSent = $this->sendSimpleWelcomeEmail($this->email, [
                        'name' => $this->name,
                        'cognome' => $this->cognome,
                        'email' => $this->email,
                        'password' => $plainPassword,
                        'level' => $this->level,
                        'company' => 'Leezard',
                        'login_url' => url('/')
                    ]);
                }

                if ($emailSent) {
                    session()->flash('success', 'Utente creato e email di benvenuto inviata con successo');
                } else {
                    session()->flash('success', 'Utente creato ma errore nell\'invio dell\'email. Controlla i log per dettagli.');
                }
            } else {
                session()->flash('success', 'Utente creato nel database tenant ma errore nella sincronizzazione master');
            }

            $this->resetFields();
            $this->add = false;
        } catch (\Exception $ex) {
            $this->logCurrentDatabase('Error in store() method');

            Log::error('User creation failed', [
                'error' => $ex->getMessage(),
                'database' => DB::connection()->getDatabaseName(),
                'user_data' => [
                    'name' => $this->name,
                    'cognome' => $this->cognome,
                    'email' => $this->email,
                    'level' => $this->level,
                    'enabled' => $this->enabled
                ]
            ]);

            session()->flash('error', 'Errore (' . $ex->getMessage() . ')');
        }
    }

    public function edit($id)
    {
        if (!$this->canEditUser($id)) {
            session()->flash('error', 'Non hai i permessi per modificare questo utente.');
            return;
        }

        $this->logCurrentDatabase('Start of edit() method');

        try {
            $user = \App\Models\User::findOrFail($id);

            $this->logCurrentDatabase('After finding user in edit()');

            if (!$user) {
                session()->flash('error', 'Utente non trovato');
            } else {
                $this->name = $user->name;
                $this->cognome = $user->cognome;
                $this->email = $user->email;
                $this->level = $user->level;
                $this->dataId = $user->id;
                $this->update = true;
                $this->add = false;
                $this->enabled = $user->enabled;
                $this->userExists = true;
                // Store old email for master database update
                $this->oldEmail = $user->email;
            }

            Log::info('User edit loaded', [
                'user_id' => $id,
                'name' => $this->name,
                'cognome' => $this->cognome,
                'email' => $this->email,
                'level' => $this->level,
                'database' => DB::connection()->getDatabaseName()
            ]);
        } catch (\Exception $ex) {
            $this->logCurrentDatabase('Error in edit() method');

            Log::error('User edit failed', [
                'user_id' => $id,
                'error' => $ex->getMessage(),
                'database' => DB::connection()->getDatabaseName()
            ]);

            session()->flash('error', 'Errore (' . $ex->getMessage() . ')');
        }
    }


    public function update()
    {
        $this->logCurrentDatabase('Start of update() method');

        $rules = [
            'name' => 'required',
            'cognome' => 'required',
            'email' => 'required|email',
            'password' => 'nullable|min:6'
        ];

        $this->validate($rules, $this->messages);

        try {
            $currentUser = \App\Models\User::findOrFail($this->dataId);
            $oldEmail = $currentUser->email;
            $oldName = $currentUser->name;

            $updateData = [
                'name' => $this->name,
                'cognome' => $this->cognome,
                'email' => $this->email,
                'level' => $this->level,
                'enabled' => $this->enabled
            ];

            $passwordChanged = !empty($this->password);
            if ($passwordChanged) {
                $hashedPassword = bcrypt($this->password);
                $updateData['password'] = $hashedPassword;
            }

            \App\Models\User::whereId($this->dataId)->update($updateData);

            $this->logCurrentDatabase('After updating user');

            Log::info('User updated successfully in tenant database', [
                'user_id' => $this->dataId,
                'name' => $this->name,
                'cognome' => $this->cognome,
                'email' => $this->email,
                'level' => $this->level,
                'enabled' => $this->enabled,
                'password_changed' => $passwordChanged,
                'database' => DB::connection()->getDatabaseName()
            ]);

            $emailChanged = $oldEmail !== $this->email;
            $nameChanged = $oldName !== $this->name;

            if ($emailChanged || $nameChanged || $passwordChanged) {
                $masterData = [
                    'name' => $this->name,
                    'email' => $this->email
                ];

                if ($passwordChanged) {
                    $masterData['password'] = $hashedPassword;
                }

                $this->syncUserToMasterDatabase($masterData, 'update', $oldEmail);
            }

            session()->flash('success', 'Dato aggiornato');
            $this->resetFields();
            $this->update = false;
        } catch (\Exception $ex) {
            $this->logCurrentDatabase('Error in update() method');

            Log::error('User update failed', [
                'user_id' => $this->dataId,
                'error' => $ex->getMessage(),
                'database' => DB::connection()->getDatabaseName()
            ]);

            session()->flash('error', 'Errore (' . $ex->getMessage() . ')');
        }
    }

    public function cancel()
    {
        $this->logCurrentDatabase('In cancel() method');

        $this->resetFields();
        $this->add = false;
        $this->update = false;
        $this->userExists = false;
        $this->enabled = false;
    }

    public function delete($id)
    {
        Log::info('Delete method called', [
            'user_id_to_delete' => $id,
            'current_user_id' => Auth::id(),
            'current_user_level' => Auth::user()->level
        ]);

        if (!$this->canDeleteUser($id)) {
            Log::warning('Delete permission denied', [
                'user_id_to_delete' => $id,
                'current_user_id' => Auth::id(),
                'current_user_level' => Auth::user()->level
            ]);
            session()->flash('error', 'Non hai i permessi per eliminare questo utente.');
            return;
        }

        $this->logCurrentDatabase('Start of delete() method');

        try {
            $user = \App\Models\User::find($id);

            if (!$user) {
                Log::error('User not found for deletion', ['user_id' => $id]);
                session()->flash('error', 'Utente non trovato.');
                return;
            }

            $userEmail = $user->email;
            $userName = $user->name;
            $userCognome = $user->cognome;

            Log::info('Found user for deletion', [
                'user_id' => $id,
                'user_email' => $userEmail,
                'user_name' => $userName . ' ' . $userCognome
            ]);

            $deleted = $user->delete();

            if (!$deleted) {
                throw new \Exception('Failed to delete user from tenant database');
            }

            $this->logCurrentDatabase('After deleting user from tenant');

            Log::info('User deleted successfully from tenant database', [
                'user_id' => $id,
                'user_email' => $userEmail,
                'database' => DB::connection()->getDatabaseName()
            ]);

            $masterDeleted = $this->deleteUserFromMasterDatabase($userEmail);

            if ($masterDeleted) {
                Log::info('User deleted from both databases successfully', [
                    'user_id' => $id,
                    'user_email' => $userEmail
                ]);
                session()->flash('success', "Utente {$userName} {$userCognome} eliminato con successo");
            } else {
                Log::warning('User deleted from tenant but failed to delete from master', [
                    'user_id' => $id,
                    'user_email' => $userEmail
                ]);
                session()->flash('success', "Utente eliminato dal database tenant, ma errore nella sincronizzazione master");
            }

            $this->emit('userDeleted');
            $this->emit('load-data-table');
        } catch (\Exception $e) {
            $this->logCurrentDatabase('Error in delete() method');

            Log::error('User deletion failed', [
                'user_id' => $id,
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString(),
                'database' => DB::connection()->getDatabaseName()
            ]);

            session()->flash('error', 'Errore durante l\'eliminazione: ' . $e->getMessage());
        }
    }


    private function canEditUser($userId)
    {
        $currentUser = Auth::user();

        if ($currentUser->level == 0) {
            $targetUser = \App\Models\User::find($userId);
            return $targetUser && $targetUser->email != 'admin@admin.com';
        }

        return $userId == $currentUser->id;
    }

    /**
     * Check if current user can edit email and password of a specific user
     */
    private function canEditEmailAndPassword($userId)
    {
        $currentUser = Auth::user();

        return $userId == $currentUser->id;
    }

    /**
     * Check if current user can delete a specific user
     */
    private function canDeleteUser($userId)
    {
        $currentUser = Auth::user();

        if ($currentUser->level != 0) {
            return false;
        }

        if ($userId == $currentUser->id) {
            return false;
        }

        $targetUser = \App\Models\User::find($userId);
        if ($targetUser && $targetUser->email == 'admin@admin.com') {
            return false;
        }

        return true;
    }

    /**
     * Check if current user can add users
     */
    private function canAddUser()
    {
        $currentUser = Auth::user();
        return $currentUser->level == 0;
    }
}
