<?php

namespace App\Modules\Registrar\CentralNic;

use App\Core\Registrar\AbstractRegistrar;
use App\Models\Registrar;
use Illuminate\Support\Facades\Log;

class CentralNic extends AbstractRegistrar
{
    /**
     * CentralNic Reseller REST API endpoint (live)
     */
    protected string $apiUrl = 'https://api.centralnicreseller.com/api/call.cgi';

    /**
     * CentralNic Reseller REST API endpoint (test/OTE)
     */
    protected string $testApiUrl = 'https://api-ote.centralnicreseller.com/api/call.cgi';

    // -------------------------------------------------------------------------
    //  Constructor
    // -------------------------------------------------------------------------

    public function __construct(array $config = [], ?Registrar $registrarModel = null)
    {
        parent::__construct($config, $registrarModel);
    }

    // -------------------------------------------------------------------------
    //  Module Meta
    // -------------------------------------------------------------------------

    public function getModuleInfo(): array
    {
        $defaultInfo = parent::getModuleInfo();

        return array_merge($defaultInfo, [
            'label' => 'CentralNic Reseller',
            'description' => 'CentralNic Reseller (formerly RRPproxy) domain registrar with extensive TLD support',
            'features' => [
                'domain_register' => true,
                'domain_transfer' => true,
                'domain_renew' => true,
                'domain_nameservers' => true,
                'domain_contacts' => true,
                'domain_epp' => true,
                'domain_lock' => true,
                'domain_availability' => true,
                'domain_pricing' => true,
            ],
        ]);
    }

    // -------------------------------------------------------------------------
    //  Config Fields
    // -------------------------------------------------------------------------

    public function getConfigFields(): array
    {
        return [
            'username' => [
                'type' => 'text',
                'label' => __('admin/modules.centralnic_field_username_label'),
                'required' => true,
                'description' => __('admin/modules.centralnic_field_username_description'),
                'placeholder' => 'your_username',
                'value' => $this->config['username'] ?? '',
            ],
            'password' => [
                'type' => 'password',
                'label' => __('admin/modules.centralnic_field_password_label'),
                'required' => true,
                'description' => __('admin/modules.centralnic_field_password_description'),
                'placeholder' => '********',
                'value' => $this->config['password'] ?? '',
            ],
            'test_mode' => [
                'type' => 'checkbox',
                'label' => __('admin/modules.centralnic_field_test_mode_label'),
                'required' => false,
                'description' => __('admin/modules.centralnic_field_test_mode_description'),
                'value' => $this->config['test_mode'] ?? false,
            ],
        ];
    }

    // -------------------------------------------------------------------------
    //  Config Validation
    // -------------------------------------------------------------------------

    public function validateConfig()
    {
        if (empty($this->config['username'])) {
            throw new \Exception(__('admin/modules.centralnic_config_username_missing'));
        }

        if (empty($this->config['password'])) {
            throw new \Exception(__('admin/modules.centralnic_config_password_missing'));
        }

        return true;
    }

    // -------------------------------------------------------------------------
    //  Domain Registration
    // -------------------------------------------------------------------------

    public function registerDomain(array $params)
    {
        $domain = $params['domain'] ?? '';
        if (empty($domain)) {
            return $this->errorResponse(__('admin/modules.centralnic_domain_required'));
        }

        try {
            $this->validateConfig();

            // Contact handle passed explicitly (re-use existing handle) short-circuits AddContact.
            $contactId = $params['owner_contact'] ?? $params['contact_id'] ?? '';

            // PRC-969: source the registrant contact from the canonical group via
            // contact() and create it with a dedicated AddContact command; ISPAPI
            // AddDomain requires contact HANDLES, not inline contact fields.
            if (empty($contactId)) {
                $contactResult = $this->callApi('AddContact', $this->buildAddContactParams($params, 'registrant'));

                if (!$this->isSuccess($contactResult)) {
                    return $this->errorResponse($this->getErrorMessage($contactResult));
                }

                $contactId = $contactResult['property']['contact'][0] ?? '';
            }

            $apiParams = [
                'domain' => $domain,
                'period' => ($params['period'] ?? $params['years'] ?? 1),
                'ownercontact0' => $params['owner_contact'] ?? $contactId,
                'admincontact0' => $params['admin_contact'] ?? $contactId,
                'techcontact0' => $params['tech_contact'] ?? $contactId,
                'billingcontact0' => $params['billing_contact'] ?? $contactId,
            ];

            // Add nameservers (nameserver0..nameserverN)
            $nameservers = $this->extractNameservers($params);
            foreach ($nameservers as $index => $ns) {
                $apiParams['nameserver'.$index] = $ns;
            }

            // TLD-specific X-* additional fields (.ca/.it/.us/.es/.de/.eu/.tel)
            $apiParams = $this->applyTldSpecificFields($params, $apiParams);

            $result = $this->callApi('AddDomain', $apiParams);

            if (!$this->isSuccess($result)) {
                return $this->errorResponse($this->getErrorMessage($result));
            }

            Log::info('CentralNic: Domain registered', [
                'domain' => $domain,
            ]);

            return $this->successResponse(__('admin/modules.centralnic_register_success'), [
                'domain' => $domain,
                'period' => $apiParams['period'],
                'contact_id' => $contactId,
                'expiry_date' => $result['property']['registration expiration date'][0] ?? null,
            ]);
        } catch (\Exception $e) {
            Log::error('CentralNic: Register domain error', ['domain' => $domain, 'error' => $e->getMessage()]);

            return $this->errorResponse($e->getMessage());
        }
    }

    // -------------------------------------------------------------------------
    //  Domain Transfer
    // -------------------------------------------------------------------------

    public function transferDomain(array $params)
    {
        $domain = $params['domain'] ?? '';
        if (empty($domain)) {
            return $this->errorResponse(__('admin/modules.centralnic_domain_required'));
        }

        try {
            $this->validateConfig();

            $auth = $params['epp_code'] ?? $params['authcode'] ?? $params['auth'] ?? '';
            if (empty($auth)) {
                return $this->errorResponse(__('admin/modules.centralnic_epp_required'));
            }

            $apiParams = [
                'domain' => $domain,
                'auth' => $auth,
                'action' => 'REQUEST', // ISPAPI TransferDomain requires an explicit action
                'period' => ($params['period'] ?? $params['years'] ?? 1),
            ];

            // Add contact handles if provided
            if (!empty($params['owner_contact'] ?? $params['contact_id'] ?? '')) {
                $apiParams['ownercontact0'] = $params['owner_contact'] ?? $params['contact_id'];
                $apiParams['admincontact0'] = $params['admin_contact'] ?? $params['contact_id'];
                $apiParams['techcontact0'] = $params['tech_contact'] ?? $params['contact_id'];
                $apiParams['billingcontact0'] = $params['billing_contact'] ?? $params['contact_id'];
            }

            $result = $this->callApi('TransferDomain', $apiParams);

            if (!$this->isSuccess($result)) {
                return $this->errorResponse($this->getErrorMessage($result));
            }

            Log::info('CentralNic: Domain transfer initiated', [
                'domain' => $domain,
            ]);

            return $this->successResponse(__('admin/modules.centralnic_transfer_success'), [
                'domain' => $domain,
            ]);
        } catch (\Exception $e) {
            Log::error('CentralNic: Transfer domain error', ['domain' => $domain, 'error' => $e->getMessage()]);

            return $this->errorResponse($e->getMessage());
        }
    }

