<?php

namespace App\Livewire\Settings;

use App\Models\Affiliate;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\RateLimiter;
use Livewire\Attributes\Url;
use Livewire\Component;

class Index extends Component
{
    // ── Tab ───────────────────────────────────────────────────────────────
    #[Url(as: 'tab')]
    public string $activeTab = 'profile';

    // ── Profil ────────────────────────────────────────────────────────────
    public string $name     = '';
    public string $email    = '';
    public string $timezone = '';
    public string $locale   = '';

    // ── Benachrichtigungen ────────────────────────────────────────────────
    public bool $reminders_enabled = true;
    public bool $notify_in_app     = true;
    public bool $notify_email      = false;
    public bool $pushEnabled       = false;
    public bool $emailEnabled      = false;

    // ── SMTP ──────────────────────────────────────────────────────────────
    public ?string $smtp_host       = null;
    public ?string $smtp_port       = null;
    public ?string $smtp_user       = null;
    public string  $smtp_password   = '';
    public string  $smtp_encryption = 'tls';
    public string  $smtpStatus      = '';
    public string  $smtpError       = '';
    public int     $emailsSentToday = 0;

    // ── Passwort ──────────────────────────────────────────────────────────
    public string $current_password          = '';
    public string $new_password              = '';
    public string $new_password_confirmation = '';

    protected $listeners = [
        'smtp:test' => 'testSmtp',
    ];

    // ── Mount ─────────────────────────────────────────────────────────────

    public function mount(): void
    {
        $user     = auth()->user();
        $settings = $user->settings ?? [];

        $this->name     = $user->name;
        $this->email    = $user->email;
        $this->timezone = $user->timezone ?? 'UTC';
        $this->locale   = $user->locale   ?? app()->getLocale();

        $this->reminders_enabled = (bool) ($settings['reminders_enabled'] ?? true);
        $this->notify_in_app     = (bool) ($settings['notify_in_app']     ?? true);
        $this->notify_email      = (bool) ($settings['notify_email']      ?? false);

        $notifSettings      = $user->notification_settings ?? [];
        $this->pushEnabled  = (bool) ($notifSettings['push_enabled']  ?? false);
        $this->emailEnabled = (bool) ($notifSettings['email_enabled'] ?? false);

        $this->smtp_host       = $settings['smtp_host']       ?? null;
        $this->smtp_port       = $settings['smtp_port']       ?? null;
        $this->smtp_user       = $settings['smtp_user']       ?? null;
        $this->smtp_password   = ($settings['smtp_password'] ?? null) ? '*******' : '';
        $this->smtp_encryption = $settings['smtp_encryption'] ?? 'tls';

        $this->emailsSentToday = $user->emailLogs()
            ->whereDate('created_at', today())
            ->count();
    }

    // ── Profil speichern ──────────────────────────────────────────────────

    public function saveProfile(): void
    {
        $this->validate(
            [
                'name'     => ['required'],
                'email'    => ['required', 'email'],
                'timezone' => ['required', 'timezone'],
                'locale'   => ['required', 'in:' . implode(',', array_keys(config('app.locales')))],
            ],
            [
                'name.required'     => t('settings.validation.name_required'),
                'email.required'    => t('settings.validation.email_required'),
                'email.email'       => t('settings.validation.email_invalid'),
                'locale.required'   => t('settings.validation.locale_required'),
                'locale.in'         => t('settings.validation.locale_invalid'),
            ]
        );

        auth()->user()->update([
            'name'     => $this->name,
            'email'    => $this->email,
            'timezone' => $this->timezone,
            'locale'   => $this->locale,
        ]);

        app()->setLocale($this->locale);
        session(['locale' => $this->locale]);

        $this->dispatch('notify', ['type' => 'success', 'message' => t('settings.profile.saved')]);
    }

    // ── Benachrichtigungen + SMTP speichern ───────────────────────────────

