<?php

namespace Tests\Tenant;

use App\Facades\Settings;
use Illuminate\Support\Facades\DB;
use Mtc\MercuryDataModels\Setting;
use Tests\TenantTestCase;

class EnsureSettingsHaveSourcesTest extends TenantTestCase
{
    protected bool $needsMasterDatabase = true;
    protected bool $useTestSettingRepository = false;

    public function testUpdateSettingSources()
    {
        collect([
            'app-content-blog-default-template',
            'app-content-news-default-template',
            'app-details-country',
            'app-details-currency',
        ])->each(fn($setting) => Settings::make([
            'tab' => 'test',
            'section' => 'test',
            'group' => 'test',
            'name' => 'test',
            'config_key' => $setting,
            'type' => 'text',
            'source' => null,
            'value' => null,
        ]));

        $this->artisan('settings:ensure-setting-sources')->assertExitCode(0);

        $this->assertEquals('templates', Setting::where('config_key', 'app-content-blog-default-template')->first()?->source);
        $this->assertEquals('templates', Setting::where('config_key', 'app-content-news-default-template')->first()?->source);
        $this->assertEquals('countries', Setting::where('config_key', 'app-details-country')->first()?->source);
        $this->assertEquals('currencies', Setting::where('config_key', 'app-details-currency')->first()?->source);

        $this->assertCount(4, Setting::where('type', 'string')->get());
        $this->assertCount(0, Setting::where('type', 'text')->get());
    }

    public function testUpdateSettingValues()
    {
        // use DB::table() instead of models to avoid any casting for value and value_text

        DB::table('settings')
            ->insert([
                'config_key' => 'app-content-news-default-template',
                'value' => 'foo',
                'value_text' => 'bar',
                'type' => 'text',
                'tab' => 'test',
                'section' => 'test',
                'group' => 'test',
                'name' => 'test',
            ]);

        DB::table('settings')
            ->insert([
                'config_key' => 'test-setting-not-to-be-changed',
                'value' => 'abc123',
                'value_text' => 'xyz456',
                'type' => 'text',
                'tab' => 'test',
                'section' => 'test',
                'group' => 'test',
                'name' => 'test',
            ]);

        // assert that the db holds different values for value and value_text
        $this->assertEquals(
            'foo',
            DB::table('settings')
                ->select('*')
                ->where('config_key', 'app-content-news-default-template')
                ->first()
                ?->value
        );
        $this->assertEquals(
            'bar',
            DB::table('settings')
                ->select('*')
                ->where('config_key', 'app-content-news-default-template')
                ->first()
                ?->value_text
        );

        $this->artisan('settings:ensure-setting-sources')->assertExitCode(0);

        // assert that value was overwritten with value_text
        $this->assertEquals(
            'bar',
            DB::table('settings')
                ->select('*')
                ->where('config_key', 'app-content-news-default-template')
                ->first()
                ?->value
        );
        $this->assertEquals(
            'bar',
            DB::table('settings')
                ->select('*')
                ->where('config_key', 'app-content-news-default-template')
                ->first()
                ?->value_text
        );
        $this->assertNull(
            DB::table('settings')
                ->select('*')
                ->where('config_key', 'test-setting-not-to-be-changed')
                ->first()
                ?->source
        );

        // assert that the setting facade returns the expected value
        $this->assertEquals('bar', Settings::get('app-content-news-default-template'));
        $this->assertEquals('xyz456', Settings::get('test-setting-not-to-be-changed'));
    }
}
