<?php
/**
 * Block Registry Service
 * Handles CRUD operations for block registry
 */
namespace Mtc\Modules\BlockRegistry\Services;

use Mtc\Modules\BlockRegistry\Models\BlockRegistry;
use Mtc\Modules\BlockRegistry\Models\BlockRegistryCategory;
use Mtc\Modules\BlockRegistry\Models\BlockRegistryField;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;

class BlockRegistryService
{
    /**
     * Create a new block
     */
    public function createBlock(array $data): BlockRegistry
    {
        return DB::transaction(function () use ($data) {
            // Create the block
            $block = BlockRegistry::create([
                'uuid' => Str::uuid(),
                'name' => $data['name'],
                'slug' => $data['slug'] ?? BlockRegistry::generateSlug($data['name']),
                'description' => $data['description'] ?? null,
                'category_id' => $data['category_id'] ?? null,
                'icon' => $data['icon'] ?? 'fa-cube',
                'preview_image' => $data['preview_image'] ?? null,
                'template' => $data['template'] ?? null,
                'is_active' => $data['is_active'] ?? true,
                'order_index' => $data['order_index'] ?? 0,
            ]);

            // Create fields if provided
            if (!empty($data['fields'])) {
                $this->createFieldsWithSubFields($block->id, $data['fields']);
            }

            return $block->fresh(['fields', 'category']);
        });
    }

    /**
     * Update an existing block
     */
    public function updateBlock(BlockRegistry $block, array $data, ?int $userId = null): BlockRegistry
    {
        return DB::transaction(function () use ($block, $data, $userId) {
            // Update block metadata
            $block->update([
                'name' => $data['name'] ?? $block->name,
                'slug' => $data['slug'] ?? $block->slug,
                'description' => $data['description'] ?? $block->description,
                'category_id' => $data['category_id'] ?? $block->category_id,
                'icon' => $data['icon'] ?? $block->icon,
                'preview_image' => array_key_exists('preview_image', $data) ? $data['preview_image'] : $block->preview_image,
                'template' => $data['template'] ?? $block->template,
                'is_active' => $data['is_active'] ?? $block->is_active,
                'order_index' => $data['order_index'] ?? $block->order_index,
            ]);

            // Update fields if provided
            if (isset($data['fields'])) {
                // Delete all existing fields (including sub-fields via cascade)
                $block->allFields()->delete();

                // Create new fields with sub-fields
                $this->createFieldsWithSubFields($block->id, $data['fields']);

            }

            return $block->fresh(['fields', 'category']);
        });
    }

    /**
     * Delete a block
     */
    public function deleteBlock(BlockRegistry $block): bool
    {
        if (!$block->canBeDeleted()) {
            throw new \Exception(
                $block->is_system
                    ? 'Cannot delete system block'
                    : 'Cannot delete block that is in use'
            );
        }

        return $block->delete();
    }

    /**
     * Duplicate a block
     */
    public function duplicateBlock(BlockRegistry $block, ?string $newName = null): BlockRegistry
    {
        $newName = $newName ?? $block->name . ' (Copy)';

        return $this->createBlock([
            'name' => $newName,
            'slug' => BlockRegistry::generateSlug($newName),
            'description' => $block->description,
            'category_id' => $block->category_id,
            'icon' => $block->icon,
            'is_active' => true,
            'fields' => $block->fields->map(function ($field) {
                return $field->toArray();
            })->toArray(),
        ]);
    }

    /**
     * Create a single BlockRegistryField from an array of attributes
     */
    public static function createField(int $blockId, array $fieldData, int $index, ?int $parentFieldId = null): BlockRegistryField
    {
        return BlockRegistryField::create([
            'block_id' => $blockId,
            'parent_field_id' => $parentFieldId,
            'name' => $fieldData['name'] ?? "field_{$index}",
            'label' => $fieldData['label'] ?? $fieldData['name'] ?? "Field {$index}",
            'type' => $fieldData['type'] ?? 'text',
            'order_index' => $fieldData['order_index'] ?? $fieldData['order'] ?? $index,
            'required' => !empty($fieldData['required']),
            'css_class' => $fieldData['css_class'] ?? null,
            'settings' => $fieldData['settings'] ?? null,
            'options' => $fieldData['options'] ?? null,
            'regex' => $fieldData['regex'] ?? null,
            'mime' => $fieldData['mime'] ?? null,
            'info' => $fieldData['info'] ?? null,
            'is_repeater' => $fieldData['is_repeater'] ?? false,
            'repeater_min' => $fieldData['repeater_min'] ?? 0,
            'repeater_max' => $fieldData['repeater_max'] ?? 100,
            'repeater_text' => $fieldData['repeater_text'] ?? 'Add Row',
        ]);
    }

    /**
     * Create fields with sub-fields for repeater types
     */
    public function createFieldsWithSubFields(int $blockId, array $fields): void
    {
        foreach ($fields as $index => $fieldData) {
            $field = self::createField($blockId, $fieldData, $index);

            // Create sub-fields for repeater type
            if ($fieldData['type'] === 'repeater' && !empty($fieldData['sub_fields'])) {
                foreach ($fieldData['sub_fields'] as $subIndex => $subFieldData) {
                    self::createField($blockId, $subFieldData, $subIndex, $field->id);
                }
            }
        }
    }

    /**
     * Get all blocks as a flat list with categories for filtering
     */
    public function getAllBlocks(): array
    {
        $blocks = BlockRegistry::with(['category', 'fields'])
            ->orderBy('name')
            ->get();

        $categories = BlockRegistryCategory::orderBy('order_index')->get();

        return [
            'blocks' => $blocks,
            'categories' => $categories,
        ];
    }

    /**
     * Get available blocks for a template
     */
    public function getAvailableBlocksForTemplate(string $templateName): \Illuminate\Database\Eloquent\Collection
    {
        return BlockRegistry::getAvailableForTemplate($templateName);
    }

    /**
     * Validate block structure
     */
    public function validateStructure(array $structure): array
    {
        $errors = [];

        if (empty($structure['name'])) {
            $errors[] = 'Block name is required';
        }

        if (isset($structure['fields'])) {
            foreach ($structure['fields'] as $index => $field) {
                if (empty($field['name'])) {
                    $errors[] = "Field at index {$index} is missing a name";
                }
                if (!empty($field['type']) && !array_key_exists($field['type'], BlockRegistryField::FIELD_TYPES)) {
                    $errors[] = "Field '{$field['name']}' has invalid type: {$field['type']}";
                }
            }
        }

        return $errors;
    }

    /**
     * Get block usage statistics
     */
    public function getBlockStatistics(BlockRegistry $block): array
    {
        $counts = \Mtc\Modules\BlockRegistry\Models\EntityBlock::where('block_id', $block->id)
            ->selectRaw('COUNT(*) as instance_count, COUNT(DISTINCT entity_id) as page_count')
            ->first();

        return [
            'page_count' => $counts->page_count ?? 0,
            'instance_count' => $counts->instance_count ?? 0,
            'version' => $block->version,
            'templates' => $block->relationLoaded('templateAssignments')
                ? $block->templateAssignments->pluck('template_name')->toArray()
                : $block->templateAssignments()->pluck('template_name')->toArray(),
            'fields_count' => $block->relationLoaded('fields')
                ? $block->fields->count()
                : $block->fields()->count(),
        ];
    }
}