    public function saveSettings(): void
    {
        $user     = auth()->user();
        $settings = $user->settings ?? [];

        $user->update([
            'settings' => [
                'reminders_enabled' => $this->reminders_enabled,
                'notify_in_app'     => $this->notify_in_app,
                'notify_email'      => $this->notify_email,

                'smtp_host'       => $this->smtp_host,
                'smtp_port'       => $this->smtp_port,
                'smtp_user'       => $this->smtp_user,
                'smtp_encryption' => $this->smtp_encryption,

                // Passwort nur überschreiben wenn geändert
                'smtp_password' => ($this->smtp_password && $this->smtp_password !== '*******')
                    ? encrypt($this->smtp_password)
                    : ($settings['smtp_password'] ?? null),
            ],
        ]);

        $this->dispatch('notify', ['type' => 'success', 'message' => t('settings.saved')]);
    }

    // ── Passwort ändern ───────────────────────────────────────────────────

    public function updatePassword(): void
    {
        $this->validate([
            'current_password' => ['required'],
            'new_password'     => ['required', 'min:6', 'confirmed'],
        ], [
            'current_password.required'  => t('settings.validation.current_password_required'),
            'new_password.required'      => t('settings.validation.new_password_required'),
            'new_password.min'           => t('settings.validation.new_password_min'),
            'new_password.confirmed'     => t('settings.validation.new_password_confirmed'),
        ]);

        $user = auth()->user();

        if (!Hash::check($this->current_password, $user->password)) {
            $this->addError('current_password', t('settings.validation.current_password_wrong'));
            return;
        }

        $user->update(['password' => Hash::make($this->new_password)]);

        $this->reset(['current_password', 'new_password', 'new_password_confirmation']);

        $this->dispatch('notify', ['type' => 'success', 'message' => t('settings.password.saved')]);
    }

    // ── Push / Email Toggle ───────────────────────────────────────────────

    public function updatedPushEnabled(): void
    {
        $this->saveNotificationSettings();
    }

    public function updatedEmailEnabled(): void
    {
        $this->saveNotificationSettings();
    }

    private function saveNotificationSettings(): void
    {
        $user = auth()->user();

        $user->update([
            'notification_settings' => [
                'push_enabled'  => $this->pushEnabled,
                'email_enabled' => $this->emailEnabled,
            ],
        ]);

        // Devices aktivieren/deaktivieren je nach Push-Wunsch
        $user->devices()->update(['active' => $this->pushEnabled]);
    }

    // ── SMTP Test (via Mailable) ──────────────────────────────────────────

    public function sendTestMail(): void
    {
        $user = auth()->user();

        if (!RateLimiter::attempt('smtp-test:' . $user->id, 3, function () {})) {
            $this->smtpStatus = 'error';
            $this->smtpError  = 'Bitte warte 1 Minute zwischen Tests.';
            return;
        }

        try {
            $settings = $user->settings ?? [];
            $config   = $user->smtp_settings ?? [];

            $host = $config['host'] ?? $settings['smtp_host'] ?? null;

            if (empty($host)) {
                $this->smtpStatus = 'error';
                $this->smtpError  = 'Kein SMTP Server konfiguriert.';
                return;
            }

            $password = ($this->smtp_password && $this->smtp_password !== '*******')
                ? $this->smtp_password
                : (isset($settings['smtp_password']) ? decrypt($settings['smtp_password']) : null);

            if (!$password) {
                $this->smtpStatus = 'error';
                $this->smtpError  = 'SMTP-Passwort fehlt.';
                return;
            }

            Config::set('mail.mailers.user_smtp', [
                'transport'  => 'smtp',
                'host'       => $this->smtp_host ?? $host,
                'port'       => (int) ($this->smtp_port ?? $config['port'] ?? 587),
                'encryption' => $this->smtp_encryption === 'null' ? null : ($this->smtp_encryption ?? 'tls'),
                'username'   => $this->smtp_user ?? $config['username'],
                'password'   => $password,
                'from'       => [
                    'address' => $config['from_address'] ?? $user->email,
                    'name'    => $config['from_name']    ?? $user->name,
                ],
                'timeout'    => 10,
            ]);

            Mail::mailer('user_smtp')
                ->to($user->email)
                ->send(new \App\Mail\SmtpTestMail($user));

            $this->smtpStatus = 'success';

        } catch (\Throwable $e) {
            $this->smtpStatus = 'error';
            $this->smtpError  = $e->getMessage();
        }
    }

    // ── SMTP testen (Legacy — dispatch) ──────────────────────────────────

