<?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;
    public $password_confirmation;
    public $master_user_id = null;

    protected $rules = [
        'name' => 'required',
        'cognome' => 'required',
        'email' => 'required',
        'password' => 'required',
        'password_confirmation' => 'required|same:password'
    ];

    protected $messages = [
        'name.required' => 'Il nome è obbligatorio',
        'cognome.required' => 'Il cognome è obbligatorio',
        'email.required' => 'La mail è obbligatoria',
        'password.required' => 'La password è obbligatoria',
        'password_confirmation.required' => 'Ripeti la password inserita',
        'password_confirmation.same' => 'Le password non coincidono',
    ];

    /**
     * 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()
            ]);
        }
    }

    /**
     * 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'];

            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->password_confirmation = '';
        $this->oldPassword = '';
        $this->level = 0;
        $this->enabled = true;
        $this->master_user_id = null;
        $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', 'master_user_id')->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',
            'password_confirmation' => 'required|same:password'
        ];

        $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',
            'password_confirmation.required' => 'Ripeti la password inserita',
            'password_confirmation.same' => 'Le password non coincidono',
        ];

        $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,
                'master_user_id' => null,
            ]);

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

            $this->master_user_id = $user->fresh()->master_user_id;

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

            $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.');
            }

            $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;
                $this->oldEmail = $user->email;
                $this->master_user_id = $user->master_user_id;
            }

            Log::info('User edit loaded', [
                'user_id' => $id,
                'master_user_id' => $this->master_user_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',
        ];

        if ($this->master_user_id == Auth::user()->id) {
            $rules['password_confirmation'] = 'required_with:password|same:password';
        }

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

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

            $passwordChanged = !empty($this->password);

            $currentUser->name = $this->name;
            $currentUser->cognome = $this->cognome;
            $currentUser->email = $this->email;
            $currentUser->level = $this->level;
            $currentUser->enabled = $this->enabled;

            if ($passwordChanged) {
                $currentUser->password = bcrypt($this->password);
            }

            $currentUser->save();

            $currentUser = $currentUser->fresh();
            $this->master_user_id = $currentUser->master_user_id;

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

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

            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;
            $masterUserId = $user->master_user_id;

            Log::info('Found user for deletion', [
                'user_id' => $id,
                'master_user_id' => $masterUserId,
                '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; master sync delegated to observer', [
                'user_id' => $id,
                'master_user_id' => $masterUserId,
                'user_email' => $userEmail,
                'database' => DB::connection()->getDatabaseName()
            ]);

            session()->flash('success', "Utente {$userName} {$userCognome} eliminato con successo");

            $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 $targetUser;
        }

        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;
    }
}