    // -------------------------------------------------------------------------
    //  Domain Renewal
    // -------------------------------------------------------------------------

    public function renewDomain(array $params)
    {
        $domain = $params['domain'] ?? '';
        if (empty($domain)) {
            return $this->errorResponse(__('admin/modules.centralnic_domain_required'));
        }

        try {
            $this->validateConfig();

            $apiParams = [
                'domain' => $domain,
                'period' => ($params['period'] ?? $params['years'] ?? 1),
            ];

            // ISPAPI RenewDomain expects `expiration` as the current expiry YEAR (Y).
            $expiryYear = null;
            if (!empty($params['expiry_date'])) {
                $expiryYear = date('Y', strtotime($params['expiry_date']));
            } elseif (!empty($params['expires_at'])) {
                $expiryYear = date('Y', strtotime($params['expires_at']));
            }

            if (empty($expiryYear)) {
                $statusResult = $this->callApi('StatusDomain', ['domain' => $domain]);
                $currentExpiry = $statusResult['property']['registration expiration date'][0] ?? '';
                if ($this->isSuccess($statusResult) && !empty($currentExpiry)) {
                    $expiryYear = date('Y', strtotime($currentExpiry));
                }
            }

            if (!empty($expiryYear)) {
                $apiParams['expiration'] = $expiryYear;
            }

            $result = $this->callApi('RenewDomain', $apiParams);

            if (!$this->isSuccess($result)) {
                return $this->errorResponse($this->getErrorMessage($result));
            }

            Log::info('CentralNic: Domain renewed', ['domain' => $domain]);

            return $this->successResponse(__('admin/modules.centralnic_renew_success'), [
                'domain' => $domain,
                'period' => $apiParams['period'],
                'expiry_date' => $result['property']['registration expiration date'][0] ?? null,
            ]);
        } catch (\Exception $e) {
            Log::error('CentralNic: Renew domain error', ['domain' => $domain, 'error' => $e->getMessage()]);

            return $this->errorResponse($e->getMessage());
        }
    }

    // -------------------------------------------------------------------------
    //  Nameservers
    // -------------------------------------------------------------------------

    public function getNameservers(array $params)
    {
        $domain = $params['domain'] ?? '';
        if (empty($domain)) {
            return $this->errorResponse(__('admin/modules.centralnic_domain_required'));
        }

        try {
            $this->validateConfig();

            $result = $this->callApi('StatusDomain', [
                'domain' => $domain,
            ]);

            if (!$this->isSuccess($result)) {
                return $this->errorResponse($this->getErrorMessage($result));
            }

            $nameservers = $result['property']['nameserver'] ?? [];

            return $this->successResponse(__('admin/modules.centralnic_nameservers_retrieved'), [
                'domain' => $domain,
                'nameservers' => array_values(array_filter($nameservers)),
            ]);
        } catch (\Exception $e) {
            return $this->errorResponse($e->getMessage());
        }
    }

    public function setNameservers(array $params)
    {
        $domain = $params['domain'] ?? '';
        if (empty($domain)) {
            return $this->errorResponse(__('admin/modules.centralnic_domain_required'));
        }

        try {
            $this->validateConfig();

            $apiParams = [
                'domain' => $domain,
            ];

            $nameservers = $this->extractNameservers($params);
            foreach ($nameservers as $index => $ns) {
                $apiParams['nameserver'.$index] = $ns;
            }

            if (empty($nameservers)) {
                return $this->errorResponse(__('admin/modules.centralnic_nameservers_required'));
            }

            $result = $this->callApi('ModifyDomain', $apiParams);

            if (!$this->isSuccess($result)) {
                return $this->errorResponse($this->getErrorMessage($result));
            }

            Log::info('CentralNic: Nameservers updated', ['domain' => $domain, 'nameservers' => $nameservers]);

            return $this->successResponse(__('admin/modules.centralnic_nameservers_updated'), [
                'domain' => $domain,
                'nameservers' => $nameservers,
            ]);
        } catch (\Exception $e) {
            return $this->errorResponse($e->getMessage());
        }
    }

    // -------------------------------------------------------------------------
    //  Contact Details
    // -------------------------------------------------------------------------

    public function getContactDetails(array $params)
    {
        $domain = $params['domain'] ?? '';
        if (empty($domain)) {
            return $this->errorResponse(__('admin/modules.centralnic_domain_required'));
        }

        try {
            $this->validateConfig();

            $result = $this->callApi('StatusDomain', [
                'domain' => $domain,
            ]);

            if (!$this->isSuccess($result)) {
                return $this->errorResponse($this->getErrorMessage($result));
            }

            $groups = [];
            // REGISTRAR_RESPONSE_CONTRACT expects `groups` keyed by
            // Registrant/Admin/Tech/Billing. These labels must match the
            // setContactMap round-trip (#4). ISPAPI StatusDomain returns
            // spaced property names: `owner contact`, etc.
            $contactTypes = [
                'Registrant' => 'owner contact',
                'Admin' => 'admin contact',
                'Tech' => 'tech contact',
                'Billing' => 'billing contact',
            ];

            foreach ($contactTypes as $group => $property) {
                $contactHandle = $result['property'][$property][0] ?? null;
                if ($contactHandle) {
                    $contactData = $this->fetchContactData($contactHandle);
                    if ($contactData !== null) {
                        $groups[$group] = array_merge(['handle' => $contactHandle], $contactData);
                    }
                }
            }

            return $this->successResponse(__('admin/modules.centralnic_contacts_retrieved'), [
                'domain' => $domain,
                'groups' => $groups,
            ]);
        } catch (\Exception $e) {
            return $this->errorResponse($e->getMessage());
        }
    }

