<?php

namespace App\Services;

use App\Models\MexcoOrganisation;
use App\Models\MexcoOrganisationUser;
use App\Models\MeetupEvent;
use Illuminate\Support\Collection;
use Illuminate\Support\Str;

class OrganisationService
{
    public function create(array $data): MexcoOrganisation
    {
        $slug = $this->uniqueSlug($data['slug'] ?? $data['name']);

        return MexcoOrganisation::query()->create([
            'name' => $data['name'],
            'slug' => $slug,
            'type' => $data['type'] ?? 'other',
            'contact_person' => $data['contact_person'] ?? null,
            'email' => isset($data['email']) ? strtolower(trim($data['email'])) : null,
            'phone' => $data['phone'] ?? null,
            'address' => $data['address'] ?? null,
            'website' => $data['website'] ?? null,
            'logo_path' => $data['logo_path'] ?? null,
            'status' => $data['status'] ?? 'active',
        ]);
    }

    public function update(MexcoOrganisation $organisation, array $data): MexcoOrganisation
    {
        $organisation->update([
            'name' => $data['name'],
            'type' => $data['type'] ?? $organisation->type,
            'contact_person' => $data['contact_person'] ?? null,
            'email' => isset($data['email']) ? strtolower(trim($data['email'])) : null,
            'phone' => $data['phone'] ?? null,
            'address' => array_key_exists('address', $data) ? $data['address'] : $organisation->address,
            'website' => array_key_exists('website', $data) ? $data['website'] : $organisation->website,
            'logo_path' => array_key_exists('logo_path', $data) ? $data['logo_path'] : $organisation->logo_path,
            'status' => $data['status'] ?? $organisation->status,
        ]);

        return $organisation->fresh();
    }

    public function stats(MexcoOrganisation $organisation): array
    {
        $organisation->loadCount([
            'events',
            'users',
        ]);

        $events = $organisation->events()->with(['license.plan', 'usage'])->get();
        $activeEvents = $events->filter(fn ($e) => $e->platform_status === 'active')->count();
        $participants = $events->sum(fn ($e) => $e->usage?->participants_count ?? $e->participants()->count());

        return [
            'total_events' => $organisation->events_count,
            'active_events' => $activeEvents,
            'completed_events' => max(0, $organisation->events_count - $activeEvents),
            'total_participants' => $participants,
            'total_organisers' => $organisation->users_count,
            'events' => $events,
        ];
    }

    public function createOrganiser(MexcoOrganisation $organisation, array $data): MexcoOrganisationUser
    {
        $user = MexcoOrganisationUser::query()->create([
            'organisation_id' => $organisation->id,
            'name' => $data['name'],
            'email' => strtolower(trim($data['email'])),
            'phone' => $data['phone'] ?? null,
            'password' => $data['password'],
            'role' => $data['role'] ?? 'event_manager',
            'status' => $data['status'] ?? 'active',
            'invited_at' => now(),
        ]);

        $this->syncUserEvents($user, $data['event_ids'] ?? []);

        return $user->fresh(['assignedEvents', 'organisation']);
    }

    public function updateOrganiser(MexcoOrganisationUser $user, array $data): MexcoOrganisationUser
    {
        $updates = [
            'name' => $data['name'],
            'email' => strtolower(trim($data['email'])),
            'role' => $data['role'] ?? $user->role,
            'status' => $data['status'] ?? $user->status,
        ];

        if (! empty($data['password'])) {
            $updates['password'] = $data['password'];
        }

        $user->update($updates);
        $this->syncUserEvents($user, $data['event_ids'] ?? []);

        return $user->fresh(['assignedEvents', 'organisation']);
    }

    public function syncUserEvents(MexcoOrganisationUser $user, array $eventIds): void
    {
        if ($user->isOrganisationAdmin()) {
            $eventIds = MeetupEvent::query()
                ->where('organisation_id', $user->organisation_id)
                ->pluck('id')
                ->all();
        }

        $eventIds = array_values(array_unique(array_filter($eventIds)));
        $sync = [];
        foreach ($eventIds as $eventId) {
            $sync[$eventId] = ['role' => $user->role];
        }
        $user->assignedEvents()->sync($sync);
    }

    public function accessibleEvents(MexcoOrganisationUser $user): Collection
    {
        if ($user->isOrganisationAdmin()) {
            return MeetupEvent::query()
                ->where('organisation_id', $user->organisation_id)
                ->where('platform_status', 'active')
                ->orderBy('name')
                ->get();
        }

        return $user->assignedEvents()
            ->where('platform_status', 'active')
            ->orderBy('name')
            ->get();
    }

    public function migrateLegacyOrganiser(MeetupEvent $event): ?MexcoOrganisationUser
    {
        if (! $event->organiser_username || ! $event->organisation_id) {
            return null;
        }

        $email = strtolower(trim($event->organiser_username));
        $user = MexcoOrganisationUser::query()
            ->where('organisation_id', $event->organisation_id)
            ->where('email', $email)
            ->first();

        if (! $user) {
            $user = MexcoOrganisationUser::query()->create([
                'organisation_id' => $event->organisation_id,
                'name' => Str::before($email, '@'),
                'email' => $email,
                'password' => $event->organiser_password ?: '1234',
                'role' => 'event_manager',
                'status' => 'active',
            ]);
        }

        $user->assignedEvents()->syncWithoutDetaching([
            $event->id => ['role' => $user->role],
        ]);

        return $user;
    }

    protected function uniqueSlug(string $base): string
    {
        $slug = Str::slug($base) ?: 'organisation';
        $original = $slug;
        $n = 1;
        while (MexcoOrganisation::query()->where('slug', $slug)->exists()) {
            $slug = $original.'-'.$n;
            $n++;
        }

        return $slug;
    }
}
