<?php

namespace Mtc\Plugins\BlockManager\Tests\Feature;

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

/**
 * Surfaces the Phase 16 VariantConflictDetector through a thin HTTP endpoint
 * so the Designer SPA can show a banner when the on-disk LESS has drifted
 * from what the generator would emit.
 */
class VariantConflictApiTest extends TestCase
{
    /** @var string[] */
    private array $createdUuids = [];

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

    /** @var array<string, string> */
    private array $manifestBackups = [];

    protected function tearDown(): void
    {
        foreach ($this->writtenFiles as $path) {
            @unlink($path);
        }
        foreach ($this->manifestBackups as $path => $content) {
            file_put_contents($path, $content);
        }
        app(\Mtc\Plugins\BlockManager\Services\VariantStyleAggregator::class)->rebuild();
        if (!empty($this->createdUuids)) {
            BlockManagerVariantDraft::whereIn('uuid', $this->createdUuids)->delete();
        }
        parent::tearDown();
    }

    public function test_conflict_returns_404_for_unknown_id(): void
    {
        $this->getJson('/api/block-manager/variants/99999999/conflict')->assertStatus(404);
    }

    public function test_conflict_returns_envelope_with_no_conflict_when_unpublished(): void
    {
        $draft = $this->seedDraft('button', 'phase17-conflict-fresh-' . Str::random(6));

        $response = $this->getJson("/api/block-manager/variants/{$draft->id}/conflict");
        $response->assertStatus(200);

        $data = $response->json('data');
        $this->assertSame(false, $data['has_conflict']);
        $this->assertNull($data['reason']);
    }

    public function test_conflict_flags_local_edit_on_published_variant(): void
    {
        $slug = 'phase17-conflict-tampered-' . Str::random(6);
        $draft = $this->seedDraft('button', $slug);
        $this->backupManifest('button');

        app(VariantPublishService::class)->publish($draft);
        $twigPath = base_path("plugins/BlockManager/elements/button/variants/{$slug}.twig");
        $lessPath = base_path("plugins/BlockManager/elements/button/styles/{$slug}.less");
        $this->writtenFiles[] = $twigPath;
        $this->writtenFiles[] = $lessPath;
        $this->writtenFiles[] = "{$twigPath}.bak";
        $this->writtenFiles[] = "{$lessPath}.bak";

        // Simulate hand-edit on disk
        file_put_contents($lessPath, file_get_contents($lessPath) . "\n/* tampered */\n");

        $response = $this->getJson("/api/block-manager/variants/{$draft->id}/conflict");
        $response->assertStatus(200);

        $data = $response->json('data');
        $this->assertTrue(
            $data['has_conflict'],
            "Conflict endpoint must report has_conflict=true after a hand-edit on the published LESS."
        );
        $this->assertIsString($data['reason']);
        $this->assertNotEmpty($data['reason']);
    }

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

        return BlockManagerVariantDraft::create([
            'uuid'            => $uuid,
            'element_type'    => $elementType,
            'variant_slug'    => $variantSlug,
            'label'           => 'Phase 17 Conflict API Probe',
            'properties_json' => ['base' => ['default' => ['desktop' => [
                'typography' => ['color' => ['token' => '@primary_color']],
            ]]]],
        ]);
    }

    private function backupManifest(string $elementType): void
    {
        $path = base_path("plugins/BlockManager/elements/{$elementType}/element.json");
        if (!isset($this->manifestBackups[$path]) && is_file($path)) {
            $this->manifestBackups[$path] = file_get_contents($path);
        }
    }
}