    public function setContactDetails(array $params)
    {
        $domain = $params['domain'] ?? '';
        if (empty($domain)) {
            return $this->errorResponse(__('admin/modules.centralnic_domain_required'));
        }

        try {
            $this->validateConfig();

            // Preferred path (#4 round-trip): modifyContact passes module-authored
            // groups[] through unmodified. Resolve current handles from StatusDomain
            // and ModifyContact each with singular ISPAPI field names.
            if (!empty($params['groups']) && is_array($params['groups'])) {
                $domainStatus = $this->callApi('StatusDomain', ['domain' => $domain]);

                if (!$this->isSuccess($domainStatus)) {
                    return $this->errorResponse($this->getErrorMessage($domainStatus));
                }

                // Labels MUST match getContactDetails' emitted group keys so the
                // admin UI round-trips correctly (#4). `Owner` legacy alias kept
                // for backward compatibility with older payloads.
                $contactMap = [
                    'Registrant' => $domainStatus['property']['owner contact'][0] ?? '',
                    'Owner' => $domainStatus['property']['owner contact'][0] ?? '',
                    'Admin' => $domainStatus['property']['admin contact'][0] ?? '',
                    'Tech' => $domainStatus['property']['tech contact'][0] ?? '',
                    'Billing' => $domainStatus['property']['billing contact'][0] ?? '',
                ];

                $errors = [];
                foreach ($params['groups'] as $groupName => $contactDetails) {
                    $handle = $contactMap[$groupName] ?? '';
                    if (empty($handle) || !is_array($contactDetails)) {
                        continue;
                    }

                    // Accept both the module's own emitted field names (round-trip
                    // from getContactDetails: organization/street/zip/country) and
                    // common alternative labels.
                    $modifyResult = $this->callApi('ModifyContact', [
                        'contact' => $handle,
                        'firstname' => $contactDetails['firstname'] ?? $contactDetails['First Name'] ?? '',
                        'lastname' => $contactDetails['lastname'] ?? $contactDetails['Last Name'] ?? '',
                        'organization' => $contactDetails['organization'] ?? $contactDetails['company'] ?? $contactDetails['Organisation'] ?? '',
                        'street' => $contactDetails['street'] ?? $contactDetails['address'] ?? $contactDetails['Street'] ?? '',
                        'city' => $contactDetails['city'] ?? $contactDetails['City'] ?? '',
                        'state' => $contactDetails['state'] ?? $contactDetails['State'] ?? '',
                        'zip' => $contactDetails['zip'] ?? $contactDetails['postal_code'] ?? $contactDetails['Zip'] ?? '',
                        'country' => $contactDetails['country'] ?? $contactDetails['Country'] ?? '',
                        'phone' => $contactDetails['phone'] ?? $contactDetails['Phone'] ?? '',
                        'fax' => $contactDetails['fax'] ?? $contactDetails['Fax'] ?? '',
                        'email' => $contactDetails['email'] ?? $contactDetails['Email'] ?? '',
                    ]);

                    if (!$this->isSuccess($modifyResult)) {
                        $errors[] = $groupName.': '.$this->getErrorMessage($modifyResult);
                    }
                }

                if (!empty($errors)) {
                    return $this->errorResponse(implode('; ', $errors));
                }

                Log::info('CentralNic: Contact details updated', [
                    'domain' => $domain,
                    'groups' => array_keys($params['groups']),
                ]);

                return $this->successResponse(__('admin/modules.centralnic_contacts_updated'), [
                    'domain' => $domain,
                ]);
            }

            // Direct contact-handle modification (singular ISPAPI field names).
            $contactHandle = $params['contact_handle'] ?? $params['contact'] ?? null;
            if ($contactHandle) {
                $apiParams = [
                    'contact' => $contactHandle,
                    'firstname' => $params['firstname'] ?? '',
                    'lastname' => $params['lastname'] ?? '',
                    'organization' => $params['company'] ?? $params['organization'] ?? '',
                    'street' => $params['address1'] ?? $params['address'] ?? '',
                    'city' => $params['city'] ?? '',
                    'state' => $params['state'] ?? '',
                    'zip' => $params['postcode'] ?? $params['postal_code'] ?? '',
                    'country' => $params['country'] ?? '',
                    'phone' => $params['phone'] ?? $params['phonenumber'] ?? '',
                    'email' => $params['email'] ?? '',
                ];

                if (!empty($params['fax'])) {
                    $apiParams['fax'] = $params['fax'];
                }

                $result = $this->callApi('ModifyContact', $apiParams);
            } else {
                // Re-assign domain contact handles via ModifyDomain
                $apiParams = ['domain' => $domain];

                if (!empty($params['owner_contact'])) {
                    $apiParams['ownercontact0'] = $params['owner_contact'];
                }
                if (!empty($params['admin_contact'])) {
                    $apiParams['admincontact0'] = $params['admin_contact'];
                }
                if (!empty($params['tech_contact'])) {
                    $apiParams['techcontact0'] = $params['tech_contact'];
                }
                if (!empty($params['billing_contact'])) {
                    $apiParams['billingcontact0'] = $params['billing_contact'];
                }

                $result = $this->callApi('ModifyDomain', $apiParams);
            }

            if (!$this->isSuccess($result)) {
                return $this->errorResponse($this->getErrorMessage($result));
            }

            Log::info('CentralNic: Contact details updated', ['domain' => $domain]);

            return $this->successResponse(__('admin/modules.centralnic_contacts_updated'), [
                'domain' => $domain,
            ]);
        } catch (\Exception $e) {
            return $this->errorResponse($e->getMessage());
        }
    }

    // -------------------------------------------------------------------------
    //  Domain Details
    // -------------------------------------------------------------------------

    public function getDomainDetails(array $params)
    {
        $domain = $params['domain'] ?? '';
        if (empty($domain)) {
            return $this->errorResponse(__('admin/modules.centralnic_domain_required'));
        }

        try {
            $this->validateConfig();

            $result = $this->callApi('StatusDomain', [
                'domain' => $domain,
            ]);

            if (!$this->isSuccess($result)) {
                return $this->errorResponse($this->getErrorMessage($result));
            }

            $properties = $result['property'] ?? [];

            return $this->successResponse(__('admin/modules.centralnic_domain_details_retrieved'), [
                'domain' => $domain,
                'status' => $properties['status'][0] ?? '',
                // ISPAPI StatusDomain uses spaced property names.
                'creation_date' => $properties['created date'][0] ?? $properties['registration date'][0] ?? '',
                'expiry_date' => $properties['registration expiration date'][0] ?? $properties['paiduntildate'][0] ?? '',
                'updated_date' => $properties['updated date'][0] ?? '',
                'nameservers' => array_values(array_filter($properties['nameserver'] ?? [])),
                'registrar_lock' => in_array('clientTransferProhibited', $properties['status'] ?? []),
                'owner_contact' => $properties['owner contact'][0] ?? '',
                'admin_contact' => $properties['admin contact'][0] ?? '',
                'tech_contact' => $properties['tech contact'][0] ?? '',
                'billing_contact' => $properties['billing contact'][0] ?? '',
                'auth_code' => $properties['auth'][0] ?? $properties['authcode'][0] ?? '',
            ]);
        } catch (\Exception $e) {
            return $this->errorResponse($e->getMessage());
        }
    }

