<?php

namespace Tests;

use App\Facades\Country;
use App\Facades\TaxonomyMapper;
use App\SiteRepository;
use App\Tier;
use Database\Seeders\Global\CountrySeeder;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Config;
use Mtc\MercuryDataModels\Tenant;
use Spatie\Permission\Middlewares\PermissionMiddleware;
use Spatie\Permission\Middlewares\RoleMiddleware;
use Stancl\Tenancy\Middleware\InitializeTenancyByPath;
use Stancl\Tenancy\Middleware\InitializeTenancyByRequestData;

abstract class TenantTestCase extends \Orchestra\Testbench\TestCase
{
    use CreatesApplication;
    use RefreshDatabase;
    use DispatchesJobs;

    protected bool $useTestSettingRepository = true;

    protected bool $mockCountryFacade = false;

    protected function setUp(): void
    {
        parent::setUp();
        $fakeTenant = new Tenant([
            'tier' => Tier::ENTERPRISE->value,
            'name' => 'foo faz',
        ]);
        $fakeTenant->id = 'test-tenant';

        $fakeTenant->features = collect([
            (object)['feature' => 'feature_a'],
            (object)['feature' => 'feature_b'],
        ]);

        $fakeTenant->primaryDomain = (object)[
            'domain' => 'foo.localhost'
        ];

        $this->withoutMiddleware([
            'auth:sanctum',
            InitializeTenancyByRequestData::class,
            PermissionMiddleware::class,
            RoleMiddleware::class,
            InitializeTenancyByPath::class,
        ]);

        \tenancy()->initialize($fakeTenant);
        Config::set('database.default', 'sqlite');

        $this->setupMocks();
    }

    protected function migrateUsing()
    {
        return [
            '--schema-path' => database_path('schema/test-tenant-schema.sql'),
            '--path' => database_path('migrations/tenant'),
            '--realpath' => true,
        ];
    }

    protected function setupMocks(): void
    {
        $this->mockCountryFacade();

        TaxonomyMapper::shouldReceive('getMappedTaxonomy')->andReturn(null);
        TaxonomyMapper::shouldReceive('storeUnmappedTaxonomies')->andReturn(false);

        $this->partialMock(SiteRepository::class, function ($mock) {
            $mock->shouldReceive('baseUrl')
                ->with(false)
                ->andReturn('http://foo.localhost');
            $mock->shouldReceive('baseUrl')
                ->with(true)
                ->andReturn('http://www.foo.localhost');
        });

        $this->app->bind('feature-flags', TestFeatureRepository::class);

        if ($this->useTestSettingRepository) {
            $this->app->bind('site-settings', TestSettingRepository::class);
        }
    }

    protected function mockCountryFacade()
    {
        if ($this->mockCountryFacade) {
            $fakeCountries = collect((new CountrySeeder())->getCountryData())
                ->map(fn($country) => (object)[
                    'name' => $country['name'],
                    'code' => $country['code'],
                    'has_postcodes' => $country['has_postcodes'],
                ]);

            Country::shouldReceive('getAll')
                ->andReturn($fakeCountries->map(fn($country) => (object)[
                    'name' => $country->name,
                    'code' => $country->code,
                ]));

            Country::shouldReceive('requiresPostcode')
                ->andReturnUsing(fn($code) => (bool)($fakeCountries->firstWhere('code', $code)?->has_postcodes));
        }
    }
}
