<?php

namespace App\Http\Controllers;

use App\Models\Event;
use App\Models\PackagePurchase;
use App\Models\Tenant;
use App\Models\TenantPackage;
use App\Services\Tenant\DashboardSummaryService;
use App\Support\TenantOnboardingState;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Http\Request;
use Illuminate\Support\Arr;
use Illuminate\Support\Collection;
use Inertia\Inertia;

class DashboardController extends Controller
{
    public function __invoke(Request $request, DashboardSummaryService $summaryService)
    {
        $user = $request->user();

        if ($user && $user->role === 'tenant_admin') {
            $returnTarget = $this->consumeTenantAdminTarget($request);

            if ($returnTarget !== null) {
                return redirect($returnTarget);
            }
        }

        // Block users with 'user' role from accessing dashboard
        if ($user && $user->role === 'user') {
            return redirect('/packages');
        }

        $tenant = $user?->tenant;

        $summary = $tenant instanceof Tenant
            ? $summaryService->build($tenant)
            : null;

        $events = $tenant instanceof Tenant
            ? $this->collectUpcomingEvents($tenant)
            : collect();

        $purchases = $tenant instanceof Tenant
            ? $this->collectRecentPurchases($tenant)
            : collect();

        $activePackage = $summary['active_package'] ?? null;
        $onboarding = $tenant instanceof Tenant
            ? $this->buildOnboardingSteps($tenant, $summary ?? [])
            : [];

        return Inertia::render('dashboard', [
            'metrics' => $summary,
            'upcomingEvents' => $events->values()->all(),
            'recentPurchases' => $purchases->values()->all(),
            'latestPurchase' => $purchases->first(),
            'tenant' => $tenant ? [
                'id' => $tenant->id,
                'name' => $tenant->name,
                'subscriptionStatus' => $tenant->subscription_status,
                'subscriptionExpiresAt' => optional($tenant->subscription_expires_at)->toIso8601String(),
                'activePackage' => $activePackage ? [
                    'name' => $activePackage['name'] ?? '',
                    'price' => $activePackage['price'] ?? null,
                    'expiresAt' => $activePackage['expires_at'] ?? null,
                    'remainingEvents' => $activePackage['remaining_events'] ?? null,
                    'isActive' => (bool) ($activePackage['is_active'] ?? false),
                ] : null,
            ] : null,
            'emailVerification' => [
                'mustVerify' => $user instanceof MustVerifyEmail,
                'verified' => $user?->hasVerifiedEmail() ?? false,
            ],
            'onboarding' => $onboarding,
        ]);
    }

    private function consumeTenantAdminTarget(Request $request): ?string
    {
        $target = $request->session()->pull('tenant_admin.return_to');

        if (! is_string($target)) {
            return null;
        }

        if (! str_starts_with($target, '/event-admin')) {
            return null;
        }

        return $target;
    }

    private function collectUpcomingEvents(Tenant $tenant): Collection
    {
        return Event::query()
            ->where('tenant_id', $tenant->getKey())
            ->withCount(['photos', 'tasks', 'joinTokens'])
            ->orderByRaw('date IS NULL')
            ->orderBy('date')
            ->limit(5)
            ->get()
            ->map(function (Event $event): array {
                return [
                    'id' => $event->id,
                    'name' => $this->resolveEventName($event),
                    'slug' => $event->slug,
                    'status' => $event->status,
                    'isActive' => (bool) $event->is_active,
                    'date' => optional($event->date)->toIso8601String(),
                    'photosCount' => (int) ($event->photos_count ?? 0),
                    'tasksCount' => (int) ($event->tasks_count ?? 0),
                    'joinTokensCount' => (int) ($event->join_tokens_count ?? 0),
                ];
            });
    }