    // -------------------------------------------------------------------------
    //  Domain Lock
    // -------------------------------------------------------------------------

    public function getDomainLock(array $params)
    {
        $domain = $params['domain'] ?? '';
        if (empty($domain)) {
            return $this->errorResponse(__('admin/modules.centralnic_domain_required'));
        }

        try {
            $this->validateConfig();

            $result = $this->callApi('StatusDomain', [
                'domain' => $domain,
            ]);

            if (!$this->isSuccess($result)) {
                return $this->errorResponse($this->getErrorMessage($result));
            }

            $transferLock = false;
            $properties = $result['property'] ?? [];

            // Check transferlock property
            if (isset($properties['transferlock'])) {
                $transferLock = (int) ($properties['transferlock'][0] ?? 0) === 1;
            }

            // Also check domain status for clientTransferProhibited
            $statuses = $properties['status'] ?? [];
            if (in_array('clientTransferProhibited', $statuses)) {
                $transferLock = true;
            }

            return $this->successResponse(__('admin/modules.centralnic_lock_status_retrieved'), [
                'domain' => $domain,
                'locked' => $transferLock,
            ]);
        } catch (\Exception $e) {
            return $this->errorResponse($e->getMessage());
        }
    }

    public function updateDomainLock(array $params)
    {
        $domain = $params['domain'] ?? '';
        if (empty($domain)) {
            return $this->errorResponse(__('admin/modules.centralnic_domain_required'));
        }

        try {
            $this->validateConfig();

            $lockEnabled = $params['lock_status'] ?? $params['locked'] ?? true;
            $lockValue = filter_var($lockEnabled, FILTER_VALIDATE_BOOLEAN) ? 1 : 0;

            $result = $this->callApi('ModifyDomain', [
                'domain' => $domain,
                'transferlock' => $lockValue,
            ]);

            if (!$this->isSuccess($result)) {
                return $this->errorResponse($this->getErrorMessage($result));
            }

            Log::info('CentralNic: Domain lock updated', ['domain' => $domain, 'locked' => (bool) $lockValue]);

            return $this->successResponse(__('admin/modules.centralnic_lock_updated'), [
                'domain' => $domain,
                'locked' => (bool) $lockValue,
            ]);
        } catch (\Exception $e) {
            return $this->errorResponse($e->getMessage());
        }
    }

    // -------------------------------------------------------------------------
    //  EPP Code
    // -------------------------------------------------------------------------

    public function getEppCode(array $params)
    {
        $domain = $params['domain'] ?? '';
        if (empty($domain)) {
            return $this->errorResponse(__('admin/modules.centralnic_domain_required'));
        }

        try {
            $this->validateConfig();

            $result = $this->callApi('StatusDomain', [
                'domain' => $domain,
            ]);

            if (!$this->isSuccess($result)) {
                return $this->errorResponse($this->getErrorMessage($result));
            }

            $authCode = $result['property']['auth'][0]
                ?? $result['property']['authcode'][0]
                ?? $result['property']['authorization'][0]
                ?? '';

            if (empty($authCode)) {
                return $this->errorResponse(__('admin/modules.centralnic_epp_not_available'));
            }

            return $this->successResponse(__('admin/modules.centralnic_epp_retrieved'), [
                'domain' => $domain,
                'epp_code' => $authCode,
            ]);
        } catch (\Exception $e) {
            return $this->errorResponse($e->getMessage());
        }
    }

    // -------------------------------------------------------------------------
    //  Domain Availability Check
    // -------------------------------------------------------------------------

    public function checkDomainAvailability(array $params)
    {
        $domains = $params['domains'] ?? [];

        // Support single domain via 'domain' key
        if (empty($domains) && !empty($params['domain'])) {
            $domains = [$params['domain']];
        }

        if (empty($domains)) {
            return $this->errorResponse(__('admin/modules.centralnic_domain_required'));
        }

        try {
            $this->validateConfig();

            // ISPAPI CheckDomain is single-domain; the top-level response code is
            // the authority (210 available, 211 taken). Loop for multiple domains.
            // Emit a 0-based indexed `results` list so the canonical DomainService
            // parser (data.results[0].available) picks it up; also expose a
            // top-level `available` for the single-domain path.
            $availability = [];
            $byDomain = [];
            foreach (array_values($domains) as $domain) {
                if (empty($domain)) {
                    continue;
                }

                $result = $this->callApi('CheckDomain', ['domain' => $domain]);
                $statusCode = (int) ($result['code'] ?? 0);

                $entry = [
                    'domain' => $domain,
                    'available' => $statusCode === 210,
                    'status' => $this->mapAvailabilityStatus($statusCode),
                    'reason' => $result['description'] ?? '',
                ];

                $availability[] = $entry;
                $byDomain[$domain] = $entry;
            }

            return $this->successResponse(__('admin/modules.centralnic_availability_checked'), [
                'available' => $availability[0]['available'] ?? false,
                'results' => $availability,
                'results_by_domain' => $byDomain,
            ]);
        } catch (\Exception $e) {
            return $this->errorResponse($e->getMessage());
        }
    }

    // -------------------------------------------------------------------------
    //  Domain Pricing
    // -------------------------------------------------------------------------

    public function getDomainPricings(array $params)
    {
        try {
            $this->validateConfig();

            $result = $this->callApi('QueryDomainPricing', $params);

            if (!$this->isSuccess($result)) {
                return $this->errorResponse($this->getErrorMessage($result));
            }

            $pricings = [];
            $properties = $result['property'] ?? [];

            $zones = $properties['zone'] ?? [];
            $registerPrices = $properties['registerprice'] ?? [];
            $renewPrices = $properties['renewprice'] ?? [];
            $transferPrices = $properties['transferprice'] ?? [];
            $currencies = $properties['currency'] ?? [];
            $periods = $properties['period'] ?? [];

            foreach ($zones as $index => $zone) {
                $pricings[$zone] = [
                    'tld' => $zone,
                    'register' => $registerPrices[$index] ?? null,
                    'renew' => $renewPrices[$index] ?? null,
                    'transfer' => $transferPrices[$index] ?? null,
                    'currency' => $currencies[$index] ?? $currencies[0] ?? 'USD',
                    'period' => $periods[$index] ?? 1,
                ];
            }

            return $this->successResponse(__('admin/modules.centralnic_pricing_retrieved'), [
                'pricings' => $pricings,
            ]);
        } catch (\Exception $e) {
            return $this->errorResponse($e->getMessage());
        }
    }

    // -------------------------------------------------------------------------
    //  WHOIS Privacy
    // -------------------------------------------------------------------------

