<?php

namespace Tests\Tenant;

use App\Facades\Feature;
use App\Facades\Settings;
use Illuminate\Support\Facades\Storage;
use Mtc\MercuryDataModels\Dealership;
use Mtc\MercuryDataModels\Page;
use Tests\TenantTestCase;

class MakeSitemapSplitTest extends TenantTestCase
{
    private string $tenantId;

    protected function setUp(): void
    {
        parent::setUp();

        Storage::fake('file-storage');

        Feature::setEnabled(tenant(), ['sitemap', 'dealerships']);

        $this->tenantId = tenant('id');
    }

    public function testDefaultModeWritesSingleSitemapWithoutIndex(): void
    {
        $this->makeSplitSetting(false);

        Page::factory()->create([
            'title' => 'About',
            'slug' => 'about',
            'status' => 'published',
            'category' => null,
        ]);

        $this->artisan('make:sitemap')->assertExitCode(0);

        Storage::disk('file-storage')->assertExists($this->tenantId . '/sitemap.xml');
        Storage::disk('file-storage')->assertMissing($this->tenantId . '/sitemap-index.xml');
        Storage::disk('file-storage')->assertMissing($this->tenantId . '/sitemap-pages.xml');
    }

    public function testSplitModeWritesIndexAndPerSectionFiles(): void
    {
        $this->makeSplitSetting(true);

        Page::factory()->create([
            'title' => 'About',
            'slug' => 'about',
            'status' => 'published',
            'category' => null,
        ]);

        Dealership::factory()->create([
            'name' => 'Sandown Mercedes',
            'slug' => 'sandown-mercedes',
            'active' => 1,
        ]);

        $this->artisan('make:sitemap')->assertExitCode(0);

        $disk = Storage::disk('file-storage');

        $disk->assertExists($this->tenantId . '/sitemap-index.xml');
        $disk->assertExists($this->tenantId . '/sitemap-pages.xml');
        $disk->assertExists($this->tenantId . '/sitemap-dealerships.xml');
        $disk->assertMissing($this->tenantId . '/sitemap.xml');

        $index = $disk->get($this->tenantId . '/sitemap-index.xml');
        $this->assertStringContainsString('<sitemapindex', $index);
        $this->assertStringContainsString('sitemap-pages.xml', $index);
        $this->assertStringContainsString('sitemap-dealerships.xml', $index);

        $pagesXml = $disk->get($this->tenantId . '/sitemap-pages.xml');
        $this->assertStringContainsString('/about', $pagesXml);
        $this->assertStringNotContainsString('sandown-mercedes', $pagesXml);

        $dealershipsXml = $disk->get($this->tenantId . '/sitemap-dealerships.xml');
        $this->assertStringContainsString('sandown-mercedes', $dealershipsXml);
        $this->assertStringNotContainsString('/about', $dealershipsXml);
    }

    public function testSplitModeSkipsSectionsWithNoUrls(): void
    {
        $this->makeSplitSetting(true);

        Page::factory()->create([
            'title' => 'About',
            'slug' => 'about',
            'status' => 'published',
            'category' => null,
        ]);

        $this->artisan('make:sitemap')->assertExitCode(0);

        $disk = Storage::disk('file-storage');

        $disk->assertExists($this->tenantId . '/sitemap-pages.xml');
        $disk->assertMissing($this->tenantId . '/sitemap-dealerships.xml');
        $disk->assertMissing($this->tenantId . '/sitemap-vehicles.xml');
        $disk->assertMissing($this->tenantId . '/sitemap-search-results.xml');

        $index = $disk->get($this->tenantId . '/sitemap-index.xml');
        $this->assertStringNotContainsString('sitemap-dealerships.xml', $index);
    }

    public function testFlippingToSplitModeRemovesPreviousMonolithSitemap(): void
    {
        Page::factory()->create([
            'title' => 'About',
            'slug' => 'about',
            'status' => 'published',
            'category' => null,
        ]);

        $this->makeSplitSetting(false);
        $this->artisan('make:sitemap')->assertExitCode(0);
        Storage::disk('file-storage')->assertExists($this->tenantId . '/sitemap.xml');

        Settings::update('seo-sitemap-split', true);
        $this->artisan('make:sitemap')->assertExitCode(0);

        Storage::disk('file-storage')->assertMissing($this->tenantId . '/sitemap.xml');
        Storage::disk('file-storage')->assertExists($this->tenantId . '/sitemap-index.xml');
        Storage::disk('file-storage')->assertExists($this->tenantId . '/sitemap-pages.xml');
    }

