<?php

namespace PloverCRM\Core\Services;

use PloverCRM\Core\Container;
use PloverCRM\Core\CRM\CRMProviderInterface;

/**
 * Centralizes provisioning of system-managed fields based on active
 * capabilities instead of letting features create fields ad hoc.
 */
class SystemFieldProvisioner
{
    private Container $container;

    public function __construct(Container $container)
    {
        $this->container = $container;
    }

    public function syncCoreFields(): bool
    {
        return $this->syncStageField();
    }

    public function syncConfiguredCapabilities(): bool
    {
        return $this->provisionCapabilities([
            SystemFieldRegistry::CAPABILITY_CORE_STAGES,
        ]);
    }

    public function ensureCapabilityIfActive(string $capabilityId, ?CRMProviderInterface $crmOverride = null): bool
    {
        if (!$this->isCapabilityActive($capabilityId)) {
            return false;
        }

        return $this->ensureCapability($capabilityId, $crmOverride);
    }

    public function ensureCapability(string $capabilityId, ?CRMProviderInterface $crmOverride = null): bool
    {
        if ($capabilityId === SystemFieldRegistry::CAPABILITY_CORE_STAGES) {
            return $this->syncStageField(null, $crmOverride);
        }

        return $this->provisionCapabilities([$capabilityId], $crmOverride);
    }

    public function syncForProviderSwitch(): bool
    {
        return $this->syncConfiguredCapabilities();
    }

    public function syncStageField(?array $stages = null, ?CRMProviderInterface $crmOverride = null): bool
    {
        $crm = $this->resolveCrm($crmOverride);

        if (!$crm || !$crm->isAvailable()) {
            return false;
        }

        $stageField = $this->resolveStageFieldDefinition(
            SystemFieldRegistry::stageField($stages ?? []),
            $crm,
            $stages
        );

        return (bool) $crm->createOrUpdateCustomFields([$stageField]);
    }

    public function isCapabilityActive(string $capabilityId): bool
    {
        $capability = SystemCapabilityRegistry::get($capabilityId);
        if (!$capability) {
            return false;
        }

        $moduleId = $capability['module_id'] ?? null;
        if (is_string($moduleId) && $moduleId !== '' && !$this->isModuleActive($moduleId)) {
            return false;
        }

        if (($capability['provisioning'] ?? '') === 'configured') {
            return $this->isCapabilityConfigured($capabilityId);
        }

        return true;
    }

    public function isCapabilityConfigured(string $capabilityId): bool
    {
        return true;
    }

    private function provisionCapabilities(array $capabilityIds, ?CRMProviderInterface $crmOverride = null): bool
    {
        $crm = $this->resolveCrm($crmOverride);

        if (!$crm || !$crm->isAvailable()) {
            return false;
        }

        $fields = [];
        foreach ($capabilityIds as $capabilityId) {
            foreach (SystemFieldRegistry::getFieldsForCapability((string) $capabilityId) as $field) {
                if (($field['slug'] ?? '') === 'stage-plover-crm') {
                    $field = $this->resolveStageFieldDefinition($field, $crm);
                }

                $fields[(string) $field['slug']] = $field;
            }
        }

        if (empty($fields)) {
            return false;
        }

        return (bool) $crm->createOrUpdateCustomFields(array_values($fields));
    }

    private function resolveStageFieldDefinition(
        array $field,
        ?CRMProviderInterface $crmOverride = null,
        ?array $explicitStages = null
    ): array
    {
        $existingStageField = null;
        $crm = $this->resolveCrm($crmOverride);
        $existingFields = $crm ? (array) $crm->getAllCustomFields() : [];

        foreach ($existingFields as $existingField) {
            if (($existingField['slug'] ?? '') !== 'stage-plover-crm') {
                continue;
            }

            $existingStageField = $existingField;
            break;
        }

        $stageOptions = [];
        if ($explicitStages !== null) {
            $stageOptions = array_values(array_filter(array_map('strval', $explicitStages), static fn ($stage) => $stage !== ''));
        } elseif (!empty($existingStageField['options']) && is_array($existingStageField['options'])) {
            $stageOptions = array_values(array_filter(array_map('strval', $existingStageField['options'])));
        }

        if (empty($stageOptions)) {
            $defaultColors = get_option('plover_crm_stage_colors', []);
            if (!empty($defaultColors) && is_array($defaultColors)) {
                $stageOptions = array_keys($defaultColors);
            }
        }

        $stageField = SystemFieldRegistry::stageField($stageOptions);
        $providerName = $crm ? $crm->getName() : '';
        $stageFieldType = $providerName === 'FluentCRM' ? 'select-one' : 'select';
        $stageField['type'] = $stageFieldType;
        $stageField['field_key'] = $stageFieldType;

        return $stageField;
    }

    private function resolveCrm(?CRMProviderInterface $crmOverride = null): ?CRMProviderInterface
    {
        if ($crmOverride) {
            return $crmOverride;
        }

        $crm = $this->container->get('crm');
        return $crm instanceof CRMProviderInterface ? $crm : null;
    }

    private function isModuleActive(string $moduleId): bool
    {
        $disabledModules = get_option('plover_crm_disabled_modules', []);
        return !in_array($moduleId, $disabledModules, true);
    }
}