    public function getPrivacySettings(array $params)
    {
        $domain = $params['domain'] ?? '';
        if (empty($domain)) {
            return $this->errorResponse(__('admin/modules.centralnic_domain_required'));
        }

        try {
            $this->validateConfig();

            $result = $this->callApi('StatusDomain', ['domain' => $domain]);

            if (!$this->isSuccess($result)) {
                return $this->errorResponse($this->getErrorMessage($result));
            }

            // ISPAPI reflects trustee/privacy acceptance via X-ACCEPT-WHOISTRUSTEE-TAC
            // (same flag the write path toggles). NOTE: exact StatusDomain property
            // name is UNVERIFIED against official ISPAPI docs; candidate keys cover
            // the known flag naming. Confirm before relying on it for billing/UI.
            $whoisPrivacy = $result['property']['x-accept-whoistrustee-tac'][0]
                ?? $result['property']['whoistrustee'][0]
                ?? $result['property']['trustee'][0]
                ?? $result['property']['whois privacy'][0]
                ?? '0';
            $privacyEnabled = in_array(strtolower((string) $whoisPrivacy), ['1', 'yes', 'true', 'on'], true);

            return $this->successResponse(__('admin/modules.centralnic_privacy_retrieved'), [
                'domain' => $domain,
                'privacy_enabled' => $privacyEnabled,
                'available' => true,
            ]);
        } catch (\Exception $e) {
            return $this->errorResponse($e->getMessage());
        }
    }

    public function updatePrivacySettings(array $params)
    {
        $domain = $params['domain'] ?? '';
        if (empty($domain)) {
            return $this->errorResponse(__('admin/modules.centralnic_domain_required'));
        }

        try {
            $this->validateConfig();

            $privacyEnabled = filter_var($params['privacy_enabled'] ?? true, FILTER_VALIDATE_BOOLEAN);

            $result = $this->callApi('ModifyDomain', [
                'domain' => $domain,
                'X-ACCEPT-WHOISTRUSTEE-TAC' => $privacyEnabled ? '1' : '0',
            ]);

            if (!$this->isSuccess($result)) {
                return $this->errorResponse($this->getErrorMessage($result));
            }

            Log::info('CentralNic: Privacy settings updated', ['domain' => $domain, 'privacy_enabled' => $privacyEnabled]);

            return $this->successResponse(__('admin/modules.centralnic_privacy_updated'), [
                'domain' => $domain,
                'privacy_enabled' => $privacyEnabled,
            ]);
        } catch (\Exception $e) {
            return $this->errorResponse($e->getMessage());
        }
    }

    // -------------------------------------------------------------------------
    //  Child Nameservers (glue records)
    // -------------------------------------------------------------------------

    public function getChildNameservers(array $params)
    {
        $domain = $params['domain'] ?? '';
        if (empty($domain)) {
            return $this->errorResponse(__('admin/modules.centralnic_domain_required'));
        }

        try {
            $this->validateConfig();

            $result = $this->callApi('StatusDomain', ['domain' => $domain]);

            if (!$this->isSuccess($result)) {
                return $this->errorResponse($this->getErrorMessage($result));
            }

            $hosts = $result['property']['nameserver'] ?? [];
            $ips = $result['property']['nameserver ip'] ?? [];

            $nameservers = [];
            foreach ($hosts as $index => $hostname) {
                if (empty($hostname)) {
                    continue;
                }
                // Only child nameservers (hosts under the domain itself).
                if (str_ends_with(strtolower($hostname), '.'.strtolower($domain))) {
                    $nameservers[] = [
                        'id' => (string) ($index + 1),
                        'hostname' => $hostname,
                        'ip' => $ips[$index] ?? '',
                    ];
                }
            }

            return $this->successResponse(__('admin/modules.centralnic_child_ns_retrieved'), [
                'domain' => $domain,
                'nameservers' => $nameservers,
            ]);
        } catch (\Exception $e) {
            return $this->errorResponse($e->getMessage());
        }
    }

    public function addChildNameserver(array $params)
    {
        $domain = $params['domain'] ?? '';
        if (empty($domain)) {
            return $this->errorResponse(__('admin/modules.centralnic_domain_required'));
        }

        try {
            $this->validateConfig();

            if (empty($params['hostname']) || empty($params['ip'])) {
                return $this->errorResponse(__('admin/modules.centralnic_child_ns_params_required'));
            }

            $result = $this->callApi('AddNameserver', [
                'nameserver' => $params['hostname'],
                'ipaddress0' => $params['ip'],
            ]);

            if (!$this->isSuccess($result)) {
                return $this->errorResponse($this->getErrorMessage($result));
            }

            Log::info('CentralNic: Child nameserver added', ['domain' => $domain, 'hostname' => $params['hostname']]);

            return $this->successResponse(__('admin/modules.centralnic_child_ns_added'), [
                'hostname' => $params['hostname'],
                'ip' => $params['ip'],
            ]);
        } catch (\Exception $e) {
            return $this->errorResponse($e->getMessage());
        }
    }

    public function updateChildNameserver(array $params)
    {
        $domain = $params['domain'] ?? '';
        if (empty($domain)) {
            return $this->errorResponse(__('admin/modules.centralnic_domain_required'));
        }

        try {
            $this->validateConfig();

            // The store child-NS update path may send `nameserver_id` instead of
            // `hostname`; ISPAPI ModifyNameserver needs the NAMESERVER hostname.
            $hostname = $params['hostname'] ?? '';
            if (empty($hostname) && !empty($params['nameserver_id'])) {
                $hostname = $this->resolveChildNameserverHostname($domain, (string) $params['nameserver_id']);
            }

            if (empty($hostname) || empty($params['ip'])) {
                return $this->errorResponse(__('admin/modules.centralnic_child_ns_params_required'));
            }

            // ISPAPI ModifyNameserver: when an old IP is supplied swap it
            // (delipaddress0/addipaddress0), otherwise set the new IP directly.
            $apiParams = ['nameserver' => $hostname];
            if (!empty($params['old_ip']) && $params['old_ip'] !== $params['ip']) {
                $apiParams['delipaddress0'] = $params['old_ip'];
                $apiParams['addipaddress0'] = $params['ip'];
            } else {
                $apiParams['ipaddress0'] = $params['ip'];
            }

            $result = $this->callApi('ModifyNameserver', $apiParams);

            if (!$this->isSuccess($result)) {
                return $this->errorResponse($this->getErrorMessage($result));
            }

            Log::info('CentralNic: Child nameserver updated', ['domain' => $domain, 'hostname' => $hostname]);

            return $this->successResponse(__('admin/modules.centralnic_child_ns_updated'), [
                'hostname' => $hostname,
                'ip' => $params['ip'],
            ]);
        } catch (\Exception $e) {
            return $this->errorResponse($e->getMessage());
        }
    }

