<?php

namespace MintyPHP\Module\Helpdesk\Service;

use MintyPHP\Http\SessionStoreInterface;

/**
 * Resolves the effective helpdesk BC config for the current request.
 *
 * Resolution rule:
 * - If the current tenant has an active override (override_enabled=1): tenant config.
 * - Otherwise: global config from the settings table.
 *
 * All runtime consumers (OData, SOAP, OAuth) should read through this service
 * instead of accessing HelpdeskSettingsGateway directly.
 */
class EffectiveHelpdeskSettingsService
{
    public function __construct(
        private readonly HelpdeskSettingsGateway $globalGateway,
        private readonly HelpdeskTenantSettingsGateway $tenantGateway,
        private readonly SessionStoreInterface $sessionStore
    ) {
    }

    /**
     * Resolve the effective settings for the given tenant.
     */
    public function resolveForTenant(int $tenantId): EffectiveHelpdeskSettings
    {
        if ($tenantId > 0 && $this->tenantGateway->isOverrideEnabled($tenantId)) {
            return $this->buildFromTenant($tenantId);
        }

        return $this->buildFromGlobal();
    }

    /**
     * Resolve for the current session tenant.
     */
    public function resolveForCurrentTenant(): EffectiveHelpdeskSettings
    {
        $tenantId = $this->resolveCurrentTenantId();

        return $this->resolveForTenant($tenantId);
    }

    // --- Proxy methods for gateway compatibility ---
    // These allow consumers to swap HelpdeskSettingsGateway → EffectiveHelpdeskSettingsService
    // with minimal code changes.

    public function getAuthMode(): string
    {
        return $this->resolveForCurrentTenant()->authMode;
    }

    public function getODataBaseUrl(): string
    {
        return $this->resolveForCurrentTenant()->odataBaseUrl;
    }

    public function getCompanyName(): string
    {
        return $this->resolveForCurrentTenant()->companyName;
    }

    public function getBasicUser(): ?string
    {
        return $this->resolveForCurrentTenant()->basicUser;
    }

    public function getBasicPassword(): ?string
    {
        return $this->resolveForCurrentTenant()->basicPassword;
    }

    public function getOAuthTenantId(): ?string
    {
        return $this->resolveForCurrentTenant()->oauthTenantId;
    }

    public function getOAuthClientId(): ?string
    {
        return $this->resolveForCurrentTenant()->oauthClientId;
    }

    public function getOAuthClientSecret(): ?string
    {
        return $this->resolveForCurrentTenant()->oauthClientSecret;
    }

    public function getOAuthTokenEndpoint(): ?string
    {
        return $this->resolveForCurrentTenant()->oauthTokenEndpoint;
    }

    public function buildEntityUrl(string $entitySet): string
    {
        return $this->resolveForCurrentTenant()->buildEntityUrl($entitySet);
    }

    /**
     * @return array<string>
     */
    public function validateConfiguration(): array
    {
        return $this->resolveForCurrentTenant()->validateConfiguration();
    }

    public function isConfigured(): bool
    {
        return $this->resolveForCurrentTenant()->isConfigured();
    }

    /**
     * @return array{
     *   config: array<string, mixed>,
     *   source: 'default'|'settings'|'fallback_invalid_json'
     * }
     */
    public function getSystemRecommendationsConfigEnvelope(): array
    {
        return $this->globalGateway->getSystemRecommendationsConfigEnvelope();
    }

    /**
     * @return array<string, mixed>
     */
    public function getSystemRecommendationsConfig(): array
    {
        return $this->globalGateway->getSystemRecommendationsConfig();
    }

    /**
     * @return array{
     *   config: array<string, mixed>,
     *   source: 'default'|'settings'|'fallback_invalid_json'
     * }
     */
    public function getControllingRiskConfigEnvelope(): array
    {
        return $this->globalGateway->getControllingRiskConfigEnvelope();
    }

    /**
     * @return array<string, mixed>
     */
    public function getControllingRiskConfig(): array
    {
        return $this->globalGateway->getControllingRiskConfig();
    }

    private function buildFromGlobal(): EffectiveHelpdeskSettings
    {
        return new EffectiveHelpdeskSettings(
            source: 'global',
            authMode: $this->globalGateway->getAuthMode(),
            odataBaseUrl: $this->globalGateway->getODataBaseUrl(),
            companyName: $this->globalGateway->getCompanyName(),
            basicUser: $this->globalGateway->getBasicUser(),
            basicPassword: $this->globalGateway->getBasicPassword(),
            oauthTenantId: $this->globalGateway->getOAuthTenantId(),
            oauthClientId: $this->globalGateway->getOAuthClientId(),
            oauthClientSecret: $this->globalGateway->getOAuthClientSecret(),
            oauthTokenEndpoint: $this->globalGateway->getOAuthTokenEndpoint(),
            systemRecommendationsConfigRaw: null,
            controllingRiskConfigRaw: null,
        );
    }

    private function buildFromTenant(int $tenantId): EffectiveHelpdeskSettings
    {
        return new EffectiveHelpdeskSettings(
            source: 'tenant',
            authMode: $this->tenantGateway->getAuthMode($tenantId),
            odataBaseUrl: $this->tenantGateway->getODataBaseUrl($tenantId),
            companyName: $this->tenantGateway->getCompanyName($tenantId),
            basicUser: $this->tenantGateway->getBasicUser($tenantId),
            basicPassword: $this->tenantGateway->getBasicPassword($tenantId),
            oauthTenantId: $this->tenantGateway->getOAuthTenantId($tenantId),
            oauthClientId: $this->tenantGateway->getOAuthClientId($tenantId),
            oauthClientSecret: $this->tenantGateway->getOAuthClientSecret($tenantId),
            oauthTokenEndpoint: $this->tenantGateway->getOAuthTokenEndpoint($tenantId),
            systemRecommendationsConfigRaw: $this->tenantGateway->getSystemRecommendationsConfig($tenantId),
            controllingRiskConfigRaw: $this->tenantGateway->getControllingRiskConfig($tenantId),
        );
    }

    private function resolveCurrentTenantId(): int
    {
        try {
            $session = $this->sessionStore->all();
        } catch (\Throwable) {
            // No active session (e.g. scheduler context) → fall back to global config
            return 0;
        }

        $tenant = $session['current_tenant'] ?? null;
        if (!is_array($tenant)) {
            return 0;
        }

        return (int) ($tenant['id'] ?? 0);
    }
}
