<?php

namespace App\Domain\Event\Services;

use App\Domain\Event\Enums\EventStatus;
use App\Domain\Event\Models\Event;
use App\Domain\Shared\Exceptions\DomainException;
use App\Models\User;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;

class EventService
{
    public function create(array $data, User $actor): Event
    {
        return DB::transaction(function () use ($data, $actor) {
            $data['created_by'] = $actor->id;
            $data['status'] = 'draft';
            $data['slug'] = $this->generateSlug($data['title'], $data['academy_id']);

            return Event::create($data);
        });
    }

    public function update(Event $event, array $data, User $actor): Event
    {
        return DB::transaction(function () use ($event, $data) {
            if (isset($data['title']) && $data['title'] !== $event->title) {
                $data['slug'] = $this->generateSlug($data['title'], $event->academy_id, $event->id);
            }

            $event->update($data);

            return $event->fresh();
        });
    }

    public function publish(Event $event, User $actor): Event
    {
        if ($event->status !== EventStatus::Draft) {
            throw new DomainException('لا يمكن نشر حدث غير مسودة');
        }

        return DB::transaction(function () use ($event) {
            $event->update([
                'status' => 'published',
                'published_at' => now(),
            ]);

            return $event->fresh();
        });
    }

    public function changeStatus(Event $event, EventStatus $newStatus, User $actor): Event
    {
        if (! $event->status->canTransitionTo($newStatus)) {
            throw new DomainException("لا يمكن تغيير الحالة من '{$event->status->label()}' إلى '{$newStatus->label()}'");
        }

        return DB::transaction(function () use ($event, $newStatus) {
            $updates = ['status' => $newStatus->value];

            if ($newStatus === EventStatus::Published && ! $event->published_at) {
                $updates['published_at'] = now();
            }

            $event->update($updates);

            return $event->fresh();
        });
    }

    public function delete(Event $event): void
    {
        $event->delete();
    }

    public function duplicate(Event $event, User $actor): Event
    {
        $data = $event->only([
            'academy_id', 'title', 'title_en', 'description', 'description_en',
            'type', 'location_type', 'facility_id', 'location_name', 'location_address',
            'max_capacity', 'form_fields', 'settings',
        ]);

        $data['title'] = $data['title'] . ' (نسخة)';

        return $this->create($data, $actor);
    }

    public function generateSlug(string $title, int $academyId, ?int $excludeId = null): string
    {
        $ascii = Str::slug($title, '-', 'en');
        $base = preg_match('/[a-z0-9]/', $ascii) ? $ascii : ('event-' . strtolower(Str::random(8)));

        $slug = $base;
        $counter = 1;

        while (
            Event::withoutGlobalScopes()
                ->where('academy_id', $academyId)
                ->where('slug', $slug)
                ->when($excludeId, fn ($q) => $q->where('id', '!=', $excludeId))
                ->exists()
        ) {
            $slug = $base . '-' . $counter;
            $counter++;
        }

        return $slug;
    }
}