    public function deleteChildNameserver(array $params)
    {
        $domain = $params['domain'] ?? '';
        if (empty($domain)) {
            return $this->errorResponse(__('admin/modules.centralnic_domain_required'));
        }

        try {
            $this->validateConfig();

            // The store child-NS delete path sends `nameserver_id` (the id emitted
            // by getChildNameservers), not `hostname`. ISPAPI DeleteNameserver
            // requires the NAMESERVER hostname, so resolve id -> hostname first.
            $hostname = $params['hostname'] ?? '';
            if (empty($hostname) && !empty($params['nameserver_id'])) {
                $hostname = $this->resolveChildNameserverHostname($domain, (string) $params['nameserver_id']);
            }

            if (empty($hostname)) {
                return $this->errorResponse(__('admin/modules.centralnic_child_ns_params_required'));
            }

            $result = $this->callApi('DeleteNameserver', [
                'nameserver' => $hostname,
            ]);

            if (!$this->isSuccess($result)) {
                return $this->errorResponse($this->getErrorMessage($result));
            }

            Log::info('CentralNic: Child nameserver deleted', ['domain' => $domain, 'hostname' => $hostname]);

            return $this->successResponse(__('admin/modules.centralnic_child_ns_deleted'), [
                'hostname' => $hostname,
            ]);
        } catch (\Exception $e) {
            return $this->errorResponse($e->getMessage());
        }
    }

    // -------------------------------------------------------------------------
    //  Sync (lifecycle / transfer polling)
    // -------------------------------------------------------------------------

    public function syncDomain(array $params)
    {
        $domain = $params['domain'] ?? '';
        if (empty($domain)) {
            return $this->errorResponse(__('admin/modules.centralnic_domain_required'));
        }

        try {
            $this->validateConfig();

            $result = $this->callApi('StatusDomain', ['domain' => $domain]);

            if (!$this->isSuccess($result)) {
                return $this->errorResponse($this->getErrorMessage($result));
            }

            $statusValues = $result['property']['status'] ?? [];
            $locked = in_array('clientTransferProhibited', $statusValues);
            $expiryDate = $result['property']['registration expiration date'][0] ?? null;

            $domainStatus = 'active';
            if (in_array('pendingDelete', $statusValues)) {
                $domainStatus = 'expired';
            } elseif (in_array('serverHold', $statusValues) || in_array('clientHold', $statusValues)) {
                $domainStatus = 'suspended';
            }

            return $this->successResponse(__('admin/modules.centralnic_sync_success'), [
                'domain' => $domain,
                'status' => $domainStatus,
                'expires_at' => $expiryDate,
                'locked' => $locked,
            ]);
        } catch (\Exception $e) {
            return $this->errorResponse($e->getMessage());
        }
    }

    public function syncDomainTransfer(array $params)
    {
        $domain = $params['domain'] ?? '';
        if (empty($domain)) {
            return $this->errorResponse(__('admin/modules.centralnic_domain_required'));
        }

        try {
            $this->validateConfig();

            $result = $this->callApi('StatusDomain', ['domain' => $domain]);

            if ($this->isSuccess($result)) {
                // Prefer an explicit transfer status property when present.
                $rawStatus = strtolower((string) ($result['property']['transferstatus'][0] ?? ''));
                $transferStatus = match ($rawStatus) {
                    'completed', 'success', 'active' => 'completed',
                    'failed', 'cancelled', 'nack' => 'failed',
                    'pending', 'requested' => 'pending',
                    // StatusDomain success without an explicit flag => transfer done.
                    default => 'completed',
                };

                return $this->successResponse(
                    $transferStatus === 'completed'
                        ? __('admin/modules.centralnic_transfer_sync_complete')
                        : __('admin/modules.centralnic_transfer_sync_pending'),
                    [
                        'domain' => $domain,
                        'transfer_status' => $transferStatus,
                        'expires_at' => $result['property']['registration expiration date'][0] ?? null,
                    ]
                );
            }

            // StatusDomain not yet resolvable => transfer still pending.
            return $this->successResponse(__('admin/modules.centralnic_transfer_sync_pending'), [
                'domain' => $domain,
                'transfer_status' => 'pending',
            ]);
        } catch (\Exception $e) {
            return $this->errorResponse($e->getMessage());
        }
    }

    // -------------------------------------------------------------------------
    //  Domain Suggestions (not supported by ISPAPI toolkit)
    // -------------------------------------------------------------------------

    public function checkDomainSuggestions(array $params)
    {
        // The ISPAPI/RRPProxy toolkit exposes no reliable name-suggestion command;
        // return an explicit unsupported error rather than a fabricated result.
        return $this->errorResponse(__('admin/modules.centralnic_suggestions_unsupported'));
    }

    // -------------------------------------------------------------------------
    //  API Communication
    // -------------------------------------------------------------------------

