<?php

namespace Mtc\Plugins\BlockManager\Tests\Unit;

use Illuminate\Support\Str;
use Mtc\Plugins\BlockManager\Models\BlockManagerVariantDraft;
use Mtc\Plugins\BlockManager\Services\VariantLessGenerator;
use Tests\TestCase;

class VariantLessGeneratorTest extends TestCase
{
    private VariantLessGenerator $service;

    /** @var string[] */
    private array $createdUuids = [];

    protected function setUp(): void
    {
        parent::setUp();
        $this->service = app(VariantLessGenerator::class);
    }

    protected function tearDown(): void
    {
        if (!empty($this->createdUuids)) {
            BlockManagerVariantDraft::whereIn('uuid', $this->createdUuids)->delete();
        }
        parent::tearDown();
    }

    public function test_service_is_resolvable_from_container(): void
    {
        $this->assertInstanceOf(VariantLessGenerator::class, $this->service);
    }

    public function test_emits_designer_meta_header(): void
    {
        $draft = $this->seedDraft('button', 'phase11-less-' . Str::random(6));

        $output = $this->service->generate($draft);

        $this->assertMatchesRegularExpression(
            '#^/\*\s*@designer-meta\s*(.*?)\s*\*/#s',
            $output,
            "LESS output must start with a /* @designer-meta {...} */ header."
        );

        // Extract and parse the meta JSON.
        $this->assertSame(1, preg_match('#@designer-meta\s*(\{.*\})\s*\*/#s', $output, $m));
        $meta = json_decode($m[1], true);
        $this->assertIsArray($meta, "Designer-meta header must contain parseable JSON.");

        foreach (['version', 'element_type', 'variant_slug', 'properties'] as $key) {
            $this->assertArrayHasKey(
                $key,
                $meta,
                "Designer-meta JSON is missing key '{$key}'."
            );
        }
    }

    public function test_emits_variant_specific_selector(): void
    {
        $slug = 'phase11-less-' . Str::random(6);
        $draft = $this->seedDraft('button', $slug);

        $output = $this->service->generate($draft);

        $this->assertMatchesRegularExpression(
            '/\.bm-button--' . preg_quote($slug, '/') . '\s*\{/',
            $output,
            "LESS rules must be scoped to '.bm-button--{$slug} {'."
        );
    }

    public function test_preserves_token_references_unresolved(): void
    {
        $draft = $this->seedDraft('button', 'phase11-less-' . Str::random(6), [
            'base' => ['default' => ['desktop' => [
                'typography' => ['color' => ['token' => '@primary_color']],
            ]]],
        ]);

        $output = $this->service->generate($draft);

        // Token reference must survive as @var (LESS variable), NOT be resolved to hex.
        $this->assertMatchesRegularExpression(
            '/color:\s*@primary_color/',
            $output,
            "Token reference must be emitted as '@primary_color' (literal LESS variable)."
        );
        $this->assertDoesNotMatchRegularExpression(
            '/color:\s*#[0-9a-fA-F]+/',
            $output,
            "Token reference must NOT be resolved to a hex value at publish time."
        );
    }

    public function test_emits_raw_values_as_is(): void
    {
        $draft = $this->seedDraft('button', 'phase11-less-' . Str::random(6), [
            'base' => ['default' => ['desktop' => [
                'box' => ['padding_x' => ['raw' => '24px']],
            ]]],
        ]);

        $output = $this->service->generate($draft);

        $this->assertStringContainsString('padding-left: 24px', $output);
        $this->assertStringContainsString('padding-right: 24px', $output);
    }

    public function test_omits_properties_with_empty_or_null_values(): void
    {
        $draft = $this->seedDraft('button', 'phase11-less-' . Str::random(6), [
            'base' => ['default' => ['desktop' => [
                'typography' => ['color' => null],
                'box'        => ['padding_x' => []],
            ]]],
        ]);

        $output = $this->service->generate($draft);

        $this->assertStringNotContainsString('color:', $output, "Null/empty cells must not emit CSS rules.");
        $this->assertStringNotContainsString('padding-left:', $output);
    }

    private function seedDraft(string $elementType, string $variantSlug, ?array $properties = null): BlockManagerVariantDraft
    {
        $uuid = (string) Str::uuid();
        $this->createdUuids[] = $uuid;

        return BlockManagerVariantDraft::create([
            'uuid'            => $uuid,
            'element_type'    => $elementType,
            'variant_slug'    => $variantSlug,
            'label'           => 'Phase 11 LessGenerator Probe',
            'properties_json' => $properties,
        ]);
    }
}
