<?php

declare(strict_types=1);

namespace App\Filament\Concerns;

use App\Models\ManagedEnvironment;
use App\Support\WorkspaceIsolation\TenantOwnedQueryScope;
use App\Support\WorkspaceIsolation\TenantOwnedRecordResolver;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;

trait InteractsWithTenantOwnedRecords
{
    protected static function tenantOwnedRelationshipName(): string
    {
        $relationshipName = property_exists(static::class, 'tenantOwnershipRelationshipName')
            ? static::$tenantOwnershipRelationshipName
            : null;

        return is_string($relationshipName) && $relationshipName !== ''
            ? $relationshipName
            : 'tenant';
    }

    protected static function resolveTenantContextForTenantOwnedRecords(): ?ManagedEnvironment
    {
        if (method_exists(static::class, 'resolveTenantContextForCurrentPanel')) {
            return static::resolveTenantContextForCurrentPanel();
        }

        if (method_exists(static::class, 'panelTenantContext')) {
            return static::panelTenantContext();
        }

        return null;
    }

    public static function getTenantOwnedEloquentQuery(): Builder
    {
        return static::scopeTenantOwnedQuery(parent::getEloquentQuery());
    }

    protected static function scopeTenantOwnedQuery(Builder $query, ?ManagedEnvironment $tenant = null): Builder
    {
        return app(TenantOwnedQueryScope::class)->apply(
            $query,
            $tenant ?? static::resolveTenantContextForTenantOwnedRecords(),
            static::tenantOwnedRelationshipName(),
        );
    }

    protected static function resolveTenantOwnedRecord(Model|int|string|null $record, ?Builder $query = null, ?ManagedEnvironment $tenant = null): ?Model
    {
        $scopedQuery = static::scopeTenantOwnedQuery(
            $query ?? parent::getEloquentQuery(),
            $tenant,
        );

        return app(TenantOwnedRecordResolver::class)->resolve($scopedQuery, $record);
    }

    protected static function resolveTenantOwnedRecordOrFail(Model|int|string|null $record, ?Builder $query = null, ?ManagedEnvironment $tenant = null): Model
    {
        $scopedQuery = static::scopeTenantOwnedQuery(
            $query ?? parent::getEloquentQuery(),
            $tenant,
        );

        return app(TenantOwnedRecordResolver::class)->resolveOrFail($scopedQuery, $record);
    }
}
