<?php

namespace App\Services\Tenant;

use App\Models\Event;
use App\Models\Task;
use App\Models\TaskCollection;
use Illuminate\Database\DatabaseManager;
use Illuminate\Support\Str;
use RuntimeException;

class TaskCollectionImportService
{
    public function __construct(private readonly DatabaseManager $db)
    {
    }

    /**
     * @return array{collection: TaskCollection, created_task_ids: array<int>, attached_task_ids: array<int>}
     */
    public function import(TaskCollection $collection, Event $event): array
    {
        if ($collection->tenant_id && $collection->tenant_id !== $event->tenant_id) {
            throw new RuntimeException('Task collection is not accessible for this tenant.');
        }

        $collection->loadMissing('tasks');

        return $this->db->transaction(function () use ($collection, $event) {
            $tenantId = $event->tenant_id;

            $targetCollection = $this->resolveTenantCollection($collection, $tenantId);

            $createdTaskIds = [];
            $attachedTaskIds = [];

            foreach ($collection->tasks as $task) {
                $tenantTask = $this->resolveTenantTask($task, $targetCollection, $tenantId);

                if ($tenantTask->wasRecentlyCreated) {
                    $createdTaskIds[] = $tenantTask->id;
                }

                if (! $tenantTask->assignedEvents()->where('event_id', $event->id)->exists()) {
                    $tenantTask->assignedEvents()->attach($event->id);
                    $attachedTaskIds[] = $tenantTask->id;
                }
            }

            $event->taskCollections()->syncWithoutDetaching([
                $targetCollection->id => ['sort_order' => $targetCollection->position ?? 0],
            ]);

            return [
                'collection' => $targetCollection->fresh(),
                'created_task_ids' => $createdTaskIds,
                'attached_task_ids' => $attachedTaskIds,
            ];
        });
    }

    protected function resolveTenantCollection(TaskCollection $collection, int $tenantId): TaskCollection
    {
        if ($collection->tenant_id === $tenantId) {
            return $collection;
        }

        $existing = TaskCollection::query()
            ->where('tenant_id', $tenantId)
            ->where('source_collection_id', $collection->id)
            ->first();

        if ($existing) {
            return $existing;
        }

        return TaskCollection::create([
            'tenant_id' => $tenantId,
            'source_collection_id' => $collection->id,
            'event_type_id' => $collection->event_type_id,
            'slug' => $this->buildCollectionSlug($collection->slug, $tenantId),
            'name_translations' => $collection->name_translations,
            'description_translations' => $collection->description_translations,
            'is_default' => false,
            'position' => $collection->position,
        ]);
    }

    protected function resolveTenantTask(Task $templateTask, TaskCollection $targetCollection, int $tenantId): Task
    {
        if ($templateTask->tenant_id === $tenantId) {
            if ($templateTask->collection_id !== $targetCollection->id) {
                $templateTask->update(['collection_id' => $targetCollection->id]);
            }

            return $templateTask;
        }

        $sourceId = $templateTask->source_task_id ?: $templateTask->id;

        $existing = Task::query()
            ->where('tenant_id', $tenantId)
            ->where('source_task_id', $sourceId)
            ->first();

        if ($existing) {
            $existing->update([
                'collection_id' => $targetCollection->id,
                'source_collection_id' => $templateTask->source_collection_id ?: $targetCollection->source_collection_id ?: $targetCollection->id,
            ]);

            return tap($existing)->refresh();
        }

        $slugBase = $templateTask->slug ?: ($templateTask->title['en'] ?? $templateTask->title['de'] ?? 'task');
        $slug = $this->buildTaskSlug($slugBase);

        $cloned = Task::create([
            'tenant_id' => $tenantId,
            'slug' => $slug,
            'emotion_id' => $templateTask->emotion_id,
            'event_type_id' => $templateTask->event_type_id,
            'title' => $templateTask->title,
            'description' => $templateTask->description,
            'example_text' => $templateTask->example_text,
            'due_date' => null,
            'is_completed' => false,
            'priority' => $templateTask->priority,
            'collection_id' => $targetCollection->id,
            'difficulty' => $templateTask->difficulty,
            'sort_order' => $templateTask->sort_order,
            'is_active' => true,
            'source_task_id' => $sourceId,
            'source_collection_id' => $templateTask->source_collection_id ?: $templateTask->collection_id,
        ]);

        return $cloned;
    }

    protected function buildCollectionSlug(?string $slug, int $tenantId): string
    {
        $base = Str::slug(($slug ?: 'collection') . '-' . $tenantId);

        do {
            $candidate = $base . '-' . Str::random(4);
        } while (TaskCollection::where('slug', $candidate)->exists());

        return $candidate;
    }

    protected function buildTaskSlug(string $base): string
    {
        $slugBase = Str::slug($base) ?: 'task';

        do {
            $candidate = $slugBase . '-' . Str::random(6);
        } while (Task::where('slug', $candidate)->exists());

        return $candidate;
    }
}
