<?php

namespace App\Livewire\Admin\Users;

use App\Enums\SubscriptionStatus;
use App\Enums\UserRole;
use App\Models\Activity;
use App\Models\AgentLog;
use App\Models\CreditTransaction;
use App\Models\Plan;
use App\Models\User;
use Illuminate\Support\Facades\Gate;
use Illuminate\Support\Facades\Mail;
use Livewire\Component;
use Livewire\WithPagination;

class Detail extends Component
{
    use WithPagination;

    public User $user;

    // Credits
    public int $creditAmount = 0;
    public string $creditReason = '';

    // Gift Access
    public string $giftPlanId = '';
    public string $giftDuration = '1_month';
    public string $giftReason = '';

    // Rolle
    public string $newRole = '';

    public function mount(User $user)
    {
        $this->user = $user;
        $this->newRole = $user->role->value;
    }

    public function giveCredits()
    {
        $this->validate([
            'creditAmount' => 'required|integer|min:1|max:10000',
            'creditReason' => 'required|string|max:255',
        ]);

        CreditTransaction::adminGift(
            $this->user,
            $this->creditAmount,
            $this->creditReason,
            auth()->user()
        );

        $this->dispatch('notify', type: 'success', message: $this->creditAmount . ' Credits an ' . $this->user->name . ' vergeben.');

        $this->creditAmount = 0;
        $this->creditReason = '';
        $this->user->refresh();
    }

    public function giftAccess()
    {
        $this->validate([
            'giftPlanId'  => 'required|exists:plans,id',
            'giftDuration' => 'required|in:1_month,3_months,6_months,1_year,forever',
            'giftReason'  => 'nullable|string|max:255',
        ]);

        $plan = Plan::findOrFail($this->giftPlanId);

        $endsAt = match($this->giftDuration) {
            '1_month'  => now()->addMonth(),
            '3_months' => now()->addMonths(3),
            '6_months' => now()->addMonths(6),
            '1_year'   => now()->addYear(),
            'forever'  => null,
        };

        $durationLabel = match($this->giftDuration) {
            '1_month'  => '1 Monat',
            '3_months' => '3 Monate',
            '6_months' => '6 Monate',
            '1_year'   => '1 Jahr',
            'forever'  => 'Unbegrenzt',
        };

        // Bestehende aktive Subscriptions deaktivieren
        $this->user->subscriptions()
            ->whereIn('status', [SubscriptionStatus::Active->value, SubscriptionStatus::Gifted->value])
            ->update(['status' => SubscriptionStatus::Superseded->value]);

        // Neue Geschenk-Subscription erstellen
        $this->user->subscriptions()->create([
            'plan_id'    => $plan->id,
            'plan_name'  => $plan->name,
            'plan_slug'  => $plan->plan_key ?? str($plan->name)->slug(),
            'price'      => 0,
            'interval'   => 'gifted',
            'status'     => SubscriptionStatus::Gifted->value,
            'starts_at'  => now(),
            'ends_at'    => $endsAt,
            'gifted_by'  => auth()->id(),
            'gifted_at'  => now(),
            'gift_reason' => $this->giftReason ?: null,
        ]);

        // Activity Log
        Activity::log(
            $this->user->id,
            'gift_access',
            "Admin hat {$plan->name} ({$durationLabel}) geschenkt",
            auth()->user()->name,
            meta: [
                'plan'       => $plan->name,
                'duration'   => $durationLabel,
                'ends_at'    => $endsAt?->toDateString() ?? 'unbegrenzt',
                'gifted_by'  => auth()->user()->name,
                'reason'     => $this->giftReason,
            ]
        );

        // Mail senden
        try {
            Mail::to($this->user->email)->send(
                new \App\Mail\GiftAccessMail($this->user, $plan, $durationLabel, $endsAt)
            );
        } catch (\Throwable $e) {
            report($e);
        }

        $this->dispatch('notify', type: 'success', message: "{$plan->name} für {$durationLabel} an {$this->user->name} vergeben.");

        $this->giftPlanId = '';
        $this->giftDuration = '1_month';
        $this->giftReason = '';
        $this->user->refresh();
    }

    public function revokeAccess()
    {
        $this->user->subscriptions()
            ->whereIn('status', [SubscriptionStatus::Active->value, SubscriptionStatus::Gifted->value])
            ->update([
                'status'  => SubscriptionStatus::Canceled->value,
                'ends_at' => now(),
            ]);

        // Auf Free-Plan zurücksetzen
        $freePlan = Plan::freePlan();

        if ($freePlan) {
            $this->user->subscriptions()->create([
                'plan_id'   => $freePlan->id,
                'plan_name' => $freePlan->name,
                'plan_slug' => $freePlan->plan_key ?? str($freePlan->name)->slug(),
                'price'     => 0,
                'interval'  => 'monthly',
                'status'    => SubscriptionStatus::Active->value,
                'starts_at' => now(),
                'ends_at'   => null,
            ]);
        }

        Activity::log(
            $this->user->id,
            'revoke_access',
            'Admin hat Zugang entzogen',
            auth()->user()->name,
        );

        $this->dispatch('notify', type: 'success', message: "Zugang von {$this->user->name} wurde entzogen.");
        $this->user->refresh();
    }

