<?php

namespace PloverCRM\Modules\Automations\Services;

use PloverCRM\Modules\Integrations\Services\CurrencyService;

/**
 * Builds guided automation definitions from flat request payloads.
 */
class AutomationDefinitionBuilder
{
    public static function build(array $input, string $actionType, string $templateKey = ''): array
    {
        $normalizedActionType = self::resolveActionType($input, $actionType);

        switch ($normalizedActionType) {
            case 'send_google_ads_conversion':
                return self::buildGoogleAdsDefinition($input, $templateKey);

            case 'send_meta_capi_event':
                return self::buildMetaCapiDefinition($input, $templateKey);

            case 'send_internal_email':
            case '':
                return self::buildEmailDefinition($input, $templateKey);
        }

        return [
            'action_type' => $normalizedActionType,
            'builder_mode' => 'guided',
            'definition' => [
                'version' => 1,
                'meta' => [
                    'template_key' => $templateKey,
                ],
                'trigger' => [
                    'event' => '',
                ],
                'conditions' => [],
                'actions' => [],
            ],
            'errors' => ['Unsupported automation action type.'],
        ];
    }

    private static function resolveActionType(array $input, string $actionType): string
    {
        if ($actionType !== '') {
            return sanitize_text_field($actionType);
        }

        return sanitize_text_field((string) ($input['action_type'] ?? 'send_internal_email'));
    }

    private static function buildEmailDefinition(array $input, string $templateKey): array
    {
        $sourceFilter = sanitize_text_field($input['source_filter'] ?? 'any');
        $listIds = array_values(array_filter(array_map('absint', (array) ($input['list_ids'] ?? []))));
        $recipients = self::parseRecipients((string) ($input['recipients'] ?? ''));
        $subject = sanitize_text_field($input['subject'] ?? '');
        $body = wp_kses_post((string) ($input['body'] ?? ''));

        $definition = [
            'version' => 1,
            'meta' => [
                'template_key' => $templateKey,
            ],
            'trigger' => [
                'event' => 'contact_created_after_enrichment',
            ],
            'conditions' => [],
            'actions' => [
                [
                    'type' => 'send_internal_email',
                    'config' => [
                        'to' => $recipients,
                        'subject' => $subject,
                        'body' => $body,
                    ],
                ],
            ],
        ];

        if ($sourceFilter !== '' && $sourceFilter !== 'any') {
            $definition['conditions'][] = [
                'field' => 'contact.source',
                'operator' => 'equals',
                'value' => $sourceFilter,
            ];
        }

        if (!empty($listIds)) {
            $definition['conditions'][] = [
                'field' => 'contact.list_ids',
                'operator' => 'contains_any',
                'value' => $listIds,
            ];
        }

        return [
            'action_type' => 'send_internal_email',
            'builder_mode' => 'guided_email',
            'definition' => $definition,
            'errors' => [],
        ];
    }

    private static function buildGoogleAdsDefinition(array $input, string $templateKey): array
    {
        $stageTo = sanitize_text_field($input['stage_to'] ?? '');
        $connectionId = absint($input['google_connection_id'] ?? 0);
        $conversionActionId = sanitize_text_field($input['google_conversion_action_id'] ?? '');
        $conversionActionName = sanitize_text_field($input['google_conversion_action_name'] ?? '');
        $currencyCode = strtoupper(sanitize_text_field($input['google_currency_code'] ?? 'USD'));
        $conversionValue = trim((string) ($input['google_conversion_value'] ?? ''));
        $errors = [];

        if ($currencyCode !== '' && !CurrencyService::isValidCurrency($currencyCode)) {
            $errors[] = 'Choose a valid currency code for Google Ads conversions.';
        }

        $definition = [
            'version' => 1,
            'meta' => [
                'template_key' => $templateKey,
            ],
            'trigger' => [
                'event' => 'contact_stage_changed',
            ],
            'conditions' => [],
            'actions' => [
                [
                    'type' => 'send_google_ads_conversion',
                    'config' => [
                        'connection_id' => $connectionId,
                        'conversion_action_id' => $conversionActionId,
                        'conversion_action_name' => $conversionActionName,
                        'conversion_value' => $conversionValue !== '' ? (float) $conversionValue : null,
                        'currency_code' => $currencyCode !== '' ? $currencyCode : 'USD',
                    ],
                ],
            ],
        ];

        if ($stageTo !== '') {
            $definition['conditions'][] = [
                'field' => 'context.stage.to',
                'operator' => 'equals',
                'value' => $stageTo,
            ];
        }

        return [
            'action_type' => 'send_google_ads_conversion',
            'builder_mode' => 'guided_google_ads',
            'definition' => $definition,
            'errors' => $errors,
        ];
    }

    private static function buildMetaCapiDefinition(array $input, string $templateKey): array
    {
        $stageTo = sanitize_text_field($input['stage_to'] ?? '');
        $connectionId = absint($input['meta_connection_id'] ?? 0);
        $eventName = sanitize_text_field($input['meta_event_name'] ?? '');
        $customEventName = sanitize_text_field($input['meta_custom_event_name'] ?? '');
        $customData = [];
        $customDataErrors = [];

        $customDataParameterErrors = [];
        $customDataParameters = isset($input['meta_custom_data_parameters']) && is_array($input['meta_custom_data_parameters'])
            ? self::sanitizeMetaCustomDataParameters($input['meta_custom_data_parameters'])
            : [];
        $errors = array_merge($customDataErrors, $customDataParameterErrors);

        $definition = [
            'version' => 1,
            'meta' => [
                'template_key' => $templateKey,
            ],
            'trigger' => [
                'event' => 'contact_stage_changed',
            ],
            'conditions' => [],
            'actions' => [
                [
                    'type' => 'send_meta_capi_event',
                    'config' => [
                        'connection_id' => $connectionId,
                        'event_name' => $eventName,
                        'custom_event_name' => $customEventName,
                        'custom_data' => $customData,
                        'custom_data_parameters' => self::sanitizeMetaCustomDataParameters($customDataParameters),
                    ],
                ],
            ],
        ];

        if ($stageTo !== '') {
            $definition['conditions'][] = [
                'field' => 'context.stage.to',
                'operator' => 'equals',
                'value' => $stageTo,
            ];
        }

        return [
            'action_type' => 'send_meta_capi_event',
            'builder_mode' => 'guided_meta_capi',
            'definition' => $definition,
            'errors' => $errors,
        ];
    }

    private static function parseRecipients(string $value): array
    {
        $emails = array_map('trim', explode(',', $value));
        $emails = array_filter($emails, function ($email) {
            return is_email($email);
        });

        return array_values(array_unique($emails));
    }

    private static function sanitizeMetaCustomDataParameters(array $parameters): array
    {
        $sanitized = [];

        foreach ($parameters as $parameter) {
            if (!is_array($parameter)) {
                continue;
            }

            $type = sanitize_text_field((string) ($parameter['type'] ?? ''));
            $value = sanitize_text_field((string) ($parameter['value'] ?? ''));

            if ($type === '' || $value === '') {
                continue;
            }

            $sanitized[] = [
                'type' => $type,
                'value' => $value,
            ];
        }

        return $sanitized;
    }
}