    public function testSmtp(): void
    {
        if (!$this->smtp_host || !$this->smtp_port || !$this->smtp_user) {
            $this->dispatch('notify', ['type' => 'error', 'message' => t('settings.smtp.invalid_config')]);
            return;
        }

        try {
            $settings = auth()->user()->settings ?? [];

            $password = ($this->smtp_password && $this->smtp_password !== '*******')
                ? $this->smtp_password
                : (isset($settings['smtp_password']) ? decrypt($settings['smtp_password']) : null);

            if (!$password) {
                throw new \RuntimeException('SMTP-Passwort fehlt.');
            }

            Config::set('mail.default', 'smtp');
            Config::set('mail.mailers.smtp', [
                'transport'  => 'smtp',
                'host'       => $this->smtp_host,
                'port'       => (int) $this->smtp_port,
                'username'   => $this->smtp_user,
                'password'   => $password,
                'encryption' => $this->smtp_encryption === 'null' ? null : $this->smtp_encryption,
                'timeout'    => 10,
            ]);

            Mail::raw(t('settings.smtp.test_mail_body'), function ($msg) {
                $msg->to(auth()->user()->email)->subject(t('settings.smtp.test_mail_subject'));
            });

            $this->dispatch('notify', ['type' => 'success', 'message' => t('settings.smtp.success')]);

        } catch (\Throwable $e) {
            $this->dispatch('openModal', 'settings.modals.smtp-error', ['message' => $e->getMessage()]);
        }
    }

    // ── Affiliate ─────────────────────────────────────────────────────────

    public function joinAffiliate(): void
    {
        $user = auth()->user();

        if ($user->isInternalUser() || $user->affiliate) {
            return;
        }

        Affiliate::create([
            'user_id' => $user->id,
            'code'    => Affiliate::generateCode($user),
            'status'  => 'active',
        ]);

        $this->dispatch('notify', ['type' => 'success', 'message' => 'Du nimmst jetzt am Affiliate-Programm teil!']);
    }

    // ── Computed ──────────────────────────────────────────────────────────

    public function getCanTestSmtpProperty(): bool
    {
        return (bool) ($this->smtp_host
            && $this->smtp_port
            && $this->smtp_user
            && ($this->smtp_password || isset(auth()->user()->settings['smtp_password'])));
    }

    public function render()
    {
        $affiliate = auth()->user()->affiliate;
        $referrals = $affiliate?->referrals()
            ->with('referredUser')
            ->latest()
            ->get() ?? collect();

        $user = auth()->user();

        // Echte Nutzung aus agent_logs (Chat, Aktionen) — Label priorisiert
        // output.title (z.B. "Friseurtermin Huber") vor dem rohen User-Input.
        $logItems = $user->agentLogs()
            ->latest()
            ->limit(20)
            ->get()
            ->map(fn ($log) => (object) [
                'source'      => 'log',
                'type'        => $log->type ?? 'chat',
                'label'       => $log->output['title'] ?? $log->input ?? $log->type,
                'amount'      => -$log->credits,
                'duration_ms' => $log->duration_ms,
                'created_at'  => $log->created_at,
            ]);

        // Bonus-Bewegungen aus credit_transactions
        $txItems = $user->creditTransactions()
            ->latest()
            ->limit(20)
            ->get()
            ->map(fn ($tx) => (object) [
                'source'      => 'transaction',
                'type'        => $tx->type,
                'label'       => $tx->description,
                'amount'      => $tx->amount,
                'duration_ms' => null,
                'created_at'  => $tx->created_at,
            ]);

        // Zusammenführen, chronologisch, auf 20 begrenzen
        $creditTransactions = $logItems
            ->concat($txItems)
            ->sortByDesc('created_at')
            ->take(20)
            ->values();

        $creditBalance = $user->credit_balance;
        $planLimit     = $user->subscription?->plan?->credit_limit ?? 0;
        $bonusLeft     = $user->bonus_credits;
        $monthUsage    = $user->monthly_usage;
        $effLimit      = $user->effective_limit;

        return view('livewire.settings.index', compact(
            'affiliate', 'referrals', 'creditTransactions',
            'creditBalance', 'planLimit', 'bonusLeft', 'monthUsage', 'effLimit'
        ))->layout('layouts.app');
    }
}