    public function testFlippingBackToSingleModeRemovesIndexAndSectionFiles(): void
    {
        Page::factory()->create([
            'title' => 'About',
            'slug' => 'about',
            'status' => 'published',
            'category' => null,
        ]);

        $this->makeSplitSetting(true);
        $this->artisan('make:sitemap')->assertExitCode(0);
        Storage::disk('file-storage')->assertExists($this->tenantId . '/sitemap-index.xml');
        Storage::disk('file-storage')->assertExists($this->tenantId . '/sitemap-pages.xml');

        Settings::update('seo-sitemap-split', false);
        $this->artisan('make:sitemap')->assertExitCode(0);

        Storage::disk('file-storage')->assertExists($this->tenantId . '/sitemap.xml');
        Storage::disk('file-storage')->assertMissing($this->tenantId . '/sitemap-index.xml');
        Storage::disk('file-storage')->assertMissing($this->tenantId . '/sitemap-pages.xml');
    }

    public function testArticlePageTypesGetOwnSitemapFile(): void
    {
        $this->makeSplitSetting(true);

        Page::factory()->create([
            'title' => 'About us',
            'slug' => 'about-us',
            'status' => 'published',
            'category' => null,
        ]);

        Page::factory()->create([
            'title' => 'Latest News',
            'slug' => 'latest-news',
            'status' => 'published',
            'category' => 'news',
        ]);

        Page::factory()->create([
            'title' => 'My Blog Post',
            'slug' => 'my-blog-post',
            'status' => 'published',
            'category' => 'blog',
        ]);

        $this->artisan('make:sitemap')->assertExitCode(0);

        $disk = Storage::disk('file-storage');

        $disk->assertExists($this->tenantId . '/sitemap-pages.xml');
        $disk->assertExists($this->tenantId . '/sitemap-news.xml');
        $disk->assertExists($this->tenantId . '/sitemap-blog.xml');

        $this->assertStringContainsString('about-us', $disk->get($this->tenantId . '/sitemap-pages.xml'));
        $this->assertStringContainsString('latest-news', $disk->get($this->tenantId . '/sitemap-news.xml'));
        $this->assertStringContainsString('my-blog-post', $disk->get($this->tenantId . '/sitemap-blog.xml'));

        $pagesXml = $disk->get($this->tenantId . '/sitemap-pages.xml');
        $this->assertStringNotContainsString('latest-news', $pagesXml);
        $this->assertStringNotContainsString('my-blog-post', $pagesXml);
    }

    public function testUrlAuthoredAsPageWinsOverSameUrlFromDealership(): void
    {
        $this->makeSplitSetting(true);

        Settings::make([
            'tab' => 'Site',
            'section' => 'Dealerships',
            'group' => 'URLs',
            'name' => 'Dealership URL path',
            'config_key' => 'dealerships-url-path',
            'type' => 'string',
            'value' => '/locations/{{SLUG}}',
        ]);

        Page::factory()->create([
            'title' => 'Sandown Mercedes',
            'slug' => 'sandown-mercedes',
            'category' => 'locations',
            'status' => 'published',
        ]);

        Dealership::factory()->create([
            'name' => 'Sandown Mercedes',
            'slug' => 'sandown-mercedes',
            'active' => 1,
        ]);

        $this->artisan('make:sitemap')->assertExitCode(0);

        $disk = Storage::disk('file-storage');

        $pagesXml = $disk->get($this->tenantId . '/sitemap-pages.xml');
        $this->assertStringContainsString('/locations/sandown-mercedes', $pagesXml);

        $dealershipsPath = $this->tenantId . '/sitemap-dealerships.xml';
        if ($disk->exists($dealershipsPath)) {
            $this->assertStringNotContainsString(
                '/locations/sandown-mercedes</loc>',
                $disk->get($dealershipsPath)
            );
        }
    }

    public function testSplitSettingSeederRegistersDefaultOff(): void
    {
        $this->assertFalse(Settings::exists('seo-sitemap-split'));

        $this->seed(\Database\Seeders\Tenant\SeoSitemapSplitSettingSeeder::class);

        $this->assertTrue(Settings::exists('seo-sitemap-split'));
        $this->assertFalse((bool) Settings::get('seo-sitemap-split'));
    }

    private function makeSplitSetting(bool $value): void
    {
        Settings::make([
            'tab' => 'Site',
            'section' => 'SEO',
            'group' => 'Sitemap',
            'name' => 'Split sitemap by category',
            'config_key' => 'seo-sitemap-split',
            'type' => 'boolean',
            'value' => $value,
        ]);
    }
}
