<?php

namespace Tests\Feature;

use App\Enums\PromptLandingPageVersionKind;
use App\Models\PromptLandingPage;
use App\Models\PromptLandingPageLead;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class PromptLandingPageCopyTest extends TestCase
{
    use RefreshDatabase;

    public function test_guests_are_redirected_from_duplicate(): void
    {
        $page = PromptLandingPage::factory()->approved()->create();

        $this->post(route('prompt-landing-pages.duplicate', $page))
            ->assertRedirect(route('login'));
    }

    public function test_the_owner_can_duplicate_a_ready_page(): void
    {
        $user = User::factory()->create();
        $page = PromptLandingPage::factory()->approved()->for($user)->create([
            'title' => 'Yoga studio',
            'website_url' => 'https://yoga.example.com',
            'purpose' => PromptLandingPage::PURPOSE_APP_DOWNLOAD,
            'html' => '<section><h1>Yoga studio</h1></section>',
            'css' => 'h1 { color: navy; }',
            'js' => 'var yoga = 1;',
            'brief' => ['brand_name' => 'Austin Yoga'],
            'prompt_used' => 'Make a yoga app page',
            'google_conversion_send_to' => 'AW-1234567890/AbCdEfGh',
            'meta_pixel_id' => '1234567890',
        ]);
        PromptLandingPageLead::factory()->for($page, 'page')->create([
            'payload' => ['email' => 'ada@example.com'],
        ]);

        $this->actingAs($user)
            ->followingRedirects()
            ->post(route('prompt-landing-pages.duplicate', $page))
            ->assertOk()
            ->assertSee('Duplicated “Yoga studio” as a new landing page.', false)
            ->assertSee('mb-chat-status', false)
            ->assertDontSee('data-action="suggest"', false);

        $copy = PromptLandingPage::query()->whereKeyNot($page->id)->first();

        $this->assertNotNull($copy);
        $this->assertSame($user->id, $copy->user_id);
        $this->assertSame('Yoga studio (copy)', $copy->title);
        $this->assertSame($page->website_url, $copy->website_url);
        $this->assertSame($page->purpose, $copy->purpose);
        $this->assertSame($page->html, $copy->html);
        $this->assertSame($page->css, $copy->css);
        $this->assertSame($page->js, $copy->js);
        $this->assertSame($page->brief, $copy->brief);
        $this->assertSame($page->prompt_used, $copy->prompt_used);
        $this->assertSame('pending_approval', $copy->status);
        $this->assertNull($copy->approved_at);
        $this->assertNull($copy->google_conversion_send_to);
        $this->assertNull($copy->meta_pixel_id);
        $this->assertSame(0, $copy->leads()->count());
        $this->assertSame(1, $copy->versions()->count());
        $this->assertSame(PromptLandingPageVersionKind::Published, $copy->versions()->first()?->kind);

        $page->refresh();
        $this->assertSame('Yoga studio', $page->title);
        $this->assertSame('approved', $page->status);
        $this->assertSame(1, $page->leads()->count());
        $this->assertSame('AW-1234567890/AbCdEfGh', $page->google_conversion_send_to);
    }

    public function test_duplicate_is_forbidden_for_another_users_page(): void
    {
        $page = PromptLandingPage::factory()->approved()->create();
        $other = User::factory()->create();

        $this->actingAs($other)
            ->post(route('prompt-landing-pages.duplicate', $page))
            ->assertForbidden();

        $this->assertDatabaseCount('prompt_landing_pages', 1);
    }

    public function test_duplicate_is_rejected_while_the_page_is_generating(): void
    {
        $user = User::factory()->create();
        $page = PromptLandingPage::factory()->completed()->for($user)->create([
            'status' => 'generating',
        ]);

        $this->actingAs($user)
            ->from(route('landing-pages.index', ['tab' => 'prompt']))
            ->post(route('prompt-landing-pages.duplicate', $page))
            ->assertRedirect(route('landing-pages.index', ['tab' => 'prompt']))
            ->assertSessionHasErrors('page');

        $this->assertDatabaseCount('prompt_landing_pages', 1);
    }

    public function test_the_owner_can_override_a_page_with_another_pages_content(): void
    {
        $user = User::factory()->create();
        $target = PromptLandingPage::factory()->approved()->for($user)->create([
            'title' => 'Page A',
            'website_url' => 'https://webcrawlers.com',
            'purpose' => 'Leads Page',
            'html' => '<section id="a">Original A</section>',
            'css' => 'body { color: red; }',
            'js' => 'var a = 1;',
            'google_conversion_send_to' => 'AW-1111111111/AaAaAaAa',
            'meta_pixel_id' => '1111111111',
        ]);
        $source = PromptLandingPage::factory()->approved()->for($user)->create([
            'title' => 'Page B',
            'website_url' => 'https://yoga.example.com',
            'purpose' => PromptLandingPage::PURPOSE_APP_DOWNLOAD,
            'html' => '<section id="b">Source B</section>',
            'css' => 'body { color: blue; }',
            'js' => 'var b = 2;',
        ]);
        PromptLandingPageLead::factory()->for($target, 'page')->create([
            'payload' => ['email' => 'ada@example.com'],
        ]);

        $this->actingAs($user)
            ->post(route('prompt-landing-pages.override', $target), [
                'source_page' => $source->id,
            ])
            ->assertRedirect(route('prompt-landing-pages.show', $target))
            ->assertSessionHas('status');

        $target->refresh();
        $source->refresh();

        $this->assertSame('Page A', $target->title);
        $this->assertSame('https://webcrawlers.com', $target->website_url);
        $this->assertSame('Leads Page', $target->purpose);
        $this->assertSame('approved', $target->status);
        $this->assertSame('AW-1111111111/AaAaAaAa', $target->google_conversion_send_to);
        $this->assertSame('1111111111', $target->meta_pixel_id);
        $this->assertSame('<section id="b">Source B</section>', $target->html);
        $this->assertSame('body { color: blue; }', $target->css);
        $this->assertSame('var b = 2;', $target->js);
        $this->assertSame(1, $target->leads()->count());
        $this->assertGreaterThanOrEqual(2, $target->versions()->count());
        $this->assertTrue($target->versions()->where('html', '<section id="a">Original A</section>')->exists());
        $this->assertTrue($target->versions()->where('html', '<section id="b">Source B</section>')->exists());

        $this->assertSame('<section id="b">Source B</section>', $source->html);
        $this->assertSame('Page B', $source->title);
        $this->assertSame(0, $source->versions()->count());
    }

    public function test_override_is_forbidden_for_another_users_target_page(): void
    {
        $target = PromptLandingPage::factory()->approved()->create();
        $source = PromptLandingPage::factory()->approved()->create();
        $other = User::factory()->create();

        $this->actingAs($other)
            ->post(route('prompt-landing-pages.override', $target), [
                'source_page' => $source->id,
            ])
            ->assertForbidden();

        $this->assertSame('<section><h1>Yoga studio</h1></section>', $target->fresh()->html);
    }

    public function test_override_returns_404_for_another_users_source_page(): void
    {
        $user = User::factory()->create();
        $target = PromptLandingPage::factory()->approved()->for($user)->create([
            'html' => '<section id="a">Original A</section>',
        ]);
        $source = PromptLandingPage::factory()->approved()->create([
            'html' => '<section id="b">Secret B</section>',
        ]);

        $this->actingAs($user)
            ->post(route('prompt-landing-pages.override', $target), [
                'source_page' => $source->id,
            ])
            ->assertNotFound();

        $this->assertSame('<section id="a">Original A</section>', $target->fresh()->html);
    }

    public function test_override_is_rejected_when_the_source_is_the_same_page(): void
    {
        $user = User::factory()->create();
        $page = PromptLandingPage::factory()->approved()->for($user)->create();

        $this->actingAs($user)
            ->from(route('landing-pages.index', ['tab' => 'prompt']))
            ->post(route('prompt-landing-pages.override', $page), [
                'source_page' => $page->id,
            ])
            ->assertRedirect(route('landing-pages.index', ['tab' => 'prompt']))
            ->assertSessionHasErrors('source_page');
    }

    public function test_override_requires_a_source_page(): void
    {
        $user = User::factory()->create();
        $page = PromptLandingPage::factory()->approved()->for($user)->create();

        $this->actingAs($user)
            ->from(route('landing-pages.index', ['tab' => 'prompt']))
            ->post(route('prompt-landing-pages.override', $page))
            ->assertRedirect(route('landing-pages.index', ['tab' => 'prompt']))
            ->assertSessionHasErrors('source_page');
    }

    public function test_the_listing_shows_duplicate_and_override_actions(): void
    {
        $user = User::factory()->create();
        $first = PromptLandingPage::factory()->approved()->for($user)->create([
            'title' => 'First page',
        ]);
        $second = PromptLandingPage::factory()->approved()->for($user)->create([
            'title' => 'Second page',
        ]);

        $this->actingAs($user)
            ->get(route('landing-pages.index', [
                'tab' => 'prompt',
                'purpose' => 'Leads Page',
            ]))
            ->assertOk()
            ->assertSee('aria-label="Duplicate page"', false)
            ->assertSee(route('prompt-landing-pages.duplicate', $first), false)
            ->assertSee(route('prompt-landing-pages.duplicate', $second), false)
            ->assertSee('aria-label="Override with another page"', false)
            ->assertSee(route('prompt-landing-pages.override', $first), false)
            ->assertSee('Use content from', false)
            ->assertSee('#'.$first->id.' · First page', false)
            ->assertSee('#'.$second->id.' · Second page', false)
            ->assertSee('Current content will be saved as a version. The source page is not changed.', false);
    }
}
