<?php
/**
 * Template Block Service
 * Manages template-block whitelist assignments
 */
namespace Mtc\Modules\BlockRegistry\Services;

use Mtc\Modules\BlockRegistry\Models\BlockRegistryTemplateAssignment;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\App;

class TemplateBlockService
{
    /**
     * Get all blocks whitelisted for a template
     */
    public function getWhitelistedBlocks(string $templateName): \Illuminate\Support\Collection
    {
        return BlockRegistryTemplateAssignment::getBlocksForTemplate($templateName);
    }

    /**
     * Get default blocks for a template (auto-added to new pages)
     */
    public function getDefaultBlocks(string $templateName): \Illuminate\Support\Collection
    {
        return BlockRegistryTemplateAssignment::getDefaultBlocksForTemplate($templateName);
    }

    /**
     * Assign a block to a template
     */
    public function assignBlockToTemplate(
        int $blockId,
        string $templateName,
        bool $isDefault = false,
        int $order = 0
    ): BlockRegistryTemplateAssignment {
        return BlockRegistryTemplateAssignment::updateOrCreate(
            [
                'block_id' => $blockId,
                'template_name' => $templateName,
            ],
            [
                'is_default' => $isDefault,
                'order_index' => $order,
            ]
        );
    }

    /**
     * Remove a block from a template
     */
    public function removeBlockFromTemplate(int $blockId, string $templateName): bool
    {
        return BlockRegistryTemplateAssignment::where('block_id', $blockId)
            ->where('template_name', $templateName)
            ->delete() > 0;
    }

    /**
     * Bulk assign blocks to a template
     */
    public function bulkAssignBlocks(array $blockIds, string $templateName, bool $asDefault = false): int
    {
        if (empty($blockIds)) {
            return 0;
        }

        $rows = [];
        foreach ($blockIds as $order => $blockId) {
            $rows[] = [
                'block_id' => (int) $blockId,
                'template_name' => $templateName,
                'is_default' => $asDefault,
                'order_index' => $order,
            ];
        }

        BlockRegistryTemplateAssignment::upsert(
            $rows,
            ['block_id', 'template_name'],
            ['is_default', 'order_index']
        );

        return count($rows);
    }

    /**
     * Bulk remove blocks from a template
     */
    public function bulkRemoveBlocks(array $blockIds, string $templateName): int
    {
        return BlockRegistryTemplateAssignment::where('template_name', $templateName)
            ->whereIn('block_id', $blockIds)
            ->delete();
    }

    /**
     * Get all templates that have block assignments
     */
    public function getTemplatesWithBlocks(): array
    {
        return BlockRegistryTemplateAssignment::getAllAssignedTemplates();
    }

    /**
     * Get all available template names from filesystem
     */
    public function getAllAvailableTemplates(): array
    {
        $templateNames = [];

        try {
            $twig = App::make('twig');
            $loader = $twig->getLoader();

            foreach ($loader->getPaths() as $path) {
                $pagesPath = $path . '/pages';
                if (is_dir($pagesPath)) {
                    $files = File::glob($pagesPath . '/*.twig');
                    foreach ($files as $file) {
                        $templateName = basename($file);
                        if (!in_array($templateName, $templateNames)) {
                            $templateNames[] = $templateName;
                        }
                    }
                }
            }
        } catch (\Exception $e) {
            // Fallback: scan common directories
            $directories = [
                base_path('sites/default/templates/pages'),
                base_path('cms/templates/pages'),
            ];

            foreach ($directories as $dir) {
                if (is_dir($dir)) {
                    $files = File::glob($dir . '/*.twig');
                    foreach ($files as $file) {
                        $templateName = basename($file);
                        if (!in_array($templateName, $templateNames)) {
                            $templateNames[] = $templateName;
                        }
                    }
                }
            }
        }

        sort($templateNames);

        // CMS page templates
        $templates = array_map(function ($name) {
            $label = str_replace(['.twig', '_', '-'], ['', ' ', ' '], $name);
            $label = ucwords($label);
            return (object) [
                'name' => $name,
                'label' => $label,
                'group' => 'CMS Pages',
            ];
        }, $templateNames);

        // Shop templates
        $templates[] = (object) [
            'name' => 'shop_item',
            'label' => 'Shop Item',
            'group' => 'Shop',
        ];
        $templates[] = (object) [
            'name' => 'shop_category',
            'label' => 'Shop Category',
            'group' => 'Shop',
        ];

        return $templates;
    }

    /**
     * Check if a block is assigned to a template
     */
    public function isBlockAssigned(int $blockId, string $templateName): bool
    {
        return BlockRegistryTemplateAssignment::isBlockAssignedToTemplate($blockId, $templateName);
    }

    /**
     * Get assignment details for a block
     */
    public function getBlockAssignments(int $blockId): array
    {
        return BlockRegistryTemplateAssignment::where('block_id', $blockId)
            ->get()
            ->map(function ($assignment) {
                return [
                    'template_name' => $assignment->template_name,
                    'is_default' => $assignment->is_default,
                    'order_index' => $assignment->order_index,
                ];
            })
            ->toArray();
    }

    /**
     * Update block order within a template
     */
    public function updateBlockOrder(string $templateName, array $orderedBlockIds): void
    {
        if (empty($orderedBlockIds)) {
            return;
        }

        $cases = collect($orderedBlockIds)->map(fn($blockId, $order) =>
            "WHEN block_id = " . (int) $blockId . " THEN " . (int) $order
        )->implode(' ');

        $ids = array_map('intval', $orderedBlockIds);

        BlockRegistryTemplateAssignment::where('template_name', $templateName)
            ->whereIn('block_id', $ids)
            ->update(['order_index' => DB::raw("CASE {$cases} END")]);
    }

    /**
     * Set default blocks for a template
     */
    public function setDefaultBlocks(string $templateName, array $blockIds): void
    {
        // First, unset all defaults for this template
        BlockRegistryTemplateAssignment::where('template_name', $templateName)
            ->update(['is_default' => false]);

        // Then set the specified blocks as default
        BlockRegistryTemplateAssignment::where('template_name', $templateName)
            ->whereIn('block_id', $blockIds)
            ->update(['is_default' => true]);
    }

    /**
     * Copy template assignments from one template to another
     */
    public function copyAssignments(string $sourceTemplate, string $targetTemplate): int
    {
        $sourceAssignments = BlockRegistryTemplateAssignment::where('template_name', $sourceTemplate)
            ->get();

        $copied = 0;

        foreach ($sourceAssignments as $assignment) {
            BlockRegistryTemplateAssignment::firstOrCreate(
                [
                    'block_id' => $assignment->block_id,
                    'template_name' => $targetTemplate,
                ],
                [
                    'is_default' => $assignment->is_default,
                    'order_index' => $assignment->order_index,
                ]
            );
            $copied++;
        }

        return $copied;
    }

    /**
     * Get statistics for template assignments
     */
    public function getAssignmentStatistics(): array
    {
        $assignments = BlockRegistryTemplateAssignment::with('block')
            ->get()
            ->groupBy('template_name');

        $stats = [];
        foreach ($assignments as $templateName => $templateAssignments) {
            $stats[$templateName] = [
                'total_blocks' => $templateAssignments->count(),
                'default_blocks' => $templateAssignments->where('is_default', true)->count(),
                'blocks' => $templateAssignments->pluck('block.name')->toArray(),
            ];
        }

        return $stats;
    }
}