    public function deleteLog(string $logId)
    {
        $log = AgentLog::findOrFail($logId);
        abort_if($log->user_id !== $this->user->id, 403);

        $credits = $log->credits;

        CreditTransaction::refund(
            $this->user,
            $credits,
            'Log-Löschung durch Admin',
            $log->id,
            auth()->user()
        );

        $log->delete();

        $this->user->refresh();
        $this->dispatch('notify', type: 'success', message: $credits . ' Credits wurden zurückerstattet.');
    }

    public function updateStatus(string $status)
    {
        $this->user->update(['status' => $status]);
        $this->user->refresh();

        $this->dispatch('notify', type: 'success', message: 'Status aktualisiert.');
    }

    public function updateRole()
    {
        Gate::authorize('change-roles');

        $this->validate([
            'newRole' => 'required|in:' . implode(',', array_column(UserRole::cases(), 'value')),
        ]);

        $newRole = UserRole::from($this->newRole);

        // Super Admin kann sich nicht selbst degradieren
        if ($this->user->isSuperAdmin() && auth()->id() === $this->user->id) {
            $this->dispatch('notify', type: 'error', message: 'Du kannst deine eigene Super-Admin Rolle nicht ändern.');
            return;
        }

        // Niemand kann einen anderen Super Admin degradieren
        if ($this->user->isSuperAdmin() && $newRole !== UserRole::SuperAdmin) {
            $this->dispatch('notify', type: 'error', message: 'Super Admin Rollen können nicht geändert werden.');
            return;
        }

        $oldRole = $this->user->role;
        $this->user->update(['role' => $newRole->value]);

        // Auto-Plan-Zuweisung passend zur neuen Rolle
        $this->assignPlanForRole($newRole);

        Activity::log(
            $this->user->id,
            'role_change',
            "Rolle geändert: {$oldRole->label()} → {$newRole->label()}",
            auth()->user()->name,
            meta: [
                'old_role' => $oldRole->value,
                'new_role' => $newRole->value,
                'changed_by' => auth()->user()->name,
            ]
        );

        $this->user->refresh();
        $this->dispatch('notify', type: 'success', message: "Rolle auf {$newRole->label()} geändert.");
    }

    private function assignPlanForRole(UserRole $role): void
    {
        $planKey = match($role) {
            UserRole::SuperAdmin => 'internal',
            UserRole::Admin      => 'internal',
            UserRole::Developer  => 'developer',
            UserRole::Support    => 'support',
            UserRole::Affiliate  => 'affiliate',
            UserRole::BetaTester => 'beta_tester',
            UserRole::User       => null,
        };

        if ($planKey === null) {
            $plan = Plan::freePlan();
        } else {
            $plan = Plan::where('plan_key', $planKey)->first();
        }

        if (!$plan) return;

        // Bestehende aktive Subscription deaktivieren
        $this->user->subscriptions()
            ->whereIn('status', [SubscriptionStatus::Active->value, SubscriptionStatus::Gifted->value])
            ->update(['status' => SubscriptionStatus::Superseded->value]);

        // Neuen Plan zuweisen
        $this->user->subscriptions()->create([
            'plan_id'   => $plan->id,
            'plan_name' => $plan->name,
            'plan_slug' => $plan->plan_key ?? str($plan->name)->slug(),
            'price'     => 0,
            'interval'  => $planKey ? 'internal' : 'monthly',
            'status'    => SubscriptionStatus::Active->value,
            'starts_at' => now(),
            'ends_at'   => null,
        ]);
    }

    public function render()
    {
        $stats = [
            'events'      => $this->user->events()->count(),
            'notes'       => $this->user->notes()->count(),
            'tasks'       => $this->user->tasks()->count(),
            'contacts'    => $this->user->contacts()->count(),
            'creditsUsed' => $this->user->agentLogs()->where('created_at', '>=', now()->startOfMonth())->sum('credits'),
            'totalCost'   => $this->user->agentLogs()->sum('cost_usd'),
            'lastActive'  => $this->user->agentLogs()->latest()->value('created_at'),
        ];

        $logs = $this->user->agentLogs()->latest()->paginate(10);

        $activeSub = $this->user->subscriptions()
            ->whereIn('status', [SubscriptionStatus::Active->value, SubscriptionStatus::Gifted->value])
            ->with(['plan', 'gifter'])
            ->latest()
            ->first();

        $plans = Plan::public()->where('price', '>', 0)->orderBy('price')->get();

        $creditTx = $this->user->creditTransactions()->with('creator')->latest()->limit(15)->get();

        return view('livewire.admin.users.detail', compact('stats', 'logs', 'activeSub', 'plans', 'creditTx'))
            ->layout('layouts.app');
    }
}