    private function collectRecentPurchases(Tenant $tenant): Collection
    {
        $entries = collect(
            $tenant->purchases()
                ->with('package')
                ->latest('purchased_at')
                ->limit(6)
                ->get()
                ->map(function (PackagePurchase $purchase): array {
                    return [
                        'id' => $purchase->id,
                        'packageName' => $purchase->package?->getNameForLocale(app()->getLocale())
                            ?? $purchase->package?->name
                            ?? __('Unknown package'),
                        'price' => $purchase->price !== null ? (float) $purchase->price : null,
                        'purchasedAt' => optional($purchase->purchased_at)->toIso8601String(),
                        'type' => $purchase->type,
                        'provider' => $purchase->provider,
                        'source' => 'purchase',
                        'isActive' => null,
                    ];
                })
                ->all()
        );

        if ($entries->isEmpty()) {
            $packageEntries = collect(
                $tenant->tenantPackages()
                    ->with('package')
                    ->orderByDesc('purchased_at')
                    ->limit(6)
                    ->get()
                    ->map(function (TenantPackage $package): array {
                        return [
                            'id' => $package->id,
                            'packageName' => $package->package?->getNameForLocale(app()->getLocale())
                                ?? $package->package?->name
                                ?? __('Unknown package'),
                            'price' => $package->price !== null ? (float) $package->price : null,
                            'purchasedAt' => optional($package->purchased_at)->toIso8601String(),
                            'type' => 'tenant_package',
                            'provider' => 'internal',
                            'source' => 'tenant_package',
                            'isActive' => (bool) $package->active,
                        ];
                    })
                    ->all()
            );

            $entries = $entries->merge($packageEntries);
        }

        return $entries
            ->sortByDesc('purchasedAt')
            ->values()
            ->take(6);
    }

    private function buildOnboardingSteps(Tenant $tenant, array $summary): array
    {
        $status = TenantOnboardingState::status($tenant);
        $settings = $tenant->settings ?? [];

        $adminAppOpened = (bool) Arr::get($settings, 'onboarding.admin_app_opened_at')
            || $tenant->last_activity_at !== null;

        $hasEvent = (bool) ($status['event'] ?? false);
        $hasInvite = (bool) ($status['invite'] ?? false);
        $hasBranding = (bool) ($status['palette'] ?? false)
            || (bool) Arr::get($settings, 'onboarding.branding_set', false);
        $hasTaskPackage = (bool) ($status['packages'] ?? false)
            || ! empty(Arr::get($settings, 'onboarding.selected_packages'));
        $hasPhotos = $tenant->photos()->exists() || (int) ($summary['new_photos'] ?? 0) > 0;

        return [
            [
                'key' => 'admin_app',
                'title' => trans('dashboard.onboarding.admin_app.title'),
                'description' => trans('dashboard.onboarding.admin_app.description'),
                'done' => $adminAppOpened,
                'cta' => url('/event-admin'),
                'ctaLabel' => trans('dashboard.onboarding.admin_app.cta'),
            ],
            [
                'key' => 'event_setup',
                'title' => trans('dashboard.onboarding.event_setup.title'),
                'description' => trans('dashboard.onboarding.event_setup.description'),
                'done' => $hasEvent,
                'cta' => url('/event-admin/events/new'),
                'ctaLabel' => trans('dashboard.onboarding.event_setup.cta'),
            ],
            [
                'key' => 'invite_guests',
                'title' => trans('dashboard.onboarding.invite_guests.title'),
                'description' => trans('dashboard.onboarding.invite_guests.description'),
                'done' => $hasInvite,
                'cta' => url('/event-admin/events'),
                'ctaLabel' => trans('dashboard.onboarding.invite_guests.cta'),
            ],
            [
                'key' => 'collect_photos',
                'title' => trans('dashboard.onboarding.collect_photos.title'),
                'description' => trans('dashboard.onboarding.collect_photos.description'),
                'done' => $hasPhotos,
                'cta' => url('/event-admin/dashboard'),
                'ctaLabel' => trans('dashboard.onboarding.collect_photos.cta'),
            ],
            [
                'key' => 'branding',
                'title' => trans('dashboard.onboarding.branding.title'),
                'description' => trans('dashboard.onboarding.branding.description'),
                'done' => $hasBranding && $hasTaskPackage,
                'cta' => url('/event-admin/tasks'),
                'ctaLabel' => trans('dashboard.onboarding.branding.cta'),
            ],
        ];
    }

    private function resolveEventName(Event $event): string
    {
        $name = $event->name;

        if (is_array($name)) {
            $locale = app()->getLocale();

            if (! empty($name[$locale])) {
                return (string) $name[$locale];
            }

            foreach (['de', 'en'] as $fallback) {
                if (! empty($name[$fallback])) {
                    return (string) $name[$fallback];
                }
            }

            $firstTranslated = reset($name);

            if (is_string($firstTranslated) && $firstTranslated !== '') {
                return $firstTranslated;
            }
        }

        if (is_string($name) && $name !== '') {
            return $name;
        }

        return __('Untitled event');
    }
}