    /**
     * Send a command to the CentralNic Reseller API
     *
     * @param  string  $command  The API command (e.g. AddDomain, StatusDomain)
     * @param  array  $params  Additional parameters for the command
     * @return array Parsed response
     */
    protected function callApi($endpoint, $method = 'GET', $data = [])
    {
        // Backward compatibility: if $method is an array, treat it as $data
        if (is_array($method)) {
            $data = $method;
        }

        $url = $this->getApiEndpoint();

        $requestParams = array_merge([
            's_login' => $this->config['username'] ?? '',
            's_pw' => $this->config['password'] ?? '',
            'command' => $endpoint,
        ], $data);

        Log::debug('CentralNic API request', [
            'command' => $endpoint,
            'domain' => $requestParams['domain'] ?? 'N/A',
        ]);

        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($requestParams));
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
        curl_setopt($ch, CURLOPT_TIMEOUT, 60);
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
            'Content-Type: application/x-www-form-urlencoded',
        ]);

        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $curlError = curl_error($ch);

        curl_close($ch);

        if ($curlError) {
            Log::error('CentralNic API curl error', [
                'command' => $endpoint,
                'error' => $curlError,
            ]);

            return [
                'code' => 421,
                'description' => __('admin/modules.centralnic_curl_error', ['error' => $curlError]),
                'property' => [],
            ];
        }

        if ($httpCode >= 400 || empty($response)) {
            Log::error('CentralNic API HTTP error', [
                'command' => $endpoint,
                'http_code' => $httpCode,
            ]);

            return [
                'code' => $httpCode,
                'description' => __('admin/modules.centralnic_api_http_error', ['code' => $httpCode]),
                'property' => [],
            ];
        }

        return $this->parseResponse($response);
    }

    /**
     * Parse CentralNic API response
     *
     * Response format:
     *   [RESPONSE]
     *   code = 200
     *   description = Command completed successfully
     *   property[nameserver][0] = ns1.example.com
     *   property[nameserver][1] = ns2.example.com
     *   property[status][0] = ACTIVE
     *   EOF
     *
     * @param  string  $response  Raw response string
     * @return array Parsed response with 'code', 'description', and 'property' keys
     */
    protected function parseResponse(string $response): array
    {
        $result = [
            'code' => 421,
            'description' => '',
            'property' => [],
        ];

        $lines = explode("\n", trim($response));

        foreach ($lines as $line) {
            $line = trim($line);

            // Skip markers
            if ($line === '[RESPONSE]' || $line === 'EOF' || $line === '') {
                continue;
            }

            // Split on first '='
            $equalPos = strpos($line, '=');
            if ($equalPos === false) {
                continue;
            }

            $key = strtolower(trim(substr($line, 0, $equalPos)));
            $value = trim(substr($line, $equalPos + 1));

            if ($key === 'code') {
                $result['code'] = (int) $value;
            } elseif ($key === 'description') {
                $result['description'] = $value;
            } elseif (preg_match('/^property\[([^\]]+)\]\[(\d+)\]$/', $key, $matches)) {
                $propName = strtolower($matches[1]);
                $propIndex = (int) $matches[2];
                $result['property'][$propName][$propIndex] = $value;
            } elseif (preg_match('/^property\[([^\]]+)\]$/', $key, $matches)) {
                $propName = strtolower($matches[1]);
                if (!isset($result['property'][$propName])) {
                    $result['property'][$propName] = [];
                }
                $result['property'][$propName][] = $value;
            }
        }

        // Log errors
        if ($result['code'] >= 400) {
            Log::warning('CentralNic API error response', [
                'code' => $result['code'],
                'description' => $result['description'],
            ]);
        }

        return $result;
    }

    // -------------------------------------------------------------------------
    //  Helper Methods
    // -------------------------------------------------------------------------

    /**
     * Get the active API endpoint based on test mode
     */
    protected function getApiEndpoint(): string
    {
        return $this->isTestMode() ? $this->testApiUrl : $this->apiUrl;
    }

    /**
     * Whether test mode is enabled
     */
    protected function isTestMode(): bool
    {
        $testMode = $this->config['test_mode'] ?? false;

        return filter_var($testMode, FILTER_VALIDATE_BOOLEAN);
    }

    /**
     * Check if an API response indicates success
     * CentralNic success codes: 200 (OK), 218 (request is not yet completed), 220 (domain available)
     */
    protected function isSuccess(array $result): bool
    {
        $code = $result['code'] ?? 0;

        return $code >= 200 && $code < 300;
    }

    /**
     * Get error message from API response
     */
    protected function getErrorMessage(array $result): string
    {
        $code = $result['code'] ?? 0;
        $description = $result['description'] ?? '';

        if (!empty($description)) {
            return '['.$code.'] '.$description;
        }

        return __('admin/modules.centralnic_unknown_error');
    }

    /**
     * Standard success response
     */
    protected function successResponse(string $message, array $data = []): array
    {
        return [
            'status' => 'success',
            'message' => $message,
            'data' => $data,
        ];
    }

    /**
     * Standard error response
     */
    protected function errorResponse(string $message, array $data = []): array
    {
        return [
            'status' => 'error',
            'message' => $message,
            'data' => $data,
        ];
    }

    /**
     * Extract nameservers from params
     * Supports 'nameservers' array, 'ns1'..'ns5', and 'nameserver0'..'nameserver3' formats
     */
    protected function extractNameservers(array $params): array
    {
        $nameservers = $params['nameservers'] ?? [];

        // Check ns1..ns5 format
        if (empty($nameservers)) {
            for ($i = 1; $i <= 5; $i++) {
                if (!empty($params['ns'.$i])) {
                    $nameservers[] = $params['ns'.$i];
                }
            }
        }

        // Check nameserver0..nameserver3 format
        if (empty($nameservers)) {
            for ($i = 0; $i <= 3; $i++) {
                if (!empty($params['nameserver'.$i])) {
                    $nameservers[] = $params['nameserver'.$i];
                }
            }
        }

        return array_values(array_filter($nameservers));
    }

    /**
     * Build the ISPAPI AddContact command parameters for a given contact group.
     *
     * PRC-969: sources the canonical contact from the provisioning-provided group
     * via contact() (with field-level client_* fallback). Field names verified
     * against WHMCS/RRPProxy ISPAPI AddContact (firstname/lastname/street/city/
     * zip/country/phone/email/organization/state).
     */
    protected function buildAddContactParams(array $params, string $group = 'registrant'): array
    {
        $contact = $this->contact($params, $group);

        return [
            'firstname' => $contact['first_name'] ?? '',
            'lastname' => $contact['last_name'] ?? '',
            'street' => $contact['address1'] ?? '',
            'city' => $contact['city'] ?? '',
            'zip' => $contact['postcode'] ?? '',
            'country' => $contact['country_code'] ?? '',
            'phone' => $contact['phone'] ?? '',
            'email' => $contact['email'] ?? '',
            'organization' => $contact['company'] ?? '',
            'state' => $contact['state'] ?? '',
        ];
    }

    /**
     * Fetch contact data by handle via StatusContact.
     * ISPAPI StatusContact returns spaced property names (`first name`, `last name`).
     */
    protected function fetchContactData(string $contactHandle): ?array
    {
        $result = $this->callApi('StatusContact', ['contact' => $contactHandle]);

        if (!$this->isSuccess($result)) {
            return null;
        }

        return [
            'firstname' => $result['property']['first name'][0] ?? '',
            'lastname' => $result['property']['last name'][0] ?? '',
            'organization' => $result['property']['organization'][0] ?? '',
            'street' => $result['property']['street'][0] ?? '',
            'city' => $result['property']['city'][0] ?? '',
            'state' => $result['property']['state'][0] ?? '',
            'zip' => $result['property']['zip'][0] ?? '',
            'country' => $result['property']['country'][0] ?? '',
            'phone' => $result['property']['phone'][0] ?? '',
            'fax' => $result['property']['fax'][0] ?? '',
            'email' => $result['property']['email'][0] ?? '',
        ];
    }

    /**
     * Resolve a child-nameserver id (as emitted by getChildNameservers,
     * id = index+1) back to its hostname. Returns '' when it cannot be
     * resolved so callers stay fail-closed.
     */
    protected function resolveChildNameserverHostname(string $domain, string $nameserverId): string
    {
        $listResult = $this->getChildNameservers(['domain' => $domain]);

        if (($listResult['status'] ?? '') !== 'success') {
            return '';
        }

        foreach ($listResult['data']['nameservers'] ?? [] as $entry) {
            if ((string) ($entry['id'] ?? '') === $nameserverId) {
                return (string) ($entry['hostname'] ?? '');
            }
        }

        return '';
    }

    /**
     * Map CentralNic availability status code to a human-readable status
     *
     * @param  int  $statusCode  Status code from CheckDomains response
     * @return string Status description
     */
    protected function mapAvailabilityStatus(int $statusCode): string
    {
        return match ($statusCode) {
            210 => 'available',
            211 => 'registered',
            220 => 'available_with_claims',
            521 => 'invalid',
            549 => 'unavailable',
            default => 'unknown',
        };
    }

    /**
     * Apply TLD-specific X-* additional fields to a domain registration request.
     * additional_fields is emitted by the builder from client_domain_fields.
     * TLD is derived from the domain string (PRC-49), never from tld_id.
     */
    protected function applyTldSpecificFields(array $params, array $postfields): array
    {
        $domain = $postfields['domain'] ?? '';
        $additionalFields = $params['additional_fields'] ?? $params['additionalfields'] ?? [];

        if (preg_match('/\.ca$/i', $domain)) {
            $postfields = $this->applyCaFields($additionalFields, $postfields);
        }
        if (preg_match('/\.tel$/i', $domain)) {
            $postfields = $this->applyTelFields($additionalFields, $postfields);
        }
        if (preg_match('/\.it$/i', $domain)) {
            $postfields = $this->applyItFields($additionalFields, $postfields);
        }
        if (preg_match('/\.us$/i', $domain)) {
            $postfields = $this->applyUsFields($additionalFields, $postfields);
        }
        if (preg_match('/\.es$/i', $domain)) {
            $postfields = $this->applyEsFields($additionalFields, $postfields);
        }
        if (preg_match('/\.de$/i', $domain)) {
            $postfields['X-DE-ACCEPT-TRUSTEE-TAC'] = '0';
        }
        if (preg_match('/\.eu$/i', $domain)) {
            $postfields['X-EU-ACCEPT-TRUSTEE-TAC'] = '0';
        }

        return $postfields;
    }

    protected function applyCaFields(array $additionalFields, array $postfields): array
    {
        $legalTypeMap = [
            'Corporation' => 'CCO',
            'Canadian Citizen' => 'CCT',
            'Permanent Resident of Canada' => 'RES',
            'Government' => 'GOV',
            'Canadian Educational Institution' => 'EDU',
            'Canadian Unincorporated Association' => 'ASS',
            'Canadian Hospital' => 'HOP',
            'Partnership Registered in Canada' => 'PRT',
            'Trade-mark registered in Canada' => 'TDM',
            'Canadian Trade Union' => 'TRD',
            'Canadian Political Party' => 'PLT',
            'Canadian Library Archive or Museum' => 'LAM',
            'Trust established in Canada' => 'TRS',
            'Aboriginal Peoples' => 'ABO',
            'Legal Representative of a Canadian Citizen' => 'LGR',
            'Official mark registered in Canada' => 'OMK',
        ];

        $legalType = $additionalFields['Legal Type'] ?? '';
        $postfields['X-CA-LEGAL-TYPE'] = $legalTypeMap[$legalType] ?? $legalType;
        $postfields['X-CA-TRADEMARK'] = '0';

        return $postfields;
    }

    protected function applyTelFields(array $additionalFields, array $postfields): array
    {
        $legalType = $additionalFields['Legal Type'] ?? '';
        $postfields['X-TEL-WHOISTYPE'] = ($legalType === 'Legal Person') ? 'Legal' : 'Natural';
        $postfields['X-TEL-PUBLISH-WHOIS'] = !empty($additionalFields['WHOIS Opt-out']) ? '1' : '0';

        return $postfields;
    }

    protected function applyItFields(array $additionalFields, array $postfields): array
    {
        $postfields['X-IT-CONSENTFORPUBLISHING'] = !empty($additionalFields['Publish Personal Data']) ? '1' : '0';
        $postfields['X-IT-SECT3-LIABILITY'] = !empty($additionalFields['Accept Section 3 of .IT registrar contract']) ? '1' : '0';
        $postfields['X-IT-SECT5-PERSONAL-DATA-FOR-REGISTRATION'] = !empty($additionalFields['Accept Section 5 of .IT registrar contract']) ? '1' : '0';
        $postfields['X-IT-SECT6-PERSONAL-DATA-FOR-DIFFUSION'] = !empty($additionalFields['Accept Section 6 of .IT registrar contract']) ? '1' : '0';
        $postfields['X-IT-SECT7-EXPLICIT-ACCEPTANCE'] = !empty($additionalFields['Accept Section 7 of .IT registrar contract']) ? '1' : '0';

        if (!empty($additionalFields['Tax ID'])) {
            $postfields['X-IT-PIN'] = $additionalFields['Tax ID'];
        }

        $entityTypeMap = [
            'Italian and foreign natural persons' => '1',
            'Companies/one man companies' => '2',
            'Freelance workers/professionals' => '3',
            'non-profit organizations' => '4',
            'public organizations' => '5',
            'other subjects' => '6',
            'non natural foreigners' => '7',
        ];

        $legalType = $additionalFields['Legal Type'] ?? '';
        $postfields['X-IT-ENTITY-TYPE'] = $entityTypeMap[$legalType] ?? $legalType;

        return $postfields;
    }

    protected function applyUsFields(array $additionalFields, array $postfields): array
    {
        $nexusPurposeMap = [
            'Business use for profit' => 'P1',
            'Non-profit business' => 'P2',
            'Club,Association' => 'P2',
            'Religious Organization' => 'P2',
            'Personal Use' => 'P3',
            'Educational purposes' => 'P4',
            'Government purposes' => 'P5',
        ];

        $nexusPurpose = $additionalFields['Application Purpose'] ?? '';
        $postfields['X-US-NEXUS-APPPURPOSE'] = $nexusPurposeMap[$nexusPurpose] ?? $nexusPurpose;

        if (!empty($additionalFields['Nexus Category'])) {
            $postfields['X-US-NEXUS-CATEGORY'] = $additionalFields['Nexus Category'];
        }

        return $postfields;
    }

    protected function applyEsFields(array $additionalFields, array $postfields): array
    {
        $postfields['X-ES-ACCEPT-SPECIAL-TAC'] = '0';

        $idFormTypeMap = [
            'Other Identification' => '0',
            'Tax Identification Number' => '1',
            'Tax Identification Code' => '2',
            'Foreigner Identification Number' => '3',
        ];

        $idFormType = $additionalFields['ID Form Type'] ?? '';
        $postfields['X-ES-REGISTRANT-TIPO-IDENTIFICACION'] = $idFormTypeMap[$idFormType] ?? $idFormType;

        if (!empty($additionalFields['ID Form Number'])) {
            $postfields['X-ES-REGISTRANT-IDENTIFICACION'] = $additionalFields['ID Form Number'];
        }

        return $postfields;
    }
}
