<?php

namespace Mtc\Modules\BlockRegistry\Services;

use Mtc\Modules\BlockRegistry\Models\BlockTemplate;
use Mtc\Modules\BlockRegistry\Models\BlockTemplateItem;
use Mtc\Modules\BlockRegistry\Models\BlockTemplateAssignment;
use Mtc\Modules\BlockRegistry\Models\EntityBlock;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;

class BlockTemplateService
{
    /**
     * Get all block templates with item counts
     */
    public function getAllTemplates(): Collection
    {
        return BlockTemplate::withCount('items')
            ->with('templateAssignments')
            ->orderBy('name')
            ->get();
    }

    /**
     * Get a single template with items and their block definitions
     */
    public function getTemplate(int $id): ?BlockTemplate
    {
        return BlockTemplate::with(['items.block.category', 'templateAssignments'])
            ->find($id);
    }

    /**
     * Create a block template with items and assignments
     */
    public function createTemplate(array $data): BlockTemplate
    {
        return DB::transaction(function () use ($data) {
            $template = BlockTemplate::create([
                'name' => $data['name'],
                'description' => $data['description'] ?? null,
            ]);

            $this->syncItems($template, $data['block_ids'] ?? []);
            $this->syncAssignments($template, $data['templates'] ?? []);

            return $template;
        });
    }

    /**
     * Update a block template with items and assignments
     */
    public function updateTemplate(int $id, array $data): BlockTemplate
    {
        return DB::transaction(function () use ($id, $data) {
            $template = BlockTemplate::findOrFail($id);
            $template->update([
                'name' => $data['name'],
                'description' => $data['description'] ?? null,
            ]);

            $this->syncItems($template, $data['block_ids'] ?? []);
            $this->syncAssignments($template, $data['templates'] ?? []);

            return $template->fresh(['items.block', 'templateAssignments']);
        });
    }

    /**
     * Delete a block template
     */
    public function deleteTemplate(int $id): bool
    {
        $template = BlockTemplate::findOrFail($id);
        return $template->delete();
    }

    /**
     * Get block templates assigned to a page template name
     */
    public function getTemplatesForTemplateName(string $templateName): Collection
    {
        $templateIds = BlockTemplateAssignment::where('template_name', $templateName)
            ->pluck('block_template_id');

        return BlockTemplate::whereIn('id', $templateIds)
            ->with(['items.block.category'])
            ->withCount('items')
            ->orderBy('name')
            ->get();
    }

    /**
     * Check if any block templates exist for a page template name
     */
    public function hasTemplatesForTemplateName(string $templateName): bool
    {
        return BlockTemplateAssignment::where('template_name', $templateName)->exists();
    }

    /**
     * Apply a block template to an entity, creating EntityBlock instances
     */
    public function applyTemplateToEntity(int $blockTemplateId, string $entityType, int $entityId): int
    {
        $template = BlockTemplate::with('items')->findOrFail($blockTemplateId);
        $count = 0;

        DB::transaction(function () use ($template, $entityType, $entityId, &$count) {
            foreach ($template->items as $item) {
                EntityBlock::create([
                    'entity_type' => $entityType,
                    'entity_id' => $entityId,
                    'block_id' => $item->block_id,
                    'status' => EntityBlock::STATUS_DRAFT,
                ]);
                $count++;
            }
        });

        return $count;
    }

    /**
     * Sync template items (replace all with new ordered list)
     */
    protected function syncItems(BlockTemplate $template, array $blockIds): void
    {
        $template->items()->delete();

        foreach ($blockIds as $index => $blockId) {
            BlockTemplateItem::create([
                'block_template_id' => $template->id,
                'block_id' => (int) $blockId,
                'order_index' => $index,
            ]);
        }
    }

    /**
     * Sync template assignments (replace all with new list)
     */
    protected function syncAssignments(BlockTemplate $template, array $templateNames): void
    {
        $template->templateAssignments()->delete();

        foreach ($templateNames as $templateName) {
            BlockTemplateAssignment::create([
                'block_template_id' => $template->id,
                'template_name' => $templateName,
            ]);
        }
    }
}
