<?php

namespace Tests\Feature\Controllers;

use Database\Seeders\Global\ContentMigrationPermissionSeed;
use Mtc\MercuryDataModels\ContentMigrationEntry;
use Mtc\MercuryDataModels\User;
use Tests\DatabaseTestCase;
use Tests\UserForTenant;

class ContentMigrationProcessStateTest extends DatabaseTestCase
{
    use UserForTenant;

    private function actingUser(): User
    {
        $user = $this->getUser('mtc');
        (new ContentMigrationPermissionSeed())->run();
        $user->givePermissionTo('migrate-content');
        $user->load('permissions');

        return $user;
    }

    private function makeEntry(array $attributes = []): ContentMigrationEntry
    {
        return ContentMigrationEntry::create(array_merge([
            'original_url' => 'https://origin.example/page',
            'record_type' => 'page',
            'status' => 'keep',
            'data' => ['fetched_content' => ['title' => 'Example', 'raw_html' => '<h1>Example</h1>']],
        ], $attributes));
    }

    private function validState(array $overrides = []): array
    {
        return array_merge([
            'v' => 1,
            'step' => 'map',
            'template_id' => null,
            'mapping' => ['Hero' => ['title' => 'Hello']],
            'rules' => null,
            'extras' => [],
            'flags' => ['used_cached_mapping' => false, 'cache_existed' => false, 'create_version' => false],
            'page_details' => ['title' => 'Hello'],
        ], $overrides);
    }

    public function testSavesWizardStateUnderEntryData()
    {
        $entry = $this->makeEntry();

        $response = $this->actingAs($this->actingUser())
            ->withHeader('X-Tenant', tenant('id'))
            ->putJson("/api/settings/content-migration/{$entry->id}/process-state", [
                'state' => $this->validState(),
            ]);

        $response->assertStatus(200);
        $this->assertNotEmpty($response->json('saved_at'));

        $entry->refresh();
        $this->assertSame('map', $entry->data['wizard']['step']);
        $this->assertSame('Hello', $entry->data['wizard']['mapping']['Hero']['title']);
        $this->assertNotEmpty($entry->data['wizard']['saved_at']);
        // Pre-existing keys survive the merge.
        $this->assertSame('Example', $entry->data['fetched_content']['title']);
    }

    public function testStripsRebuildableBlobsFromState()
    {
        $entry = $this->makeEntry();

        $this->actingAs($this->actingUser())
            ->withHeader('X-Tenant', tenant('id'))
            ->putJson("/api/settings/content-migration/{$entry->id}/process-state", [
                'state' => $this->validState([
                    'preview' => ['huge' => 'blob'],
                    'fetched_content' => ['raw_html' => str_repeat('x', 100)],
                    'listing_content' => ['raw_html' => str_repeat('y', 100)],
                ]),
            ])
            ->assertStatus(200);

        $wizard = $entry->refresh()->data['wizard'];
        $this->assertArrayNotHasKey('preview', $wizard);
        $this->assertArrayNotHasKey('fetched_content', $wizard);
        $this->assertArrayNotHasKey('listing_content', $wizard);
    }

    public function testRejectsSavesForProcessedEntries()
    {
        $entry = $this->makeEntry(['processed_at' => now()]);

        $this->actingAs($this->actingUser())
            ->withHeader('X-Tenant', tenant('id'))
            ->putJson("/api/settings/content-migration/{$entry->id}/process-state", [
                'state' => $this->validState(),
            ])
            ->assertStatus(409);

        $this->assertArrayNotHasKey('wizard', $entry->refresh()->data ?? []);
    }

    public function testRejectsUnknownSteps()
    {
        $entry = $this->makeEntry();

        $this->actingAs($this->actingUser())
            ->withHeader('X-Tenant', tenant('id'))
            ->putJson("/api/settings/content-migration/{$entry->id}/process-state", [
                'state' => $this->validState(['step' => 'bogus']),
            ])
            ->assertStatus(422);
    }

    public function testClearRemovesOnlyTheWizardKey()
    {
        $entry = $this->makeEntry([
            'data' => [
                'fetched_content' => ['title' => 'Example'],
                'wizard' => ['v' => 1, 'step' => 'review'],
            ],
        ]);

        $this->actingAs($this->actingUser())
            ->withHeader('X-Tenant', tenant('id'))
            ->deleteJson("/api/settings/content-migration/{$entry->id}/process-state")
            ->assertStatus(200);

        $data = $entry->refresh()->data;
        $this->assertArrayNotHasKey('wizard', $data);
        $this->assertSame('Example', $data['fetched_content']['title']);
    }

    public function testConfirmClearsWizardState()
    {
        $entry = $this->makeEntry([
            'data' => [
                'fetched_content' => ['title' => 'Example'],
                'wizard' => ['v' => 1, 'step' => 'details'],
            ],
        ]);

        $this->actingAs($this->actingUser())
            ->withHeader('X-Tenant', tenant('id'))
            ->postJson('/api/settings/content-migration/process/confirm', ['entry_id' => $entry->id])
            ->assertStatus(200);

        $entry->refresh();
        $this->assertNotNull($entry->processed_at);
        $this->assertArrayNotHasKey('wizard', $entry->data ?? []);
    }

    public function testIndexExcludesWizardAndFetchedContent()
    {
        $entry = $this->makeEntry([
            'data' => [
                'fetched_content' => ['title' => 'Example'],
                'wizard' => ['v' => 1, 'step' => 'map'],
            ],
        ]);

        $response = $this->actingAs($this->actingUser())
            ->withHeader('X-Tenant', tenant('id'))
            ->getJson('/api/settings/content-migration')
            ->assertStatus(200);

        $row = collect($response->json('data'))->firstWhere('id', $entry->id);
        $this->assertNotNull($row);
        $this->assertArrayNotHasKey('wizard', $row['data'] ?? []);
        $this->assertArrayNotHasKey('fetched_content', $row['data'] ?? []);
    }

    public function testShowIncludesWizardState()
    {
        $entry = $this->makeEntry([
            'data' => [
                'fetched_content' => ['title' => 'Example'],
                'wizard' => ['v' => 1, 'step' => 'map'],
            ],
        ]);

        $response = $this->actingAs($this->actingUser())
            ->withHeader('X-Tenant', tenant('id'))
            ->getJson("/api/settings/content-migration/{$entry->id}")
            ->assertStatus(200);

        $this->assertSame('map', $response->json('data.wizard.step'));
        $this->assertSame('Example', $response->json('data.fetched_content.title'));
    }
}
