<?php

namespace PloverCRM\Core\Services;

use PloverCRM\Core\Container;
use PloverCRM\Core\CRM\CRMManager;

/**
 * Builds the general settings payload used by the standalone app.
 */
class GeneralSettingsPayloadBuilder
{
    public const REPLY_TO_EMAIL_OPTION = 'plover_crm_reply_to_email';
    public const ACTIVE_COLUMNS_OPTION = 'plover_crm_active_columns';

    public const DEFAULT_ACTIVE_COLUMNS = [
        'full_name',
        'email',
        'phone',
        'city',
        'country',
        'created_at',
        'stage-plover-crm',
    ];

    private const EXCLUDED_COLUMNS = [
        'id',
        'user_id',
        'hash',
        'contact_owner',
        'company_id',
        'prefix',
        'latitude',
        'longitude',
        'total_points',
        'life_time_value',
        'lead_type',
        'contact_type',
        'avatar',
        'photo',
        'custom_fields',
        'last_activity',
        'updated_at',
        'plover_crm_avatar',
    ];

    public static function build(Container $container): array
    {
        return array_merge(
            self::buildCrmSettings($container),
            self::buildLeadTableSettings($container)
        );
    }

    public static function buildCrmSettings(Container $container): array
    {
        /** @var CRMManager $crmManager */
        $crmManager = $container->get('crm');
        $selectedProviderId = (string) get_option(
            'plover_crm_selected_crm',
            $crmManager->getSelectedProviderId()
        );

        if ($selectedProviderId === '') {
            $selectedProviderId = $crmManager->getSelectedProviderId();
        }

        return [
            'selectedProviderId' => $selectedProviderId,
            'currentProviderId' => $crmManager->getSelectedProviderId(),
            'currentProviderName' => $crmManager->getName(),
            'replyToEmail' => self::getReplyToEmail(),
            'providers' => self::serializeProviders($crmManager, $selectedProviderId),
            'workspace' => WorkspacePayloadBuilder::build($container),
        ];
    }

    public static function buildLeadTableSettings(Container $container): array
    {
        $selectableColumns = self::getSelectableColumnSlugs($container);
        $activeColumns = self::sanitizeActiveColumns(
            self::getActiveColumns(),
            $selectableColumns
        );

        return [
            'activeColumns' => $activeColumns,
        ];
    }

    public static function getReplyToEmail(): string
    {
        return (string) get_option(self::REPLY_TO_EMAIL_OPTION, get_option('admin_email', ''));
    }

    public static function getActiveColumns(): array
    {
        $activeColumns = get_option(self::ACTIVE_COLUMNS_OPTION, self::DEFAULT_ACTIVE_COLUMNS);

        if (!is_array($activeColumns)) {
            return self::DEFAULT_ACTIVE_COLUMNS;
        }

        return array_values(array_map('strval', $activeColumns));
    }

    public static function getValidColumnSlugs(Container $container): array
    {
        $workspace = WorkspacePayloadBuilder::build($container);
        $standardFields = array_map('strval', (array) ($workspace['standardFields'] ?? []));
        $customFieldSlugs = array_values(array_filter(array_map(static function ($field) {
            return is_array($field) ? (string) ($field['slug'] ?? '') : '';
        }, (array) ($workspace['customFields'] ?? []))));

        return array_values(array_unique(array_merge($standardFields, $customFieldSlugs)));
    }

    public static function getSelectableColumnSlugs(Container $container): array
    {
        return array_values(array_filter(
            self::getValidColumnSlugs($container),
            static fn($column) => !in_array($column, self::EXCLUDED_COLUMNS, true)
        ));
    }

    public static function refreshCrmService(Container $container): void
    {
        if ($container->has('crm')) {
            $container->remove('crm');
        }

        $container->singleton('crm', static function () {
            return new CRMManager();
        });
    }

    private static function serializeProviders(CRMManager $crmManager, string $selectedProviderId): array
    {
        $availableProviders = $crmManager->getAvailableProviders();
        $validationResults = $crmManager->getValidationResults();
        $currentProviderId = $crmManager->getSelectedProviderId();
        $providers = [];

        foreach ($availableProviders as $providerId => $provider) {
            $validation = $validationResults[$providerId] ?? ['valid' => true, 'errors' => []];

            $providers[] = [
                'id' => (string) $providerId,
                'name' => (string) ($provider['name'] ?? $providerId),
                'available' => !empty($provider['available']),
                'enabled' => !empty($provider['enabled']),
                'isSelected' => $selectedProviderId === $providerId,
                'isCurrent' => $currentProviderId === $providerId,
                'validation' => [
                    'valid' => !empty($validation['valid']),
                    'errors' => array_values(array_map('strval', (array) ($validation['errors'] ?? []))),
                ],
            ];
        }

        return $providers;
    }

    private static function sanitizeActiveColumns(array $activeColumns, array $validColumns): array
    {
        return array_values(array_filter(
            array_map('strval', $activeColumns),
            static fn($column) => in_array($column, $validColumns, true)
        ));
    }
}
