<?php

namespace App\Modules\Registrar\Bizcn;

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

class Bizcn extends AbstractRegistrar
{
    /**
     * BizCN API production URL
     */
    protected const API_URL = 'https://api.71.com/webrrpdomain';

    /**
     * BizCN API test/sandbox URL
     */
    protected const API_TEST_URL = 'https://test.api.71.com/webrrpdomain';

    /**
     * Get the configuration fields for this registrar module
     *
     * @return array
     */
    public function getConfigFields(): array
    {
        return [
            'username' => [
                'type' => 'text',
                'label' => __('admin/modules.bizcn_field_username_label'),
                'required' => true,
                'description' => __('admin/modules.bizcn_field_username_description'),
                'placeholder' => 'username',
                'value' => $this->config['username'] ?? '',
            ],
            'password' => [
                'type' => 'password',
                'label' => __('admin/modules.bizcn_field_password_label'),
                'required' => true,
                'description' => __('admin/modules.bizcn_field_password_description'),
                'placeholder' => '********',
                'value' => $this->config['password'] ?? '',
            ],
            'test_mode' => [
                'type' => 'checkbox',
                'label' => __('admin/modules.bizcn_field_test_mode_label'),
                'required' => false,
                'description' => __('admin/modules.bizcn_field_test_mode_description'),
                'default' => false,
                'value' => $this->config['test_mode'] ?? false,
            ],
        ];
    }

    // =========================================================================
    // API Communication
    // =========================================================================

    /**
     * Get the API URL based on test mode setting
     *
     * @return string
     */
    protected function getApiUrl(): string
    {
        $testMode = $this->config['test_mode'] ?? false;

        return $testMode ? self::API_TEST_URL : self::API_URL;
    }

    /**
     * Make an API call to the BizCN API
     *
     * @param  array  $params  API parameters
     * @return string|null Raw response from the API
     */
    protected function apiCall(array $params): ?string
    {
        $url = $this->getApiUrl();

        // Authoritative cnobin api.cnobin.php:313 uses a plain http_build_query
        // body. The previous EQU/AND str_replace hack corrupted any value that
        // contained the literal substrings "EQU"/"AND" (e.g. contact name
        // "SANDRA" → "S&RA", authcode "aAND9x" → "a&9x") and broke the request
        // shape. Multi-value fields (nameservers) are sent as discrete
        // dns_host1..N params, so no delimiter encoding is needed.
        $queryString = http_build_query($params, '', '&');

        try {
            // Use raw cURL to preserve BizCN's custom parameter encoding
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL, $url);
            curl_setopt($ch, CURLOPT_POST, 1);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $queryString);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
            curl_setopt($ch, CURLOPT_HEADER, 0);
            curl_setopt($ch, CURLOPT_NOBODY, 0);
            curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
            curl_setopt($ch, CURLOPT_TIMEOUT, 30);
            $result = curl_exec($ch);
            $curlError = curl_error($ch);
            curl_close($ch);

            if ($result === false) {
                Log::error('Bizcn: cURL error', [
                    'error' => $curlError,
                    'module' => $params['module'] ?? 'unknown',
                ]);

                return null;
            }

            Log::info('Bizcn: API call', [
                'module' => $params['module'] ?? 'unknown',
                'url' => $url,
            ]);

            return $result;
        } catch (\Exception $e) {
            Log::error('Bizcn: API call failed', [
                'error' => $e->getMessage(),
                'module' => $params['module'] ?? 'unknown',
            ]);

            return null;
        }
    }

    /**
     * Check if the API response indicates success (status code 200)
     *
     * @param  string|null  $result  Raw API response
     * @return bool
     */
    protected function isSuccessResponse(?string $result): bool
    {
        if (empty($result)) {
            return false;
        }

        return substr($result, 0, 3) == '200';
    }

    /**
     * Build base API parameters with authentication
     *
     * @param  string  $module  The API module/action to call
     * @param  string  $domain  The domain name
     * @return array
     */
    protected function buildBaseParams(string $module, string $domain = ''): array
    {
        $params = [
            'username' => $this->config['username'] ?? '',
            'password' => md5($this->config['password'] ?? ''),
            'module' => $module,
        ];

        if (! empty($domain)) {
            $params['domainname'] = $domain;
        }

        return $params;
    }

    /**
     * Extract domain name from params
     *
     * @param  array  $params  Input parameters
     * @return string Full domain name (sld.tld)
     */
    protected function getDomainFromParams(array $params): string
    {
        if (! empty($params['domain'])) {
            return $params['domain'];
        }

        $sld = $params['sld'] ?? '';
        $tld = $params['tld'] ?? '';

        return $sld . '.' . $tld;
    }

    // =========================================================================
    // Required Abstract Methods
    // =========================================================================

    /**
     * Register a new domain
     *
     * @param  array  $params  Registration parameters
     * @return array
     */
    public function registerDomain(array $params)
    {
        $requiredParams = ['domain', 'period'];
        foreach ($requiredParams as $param) {
            if (! isset($params[$param]) || empty($params[$param])) {
                return [
                    'status' => 'error',
                    'message' => __('admin/modules.bizcn_missing_param', ['param' => $param]),
                ];
            }
        }

        $domain = $this->getDomainFromParams($params);
        $period = $params['period'];

        // PRC-969: canonical contact groups from builder (registrant + admin).
        // WHMCS bizcn.php:352 maps tech + bill = admin.
        $reg = $this->contact($params, 'registrant');
        $admin = $this->contact($params, 'admin');

        $regOrg = $reg['company'] !== '' ? $reg['company'] : trim($reg['first_name'] . ' ' . $reg['last_name']);

        // Nameservers — cnobin api.cnobin.php:76-80 sends discrete dns_host1..6.
        $nameservers = $params['nameservers'] ?? [];
        if (empty($nameservers)) {
            $nameservers = array_values(array_filter([
                $params['ns1'] ?? '',
                $params['ns2'] ?? '',
                $params['ns3'] ?? '',
                $params['ns4'] ?? '',
            ]));
        }
        $nsHosts = [];
        $i = 1;
        foreach ($nameservers as $ns) {
            $ns = trim((string) $ns);
            if ($ns !== '' && $i <= 6) {
                $nsHosts['dns_host' . $i] = $ns;
                $i++;
            }
        }

        $apiParams = $this->buildBaseParams('adddomain', $domain);
        $apiParams = array_merge($apiParams, $nsHosts, [
            'term' => $period,
            // Registrant (domain owner)
            'dom_org' => $regOrg,
            'dom_fn' => $reg['first_name'],
            'dom_ln' => $reg['last_name'],
            'dom_adr1' => $reg['address1'],
            'dom_adr2' => $reg['address2'],
            'dom_ct' => $reg['city'],
            'dom_st' => $reg['state'],
            'dom_co' => $reg['country_code'],
            'dom_ph' => $reg['phone'],
            'dom_pc' => $reg['postcode'],
            'dom_em' => $reg['email'],
            // Admin contact
            'admi_fn' => $admin['first_name'],
            'admi_ln' => $admin['last_name'],
            'admi_adr1' => $admin['address1'],
            'admi_adr2' => $admin['address2'],
            'admi_ct' => $admin['city'],
            'admi_st' => $admin['state'],
            'admi_co' => $admin['country_code'],
            'admi_ph' => $admin['phone'],
            'admi_pc' => $admin['postcode'],
            'admi_em' => $admin['email'],
            // Tech contact (same as admin — WHMCS bizcn.php:352)
            'tech_fn' => $admin['first_name'],
            'tech_ln' => $admin['last_name'],
            'tech_adr1' => $admin['address1'],
            'tech_adr2' => $admin['address2'],
            'tech_ct' => $admin['city'],
            'tech_st' => $admin['state'],
            'tech_co' => $admin['country_code'],
            'tech_ph' => $admin['phone'],
            'tech_pc' => $admin['postcode'],
            'tech_em' => $admin['email'],
            // Billing contact (same as admin — WHMCS bizcn.php:352)
            'bill_fn' => $admin['first_name'],
            'bill_ln' => $admin['last_name'],
            'bill_adr1' => $admin['address1'],
            'bill_adr2' => $admin['address2'],
            'bill_ct' => $admin['city'],
            'bill_st' => $admin['state'],
            'bill_co' => $admin['country_code'],
            'bill_ph' => $admin['phone'],
            'bill_pc' => $admin['postcode'],
            'bill_em' => $admin['email'],
        ]);

        // Optional glue record IPs
        if (! empty($params['dns_ip1'])) {
            $apiParams['dns_ip1'] = $params['dns_ip1'];
        }
        if (! empty($params['dns_ip2'])) {
            $apiParams['dns_ip2'] = $params['dns_ip2'];
        }

        // TLD-specific extras (.cn etc.) forwarded from client_domain_fields.
        if (! empty($params['additional_fields']) && is_array($params['additional_fields'])) {
            foreach ($params['additional_fields'] as $afKey => $afVal) {
                if (! isset($apiParams[$afKey]) && $afVal !== null && $afVal !== '') {
                    $apiParams[$afKey] = $afVal;
                }
            }
        }

        $result = $this->apiCall($apiParams);

        if (empty($result)) {
            return [
                'status' => 'error',
                'message' => __('admin/modules.bizcn_api_empty_response'),
            ];
        }

        if ($this->isSuccessResponse($result)) {
            Log::info('Bizcn: Domain registered', [
                'action' => 'registered',
                'domain' => $domain,
                'period' => $period,
            ]);

            return [
                'status' => 'success',
                'message' => __('admin/modules.bizcn_register_success'),
                'data' => [
                    'domain' => $domain,
                    'period' => $period,
                    'registrar' => 'bizcn',
                    'registered_at' => now()->toISOString(),
                    'nameservers' => array_values($nsHosts),
                ],
            ];
        }

        Log::error('Bizcn: Domain registration failed', [
            'domain' => $domain,
            'response' => $result,
        ]);

        return [
            'status' => 'error',
            'message' => __('admin/modules.bizcn_register_failed', ['error' => $result]),
        ];
    }

    /**
     * Transfer a domain to BizCN
     *
     * @param  array  $params  Transfer parameters
     * @return array
     */
    public function transferDomain(array $params)
    {
        $requiredParams = ['domain', 'epp_code'];
        foreach ($requiredParams as $param) {
            if (! isset($params[$param]) || empty($params[$param])) {
                return [
                    'status' => 'error',
                    'message' => __('admin/modules.bizcn_missing_param', ['param' => $param]),
                ];
            }
        }

        $domain = $this->getDomainFromParams($params);
        $period = $params['period'] ?? 1;

        // 71.com/cnobin webrrpdomain transfer: module=transferdomain,
        // domainname + domainpwd(authcode) + ip (api.cnobin.php:99-110).
        $apiParams = $this->buildBaseParams('transferdomain', $domain);
        unset($apiParams['domainname']);
        $apiParams = array_merge($apiParams, [
            'domainname' => $domain,
            'domainpwd' => $params['epp_code'],
            'ip' => $params['ip'] ?? ($params['client_ip'] ?? ($_SERVER['REMOTE_ADDR'] ?? '')),
        ]);

        $result = $this->apiCall($apiParams);

        if (empty($result)) {
            return [
                'status' => 'error',
                'message' => __('admin/modules.bizcn_api_empty_response'),
            ];
        }

        if ($this->isSuccessResponse($result)) {
            Log::info('Bizcn: Domain transfer initiated', [
                'action' => 'transfer',
                'domain' => $domain,
            ]);

            return [
                'status' => 'success',
                'message' => __('admin/modules.bizcn_transfer_success'),
                'data' => [
                    'domain' => $domain,
                    'period' => $period,
                    'registrar' => 'bizcn',
                    'transfer_started_at' => now()->toISOString(),
                ],
            ];
        }

        Log::error('Bizcn: Domain transfer failed', [
            'domain' => $domain,
            'response' => $result,
        ]);

        return [
            'status' => 'error',
            'message' => __('admin/modules.bizcn_transfer_failed', ['error' => $result]),
        ];
    }

    /**
     * Renew a domain
     *
     * @param  array  $params  Renewal parameters
     * @return array
     */
    public function renewDomain(array $params)
    {
        $requiredParams = ['domain', 'period'];
        foreach ($requiredParams as $param) {
            if (! isset($params[$param]) || empty($params[$param])) {
                return [
                    'status' => 'error',
                    'message' => __('admin/modules.bizcn_missing_param', ['param' => $param]),
                ];
            }
        }

        $domain = $this->getDomainFromParams($params);
        $period = $params['period'];

        $apiParams = [
            'username' => $this->config['username'] ?? '',
            'password' => md5($this->config['password'] ?? ''),
            'module' => 'renewdomain',
            'domain' => $domain,
            'term' => $period,
        ];

        $result = $this->apiCall($apiParams);

        if ($this->isSuccessResponse($result)) {
            Log::info('Bizcn: Domain renewed', [
                'action' => 'renewed',
                'domain' => $domain,
                'period' => $period,
            ]);

            return [
                'status' => 'success',
                'message' => __('admin/modules.bizcn_renew_success'),
                'data' => [
                    'domain' => $domain,
                    'period' => $period,
                    'registrar' => 'bizcn',
                    'renewed_at' => now()->toISOString(),
                ],
            ];
        }

        Log::error('Bizcn: Domain renewal failed', [
            'domain' => $domain,
            'response' => $result,
        ]);

        return [
            'status' => 'error',
            'message' => __('admin/modules.bizcn_renew_failed', ['error' => $result ?? 'Empty response']),
        ];
    }

    /**
     * Get nameservers for a domain
     *
     * @param  array  $params  Parameters
     * @return array
     */
    public function getNameservers(array $params)
    {
        if (! isset($params['domain']) || empty($params['domain'])) {
            return [
                'status' => 'error',
                'message' => __('admin/modules.bizcn_missing_param', ['param' => 'domain']),
            ];
        }

        $domain = $this->getDomainFromParams($params);
        $apiParams = $this->buildBaseParams('getdomaindns', $domain);

        $result = $this->apiCall($apiParams);

        if (empty($result)) {
            return [
                'status' => 'error',
                'message' => __('admin/modules.bizcn_api_empty_response'),
            ];
        }

        if ($this->isSuccessResponse($result)) {
            $lines = explode("\r\n", $result);
            // First line is the status code, subsequent lines are nameservers
            $nameservers = [];
            for ($i = 1; $i <= 5; $i++) {
                if (! empty($lines[$i] ?? '')) {
                    $nameservers[] = trim($lines[$i]);
                }
            }

            return [
                'status' => 'success',
                'message' => __('admin/modules.bizcn_get_nameservers_success'),
                'data' => [
                    'domain' => $domain,
                    'nameservers' => $nameservers,
                ],
            ];
        }

        return [
            'status' => 'error',
            'message' => __('admin/modules.bizcn_get_nameservers_failed', ['error' => $result]),
        ];
    }

    /**
     * Set nameservers for a domain
     *
     * @param  array  $params  Parameters
     * @return array
     */
    public function setNameservers(array $params)
    {
        if (! isset($params['domain']) || empty($params['domain'])) {
            return [
                'status' => 'error',
                'message' => __('admin/modules.bizcn_missing_param', ['param' => 'domain']),
            ];
        }

        if (! isset($params['nameservers']) || ! is_array($params['nameservers'])) {
            return [
                'status' => 'error',
                'message' => __('admin/modules.bizcn_missing_param', ['param' => 'nameservers']),
            ];
        }

        $domain = $this->getDomainFromParams($params);
        $nameservers = $params['nameservers'];

        // cnobin api.cnobin.php:138-156 sends each nameserver as a discrete
        // dns_host1..N param — not a single delimited dns_host string.
        $apiParams = $this->buildBaseParams('moddomaindns', $domain);
        $i = 1;
        foreach ($nameservers as $ns) {
            $ns = trim((string) $ns);
            if ($ns !== '') {
                $apiParams['dns_host' . $i] = $ns;
                $i++;
            }
        }

        $result = $this->apiCall($apiParams);

        if (empty($result)) {
            return [
                'status' => 'error',
                'message' => __('admin/modules.bizcn_api_empty_response'),
            ];
        }

        if ($this->isSuccessResponse($result)) {
            Log::info('Bizcn: Nameservers updated', [
                'domain' => $domain,
                'nameservers' => $nameservers,
            ]);

            return [
                'status' => 'success',
                'message' => __('admin/modules.bizcn_set_nameservers_success'),
                'data' => [
                    'domain' => $domain,
                    'nameservers' => $nameservers,
                    'updated_at' => now()->toISOString(),
                ],
            ];
        }

        return [
            'status' => 'error',
            'message' => __('admin/modules.bizcn_set_nameservers_failed', ['error' => $result]),
        ];
    }

    /**
     * Get contact details for a domain
     *
     * @param  array  $params  Parameters
     * @return array
     */
    public function getContactDetails(array $params)
    {
        if (! isset($params['domain']) || empty($params['domain'])) {
            return [
                'status' => 'error',
                'message' => __('admin/modules.bizcn_missing_param', ['param' => 'domain']),
            ];
        }

        $domain = $this->getDomainFromParams($params);
        $apiParams = $this->buildBaseParams('getcontactdetails', $domain);

        $result = $this->apiCall($apiParams);

        if (empty($result)) {
            return [
                'status' => 'error',
                'message' => __('admin/modules.bizcn_api_empty_response'),
            ];
        }

        if ($this->isSuccessResponse($result)) {
            $lines = explode("\r\n", $result);
            $parsed = [];
            if (count($lines) > 0) {
                for ($i = 1; $i < count($lines); $i++) {
                    $parts = explode(':', $lines[$i], 2);
                    if (count($parts) === 2) {
                        $parsed[trim($parts[0])] = trim($parts[1]);
                    }
                }
            }

            return [
                'status' => 'success',
                'message' => __('admin/modules.bizcn_get_contacts_success'),
                'groups' => [
                    'Registrant' => [
                        'firstname' => $parsed['dom_fn'] ?? '',
                        'lastname' => $parsed['dom_ln'] ?? '',
                        'company' => $parsed['dom_org'] ?? '',
                        'address1' => $parsed['dom_adr1'] ?? '',
                        'address2' => $parsed['dom_adr2'] ?? '',
                        'city' => $parsed['dom_ct'] ?? '',
                        'state' => $parsed['dom_st'] ?? '',
                        'country' => $parsed['dom_co'] ?? '',
                        'phone' => $parsed['dom_ph'] ?? '',
                        'email' => $parsed['dom_em'] ?? '',
                        'postal_code' => $parsed['dom_pc'] ?? '',
                    ],
                    'Admin' => [
                        'firstname' => $parsed['admi_fn'] ?? '',
                        'lastname' => $parsed['admi_ln'] ?? '',
                        'address1' => $parsed['admi_adr1'] ?? '',
                        'address2' => $parsed['admi_adr2'] ?? '',
                        'city' => $parsed['admi_ct'] ?? '',
                        'state' => $parsed['admi_st'] ?? '',
                        'country' => $parsed['admi_co'] ?? '',
                        'phone' => $parsed['admi_ph'] ?? '',
                        'email' => $parsed['admi_em'] ?? '',
                        'postal_code' => $parsed['admi_pc'] ?? '',
                    ],
                    'Tech' => [
                        'firstname' => $parsed['tech_fn'] ?? '',
                        'lastname' => $parsed['tech_ln'] ?? '',
                        'address1' => $parsed['tech_adr1'] ?? '',
                        'address2' => $parsed['tech_adr2'] ?? '',
                        'city' => $parsed['tech_ct'] ?? '',
                        'state' => $parsed['tech_st'] ?? '',
                        'country' => $parsed['tech_co'] ?? '',
                        'phone' => $parsed['tech_ph'] ?? '',
                        'email' => $parsed['tech_em'] ?? '',
                        'postal_code' => $parsed['tech_pc'] ?? '',
                    ],
                    'Billing' => [
                        'firstname' => $parsed['bill_fn'] ?? '',
                        'lastname' => $parsed['bill_ln'] ?? '',
                        'address1' => $parsed['bill_adr1'] ?? '',
                        'address2' => $parsed['bill_adr2'] ?? '',
                        'city' => $parsed['bill_ct'] ?? '',
                        'state' => $parsed['bill_st'] ?? '',
                        'country' => $parsed['bill_co'] ?? '',
                        'phone' => $parsed['bill_ph'] ?? '',
                        'email' => $parsed['bill_em'] ?? '',
                        'postal_code' => $parsed['bill_pc'] ?? '',
                    ],
                ],
            ];
        }

        return [
            'status' => 'error',
            'message' => __('admin/modules.bizcn_get_contacts_failed', ['error' => $result]),
        ];
    }

    /**
     * Set contact details for a domain
     *
     * @param  array  $params  Parameters
     * @return array
     */
    public function setContactDetails(array $params)
    {
        if (! isset($params['domain']) || empty($params['domain'])) {
            return [
                'status' => 'error',
                'message' => __('admin/modules.bizcn_missing_param', ['param' => 'domain']),
            ];
        }

        if (! isset($params['groups']) || ! is_array($params['groups'])) {
            return [
                'status' => 'error',
                'message' => __('admin/modules.bizcn_missing_param', ['param' => 'groups']),
            ];
        }

        $domain = $this->getDomainFromParams($params);
        $groups = $params['groups'];

        $registrant = $groups['Registrant'] ?? [];
        $admin = $groups['Admin'] ?? [];
        $tech = $groups['Tech'] ?? [];
        $billing = $groups['Billing'] ?? [];

        // Fallback for billing contact
        $billFirstname = $billing['firstname'] ?? ($admin['firstname'] ?? '');
        $billLastname = $billing['lastname'] ?? $billFirstname;

        $apiParams = $this->buildBaseParams('savecontactdetails', $domain);
        $apiParams = array_merge($apiParams, [
            // Registrant
            'dom_org' => $registrant['company'] ?? '',
            'dom_fn' => $registrant['firstname'] ?? '',
            'dom_ln' => $registrant['lastname'] ?? '',
            'dom_adr1' => $registrant['address1'] ?? '',
            'dom_adr2' => $registrant['address2'] ?? '',
            'dom_ct' => $registrant['city'] ?? '',
            'dom_st' => $registrant['state'] ?? '',
            'dom_co' => $registrant['country'] ?? '',
            'dom_ph' => $registrant['phone'] ?? '',
            'dom_pc' => $registrant['postal_code'] ?? '',
            'dom_em' => $registrant['email'] ?? '',
            // Admin
            'admi_fn' => $admin['firstname'] ?? '',
            'admi_ln' => $admin['lastname'] ?? '',
            'admi_adr1' => $admin['address1'] ?? '',
            'admi_adr2' => $admin['address2'] ?? '',
            'admi_ct' => $admin['city'] ?? '',
            'admi_st' => $admin['state'] ?? '',
            'admi_co' => $admin['country'] ?? '',
            'admi_ph' => $admin['phone'] ?? '',
            'admi_pc' => $admin['postal_code'] ?? '',
            'admi_em' => $admin['email'] ?? '',
            // Tech
            'tech_fn' => $tech['firstname'] ?? '',
            'tech_ln' => $tech['lastname'] ?? '',
            'tech_adr1' => $tech['address1'] ?? '',
            'tech_adr2' => $tech['address2'] ?? '',
            'tech_ct' => $tech['city'] ?? '',
            'tech_st' => $tech['state'] ?? '',
            'tech_co' => $tech['country'] ?? '',
            'tech_ph' => $tech['phone'] ?? '',
            'tech_pc' => $tech['postal_code'] ?? '',
            'tech_em' => $tech['email'] ?? '',
            // Billing
            'bill_fn' => $billFirstname,
            'bill_ln' => $billLastname,
            'bill_adr1' => $billing['address1'] ?? '',
            'bill_adr2' => $billing['address2'] ?? '',
            'bill_ct' => $billing['city'] ?? '',
            'bill_st' => $billing['state'] ?? '',
            'bill_co' => $billing['country'] ?? '',
            'bill_ph' => $billing['phone'] ?? '',
            'bill_pc' => $billing['postal_code'] ?? '',
            'bill_em' => $billing['email'] ?? '',
        ]);

        $result = $this->apiCall($apiParams);

        if (empty($result)) {
            return [
                'status' => 'error',
                'message' => __('admin/modules.bizcn_api_empty_response'),
            ];
        }

        if ($this->isSuccessResponse($result)) {
            Log::info('Bizcn: Contact details updated', ['domain' => $domain]);

            return [
                'status' => 'success',
                'message' => __('admin/modules.bizcn_set_contacts_success'),
                'data' => [
                    'domain' => $domain,
                    'groups' => $groups,
                    'updated_at' => now()->toISOString(),
                ],
            ];
        }

        return [
            'status' => 'error',
            'message' => __('admin/modules.bizcn_set_contacts_failed', ['error' => $result]),
        ];
    }

    // =========================================================================
    // Optional Methods - Domain Lock
    // =========================================================================

    /**
     * Get the lock status of a domain
     *
     * @param  array  $params  Parameters
     * @return array
     */
    public function getDomainLock(array $params)
    {
        if (! isset($params['domain']) || empty($params['domain'])) {
            return [
                'status' => 'error',
                'message' => __('admin/modules.bizcn_missing_param', ['param' => 'domain']),
            ];
        }

        $domain = $this->getDomainFromParams($params);
        $apiParams = $this->buildBaseParams('getdomainlock', $domain);

        $result = $this->apiCall($apiParams);

        if (empty($result)) {
            return [
                'status' => 'error',
                'message' => __('admin/modules.bizcn_api_empty_response'),
            ];
        }

        if ($this->isSuccessResponse($result)) {
            $lines = explode("\r\n", $result);
            $lockValue = trim(substr($lines[1] ?? '', 5));
            $locked = ($lockValue === 'true');

            return [
                'status' => 'success',
                'message' => __('admin/modules.bizcn_get_lock_success'),
                'data' => [
                    'domain' => $domain,
                    'locked' => $locked,
                ],
            ];
        }

        return [
            'status' => 'error',
            'message' => __('admin/modules.bizcn_get_lock_failed', ['error' => $result]),
        ];
    }

    /**
     * Update the lock status of a domain
     *
     * @param  array  $params  Parameters
     * @return array
     */
    public function updateDomainLock(array $params)
    {
        if (! isset($params['domain']) || empty($params['domain'])) {
            return [
                'status' => 'error',
                'message' => __('admin/modules.bizcn_missing_param', ['param' => 'domain']),
            ];
        }

        $domain = $this->getDomainFromParams($params);
        $lockStatus = $params['lock_status'] ?? true;
        $module = $lockStatus ? 'lockdomain' : 'unlockdomain';

        $apiParams = $this->buildBaseParams($module, $domain);

        $result = $this->apiCall($apiParams);

        if (empty($result)) {
            return [
                'status' => 'error',
                'message' => __('admin/modules.bizcn_api_empty_response'),
            ];
        }

        if ($this->isSuccessResponse($result)) {
            Log::info('Bizcn: Domain lock updated', [
                'domain' => $domain,
                'locked' => $lockStatus,
            ]);

            return [
                'status' => 'success',
                'message' => __('admin/modules.bizcn_set_lock_success'),
                'data' => [
                    'domain' => $domain,
                    'lock_status' => $lockStatus,
                    'updated_at' => now()->toISOString(),
                ],
            ];
        }

        return [
            'status' => 'error',
            'message' => __('admin/modules.bizcn_set_lock_failed', ['error' => $result]),
        ];
    }

    // =========================================================================
    // Optional Methods - DNS Management
    // =========================================================================

    /**
     * Get DNS records for a domain
     *
     * @param  array  $params  Parameters
     * @return array
     */
    public function getDNSRecords(array $params)
    {
        if (! isset($params['domain']) || empty($params['domain'])) {
            return [
                'status' => 'error',
                'message' => __('admin/modules.bizcn_missing_param', ['param' => 'domain']),
            ];
        }

        $domain = $this->getDomainFromParams($params);
        $apiParams = $this->buildBaseParams('getdnsrecord', $domain);

        $result = $this->apiCall($apiParams);

        if (empty($result)) {
            return [
                'status' => 'error',
                'message' => __('admin/modules.bizcn_api_empty_response'),
            ];
        }

        if ($this->isSuccessResponse($result)) {
            $lines = explode("\r\n", $result);
            $records = [];

            foreach ($lines as $index => $line) {
                // Skip the first line (status code)
                if ($index === 0) {
                    continue;
                }

                $parts = explode('|', $line);
                if (count($parts) >= 3) {
                    $records[] = [
                        'id' => (string) $index,
                        'name' => $parts[0] ?? '',
                        'type' => $parts[1] ?? '',
                        'value' => $parts[2] ?? '',
                        'ttl' => 3600,
                        'priority' => null,
                    ];
                }
            }

            return [
                'status' => 'success',
                'message' => __('admin/modules.bizcn_get_dns_success'),
                'data' => [
                    'domain' => $domain,
                    'records' => $records,
                ],
            ];
        }

        return [
            'status' => 'error',
            'message' => __('admin/modules.bizcn_get_dns_failed', ['error' => $result]),
        ];
    }

    /**
     * Add a DNS record for a domain
     *
     * @param  array  $params  Parameters
     * @return array
     */
    public function addDNSRecord(array $params)
    {
        $requiredParams = ['domain', 'type', 'name', 'value'];
        foreach ($requiredParams as $param) {
            if (! isset($params[$param]) || empty($params[$param])) {
                return [
                    'status' => 'error',
                    'message' => __('admin/modules.bizcn_missing_param', ['param' => $param]),
                ];
            }
        }

        $domain = $this->getDomainFromParams($params);

        $apiParams = $this->buildBaseParams('adddnsrecord', $domain);
        $apiParams['resolvetype'] = $params['type'];
        $apiParams['resolvehost'] = $params['name'];
        $apiParams['resolvevalue'] = $params['value'];
        $apiParams['mxlevel'] = $params['priority'] ?? 10;

        $result = $this->apiCall($apiParams);

        if (empty($result)) {
            return [
                'status' => 'error',
                'message' => __('admin/modules.bizcn_api_empty_response'),
            ];
        }

        if ($this->isSuccessResponse($result)) {
            return [
                'status' => 'success',
                'message' => __('admin/modules.bizcn_add_dns_success'),
                'data' => [
                    'domain' => $domain,
                    'type' => $params['type'],
                    'name' => $params['name'],
                    'value' => $params['value'],
                    'ttl' => $params['ttl'] ?? 3600,
                    'priority' => $params['priority'] ?? null,
                ],
            ];
        }

        return [
            'status' => 'error',
            'message' => __('admin/modules.bizcn_add_dns_failed', ['error' => $result]),
        ];
    }

    /**
     * Update a DNS record for a domain
     *
     * @param  array  $params  Parameters
     * @return array
     */
    public function updateDNSRecord(array $params)
    {
        $requiredParams = ['domain', 'type', 'name', 'value'];
        foreach ($requiredParams as $param) {
            if (! isset($params[$param]) || empty($params[$param])) {
                return [
                    'status' => 'error',
                    'message' => __('admin/modules.bizcn_missing_param', ['param' => $param]),
                ];
            }
        }

        $domain = $this->getDomainFromParams($params);

        $apiParams = $this->buildBaseParams('moddnsrecord', $domain);
        $apiParams['resolvetype'] = $params['type'];
        $apiParams['resolvehost'] = $params['name'];
        $apiParams['resolveoldvalue'] = $params['old_value'] ?? '';
        $apiParams['resolvevalue'] = $params['value'];
        $apiParams['mxlevel'] = $params['priority'] ?? 10;

        $result = $this->apiCall($apiParams);

        if (empty($result)) {
            return [
                'status' => 'error',
                'message' => __('admin/modules.bizcn_api_empty_response'),
            ];
        }

        if ($this->isSuccessResponse($result)) {
            return [
                'status' => 'success',
                'message' => __('admin/modules.bizcn_update_dns_success'),
                'data' => [
                    'domain' => $domain,
                    'type' => $params['type'],
                    'name' => $params['name'],
                    'value' => $params['value'],
                    'ttl' => $params['ttl'] ?? 3600,
                    'priority' => $params['priority'] ?? null,
                ],
            ];
        }

        return [
            'status' => 'error',
            'message' => __('admin/modules.bizcn_update_dns_failed', ['error' => $result]),
        ];
    }

    /**
     * Delete a DNS record for a domain
     *
     * @param  array  $params  Parameters
     * @return array
     */
    public function deleteDNSRecord(array $params)
    {
        $requiredParams = ['domain', 'type', 'name', 'value'];
        foreach ($requiredParams as $param) {
            if (! isset($params[$param]) || empty($params[$param])) {
                return [
                    'status' => 'error',
                    'message' => __('admin/modules.bizcn_missing_param', ['param' => $param]),
                ];
            }
        }

        $domain = $this->getDomainFromParams($params);

        $apiParams = $this->buildBaseParams('deldnsrecord', $domain);
        $apiParams['resolvetype'] = $params['type'];
        $apiParams['resolvehost'] = $params['name'];
        $apiParams['resolveoldvalue'] = $params['value'];
        $apiParams['mxlevel'] = $params['priority'] ?? 10;

        $result = $this->apiCall($apiParams);

        if (empty($result)) {
            return [
                'status' => 'error',
                'message' => __('admin/modules.bizcn_api_empty_response'),
            ];
        }

        if ($this->isSuccessResponse($result)) {
            return [
                'status' => 'success',
                'message' => __('admin/modules.bizcn_delete_dns_success'),
                'data' => [
                    'domain' => $domain,
                    'deleted_at' => now()->toISOString(),
                ],
            ];
        }

        return [
            'status' => 'error',
            'message' => __('admin/modules.bizcn_delete_dns_failed', ['error' => $result]),
        ];
    }

    /**
     * Bulk update DNS records for a domain
     * Compares existing records with new records and performs add/mod/del operations
     *
     * @param  array  $params  Parameters
     * @return array
     */
    public function updateDNSRecords(array $params)
    {
        if (! isset($params['domain']) || empty($params['domain'])) {
            return [
                'status' => 'error',
                'message' => __('admin/modules.bizcn_missing_param', ['param' => 'domain']),
            ];
        }

        if (! isset($params['records']) || ! is_array($params['records'])) {
            return [
                'status' => 'error',
                'message' => __('admin/modules.bizcn_missing_param', ['param' => 'records']),
            ];
        }

        $domain = $this->getDomainFromParams($params);
        $newRecords = $params['records'];

        // Get existing DNS records
        $existingResult = $this->getDNSRecords(['domain' => $domain]);
        if ($existingResult['status'] === 'error') {
            return [
                'status' => 'error',
                'message' => __('admin/modules.bizcn_update_dns_get_failed'),
            ];
        }

        $existingRecords = $existingResult['data']['records'] ?? [];
        $operations = [];

        // Compare existing records with new ones to determine operations
        $tmpNewRecords = $newRecords;

        foreach ($existingRecords as $existing) {
            $found = false;
            foreach ($newRecords as $newKey => $new) {
                if ($existing['name'] === $new['name'] && $existing['type'] === $new['type'] && $existing['value'] === $new['value']) {
                    // Record unchanged - no operation needed
                    $found = true;
                    unset($tmpNewRecords[$newKey]);

                    break;
                }
                if ($existing['name'] === $new['name'] && $existing['type'] === $new['type']) {
                    // Record modified - need to update
                    $operations[] = ['func' => 'MOD', 'record' => $new, 'old_value' => $existing['value']];
                    $found = true;
                    unset($tmpNewRecords[$newKey]);

                    break;
                }
            }
            if (! $found) {
                // Record removed - need to delete
                $operations[] = ['func' => 'DEL', 'record' => $existing];
            }
        }

        // Remaining new records need to be added
        foreach ($tmpNewRecords as $new) {
            $operations[] = ['func' => 'ADD', 'record' => $new];
        }

        // Execute operations
        $errors = [];
        foreach ($operations as $op) {
            $record = $op['record'];
            $opResult = null;

            switch ($op['func']) {
                case 'ADD':
                    $opResult = $this->addDNSRecord([
                        'domain' => $domain,
                        'type' => $record['type'],
                        'name' => $record['name'],
                        'value' => $record['value'],
                        'priority' => $record['priority'] ?? null,
                    ]);
                    break;

                case 'MOD':
                    $opResult = $this->updateDNSRecord([
                        'domain' => $domain,
                        'type' => $record['type'],
                        'name' => $record['name'],
                        'old_value' => $op['old_value'],
                        'value' => $record['value'],
                        'priority' => $record['priority'] ?? null,
                    ]);
                    break;

                case 'DEL':
                    $opResult = $this->deleteDNSRecord([
                        'domain' => $domain,
                        'type' => $record['type'],
                        'name' => $record['name'],
                        'value' => $record['value'],
                        'priority' => $record['priority'] ?? null,
                    ]);
                    break;
            }

            if ($opResult !== null && $opResult['status'] === 'error') {
                $errors[] = $opResult['message'];
            }
        }

        if (! empty($errors)) {
            return [
                'status' => 'error',
                'message' => __('admin/modules.bizcn_update_dns_partial_failed', ['errors' => implode('; ', $errors)]),
            ];
        }

        return [
            'status' => 'success',
            'message' => __('admin/modules.bizcn_update_dns_records_success'),
            'data' => [
                'domain' => $domain,
                'records' => $newRecords,
                'updated_at' => now()->toISOString(),
            ],
        ];
    }

    // =========================================================================
    // Optional Methods - Child Nameservers (Glue Records)
    // =========================================================================

    /**
     * Register a child nameserver (glue record)
     *
     * @param  array  $params  Parameters
     * @return array
     */
    public function addChildNameserver(array $params)
    {
        $requiredParams = ['domain', 'hostname', 'ip'];
        foreach ($requiredParams as $param) {
            if (! isset($params[$param]) || empty($params[$param])) {
                return [
                    'status' => 'error',
                    'message' => __('admin/modules.bizcn_missing_param', ['param' => $param]),
                ];
            }
        }

        $domain = $this->getDomainFromParams($params);

        $apiParams = $this->buildBaseParams('createnameserver', $domain);
        $apiParams['hostname'] = $params['hostname'];
        $apiParams['ip'] = $params['ip'];

        $result = $this->apiCall($apiParams);

        if (empty($result)) {
            return [
                'status' => 'error',
                'message' => __('admin/modules.bizcn_api_empty_response'),
            ];
        }

        if ($this->isSuccessResponse($result)) {
            Log::info('Bizcn: Child nameserver created', [
                'domain' => $domain,
                'hostname' => $params['hostname'],
                'ip' => $params['ip'],
            ]);

            return [
                'status' => 'success',
                'message' => __('admin/modules.bizcn_add_child_ns_success'),
                'data' => [
                    'hostname' => $params['hostname'],
                    'ip' => $params['ip'],
                ],
            ];
        }

        return [
            'status' => 'error',
            'message' => __('admin/modules.bizcn_add_child_ns_failed', ['error' => $result]),
        ];
    }

    /**
     * Modify a child nameserver (glue record)
     *
     * @param  array  $params  Parameters
     * @return array
     */
    public function updateChildNameserver(array $params)
    {
        $domain = $this->getDomainFromParams($params);
        // Caller (DomainManagementController) sends nameserver_id (= hostname)
        // + hostname + ip; WHMCS bizcn.php:606 modnameserver = hostname/oldip/newip.
        $hostname = $params['hostname'] ?? ($params['nameserver_id'] ?? '');
        $newIp = $params['ip'] ?? '';
        $oldIp = $params['old_ip'] ?? ($params['current_ip'] ?? '');

        if (empty($domain) || empty($hostname) || empty($newIp)) {
            return [
                'status' => 'error',
                'message' => __('admin/modules.bizcn_missing_param', ['param' => 'hostname/ip']),
            ];
        }

        // modnameserver (cnobin api.cnobin.php:287-293) needs hostname/oldip/newip.
        // The API exposes no glue-list action to auto-resolve the current IP, so
        // the caller must supply it — fail closed if absent.
        if (empty($oldIp)) {
            return [
                'status' => 'error',
                'message' => __('admin/modules.bizcn_missing_param', ['param' => 'old_ip']),
            ];
        }

        $apiParams = $this->buildBaseParams('modnameserver', $domain);
        $apiParams['hostname'] = $hostname;
        $apiParams['oldip'] = $oldIp;
        $apiParams['newip'] = $newIp;

        $result = $this->apiCall($apiParams);

        if (empty($result)) {
            return [
                'status' => 'error',
                'message' => __('admin/modules.bizcn_api_empty_response'),
            ];
        }

        if ($this->isSuccessResponse($result)) {
            Log::info('Bizcn: Child nameserver updated', [
                'domain' => $domain,
                'hostname' => $hostname,
                'ip' => $newIp,
            ]);

            return [
                'status' => 'success',
                'message' => __('admin/modules.bizcn_update_child_ns_success'),
                'data' => [
                    'hostname' => $hostname,
                    'ip' => $newIp,
                ],
            ];
        }

        return [
            'status' => 'error',
            'message' => __('admin/modules.bizcn_update_child_ns_failed', ['error' => $result]),
        ];
    }

    /**
     * Delete a child nameserver (glue record)
     *
     * @param  array  $params  Parameters
     * @return array
     */
    public function deleteChildNameserver(array $params)
    {
        $domain = $this->getDomainFromParams($params);
        // Caller sends nameserver_id (= hostname); WHMCS bizcn.php:628 delnameserver = hostname.
        $hostname = $params['hostname'] ?? ($params['nameserver_id'] ?? '');

        if (empty($domain) || empty($hostname)) {
            return [
                'status' => 'error',
                'message' => __('admin/modules.bizcn_missing_param', ['param' => 'hostname']),
            ];
        }

        $apiParams = $this->buildBaseParams('delnameserver', $domain);
        $apiParams['hostname'] = $hostname;

        $result = $this->apiCall($apiParams);

        if (empty($result)) {
            return [
                'status' => 'error',
                'message' => __('admin/modules.bizcn_api_empty_response'),
            ];
        }

        if ($this->isSuccessResponse($result)) {
            Log::info('Bizcn: Child nameserver deleted', [
                'domain' => $domain,
                'hostname' => $hostname,
            ]);

            return [
                'status' => 'success',
                'message' => __('admin/modules.bizcn_delete_child_ns_success'),
                'data' => [
                    'hostname' => $hostname,
                    'deleted_at' => now()->toISOString(),
                ],
            ];
        }

        return [
            'status' => 'error',
            'message' => __('admin/modules.bizcn_delete_child_ns_failed', ['error' => $result]),
        ];
    }

    // =========================================================================
    // Sync / Details / EPP / Privacy / Child NS list
    // =========================================================================

    /**
     * Parse a 71.com/webrrpdomain "key:value" body (skips the status line).
     *
     * @return array<string,string>
     */
    protected function parseKeyValueResponse(?string $result): array
    {
        $parsed = [];
        $lines = preg_split("/\r\n|\n/", (string) $result);
        for ($i = 1, $n = count($lines); $i < $n; $i++) {
            $line = trim($lines[$i]);
            if ($line === '' || strpos($line, ':') === false) {
                continue;
            }
            $parts = explode(':', $line, 2);
            $parsed[trim($parts[0])] = trim($parts[1]);
        }

        return $parsed;
    }

    /**
     * Get the EPP/auth code for a domain.
     * Command: geteppcode (api.cnobin.php:271), response line eppcode:<value>.
     *
     * @param  array  $params  Parameters
     * @return array
     */
    public function getEppCode(array $params)
    {
        if (empty($params['domain']) && empty($params['sld'])) {
            return [
                'status' => 'error',
                'message' => __('admin/modules.bizcn_missing_param', ['param' => 'domain']),
            ];
        }

        $domain = $this->getDomainFromParams($params);
        $apiParams = $this->buildBaseParams('geteppcode', $domain);

        $result = $this->apiCall($apiParams);

        if (empty($result)) {
            return [
                'status' => 'error',
                'message' => __('admin/modules.bizcn_api_empty_response'),
            ];
        }

        if ($this->isSuccessResponse($result)) {
            $parsed = $this->parseKeyValueResponse($result);
            $eppCode = $parsed['eppcode'] ?? '';

            return [
                'status' => 'success',
                'message' => __('admin/modules.bizcn_get_epp_success'),
                'data' => [
                    'domain' => $domain,
                    'epp_code' => $eppCode,
                ],
            ];
        }

        return [
            'status' => 'error',
            'message' => __('admin/modules.bizcn_get_epp_failed', ['error' => $result]),
        ];
    }

    /**
     * Fetch registrar-authoritative domain info (expiry/status).
     * Command: getdomaininfo (api.cnobin.php:121), response includes expiredate.
     *
     * @param  array  $params  Parameters
     * @return array
     */
    public function getDomainDetails(array $params)
    {
        if (empty($params['domain']) && empty($params['sld'])) {
            return [
                'status' => 'error',
                'message' => __('admin/modules.bizcn_missing_param', ['param' => 'domain']),
            ];
        }

        $domain = $this->getDomainFromParams($params);
        $apiParams = $this->buildBaseParams('getdomaininfo', $domain);

        $result = $this->apiCall($apiParams);

        if (empty($result)) {
            return [
                'status' => 'error',
                'message' => __('admin/modules.bizcn_api_empty_response'),
            ];
        }

        if (! $this->isSuccessResponse($result)) {
            return [
                'status' => 'error',
                'message' => __('admin/modules.bizcn_get_details_failed', ['error' => $result]),
            ];
        }

        $info = $this->parseKeyValueResponse($result);

        $expiryRaw = $info['expiredate'] ?? ($info['expirydate'] ?? '');
        $expiryDate = null;
        if ($expiryRaw !== '') {
            $ts = strtotime($expiryRaw);
            if ($ts !== false) {
                $expiryDate = date('Y-m-d', $ts);
            }
        }

        // Nameservers + lock via commands the module already speaks.
        $nsResult = $this->getNameservers(['domain' => $domain]);
        $nameservers = ($nsResult['status'] ?? '') === 'success'
            ? ($nsResult['data']['nameservers'] ?? [])
            : [];

        $lockResult = $this->getDomainLock(['domain' => $domain]);
        $locked = ($lockResult['status'] ?? '') === 'success'
            ? ($lockResult['data']['locked'] ?? null)
            : null;

        return [
            'status' => 'success',
            'message' => __('admin/modules.bizcn_get_details_success'),
            'data' => [
                'domain' => $domain,
                'expiry_date' => $expiryDate,
                'status' => $info['status'] ?? null,
                'nameservers' => $nameservers,
                'locked' => $locked,
            ],
        ];
    }

    /**
     * Reconcile local expiry/status from the registrar's authoritative record.
     * Command: getdomaininfo (cnobin_Sync, cnobin.php:648).
     *
     * @param  array  $params  Parameters
     * @return array
     */
    public function syncDomain(array $params)
    {
        if (empty($params['domain']) && empty($params['sld'])) {
            return [
                'status' => 'error',
                'message' => __('admin/modules.bizcn_missing_param', ['param' => 'domain']),
            ];
        }

        $domain = $this->getDomainFromParams($params);
        $apiParams = $this->buildBaseParams('getdomaininfo', $domain);

        $result = $this->apiCall($apiParams);

        if (empty($result)) {
            return [
                'status' => 'error',
                'message' => __('admin/modules.bizcn_api_empty_response'),
            ];
        }

        if (! $this->isSuccessResponse($result)) {
            return [
                'status' => 'error',
                'message' => __('admin/modules.bizcn_sync_failed', ['error' => $result]),
            ];
        }

        $info = $this->parseKeyValueResponse($result);
        $expiryRaw = $info['expiredate'] ?? ($info['expirydate'] ?? '');
        $ts = $expiryRaw !== '' ? strtotime($expiryRaw) : false;

        $data = [
            'domain' => $domain,
            'active' => true,
            'expired' => false,
        ];

        if ($ts !== false) {
            $data['expiry_date'] = date('Y-m-d', $ts);
            $data['expired'] = time() > $ts;
            $data['active'] = time() <= $ts;
        }

        return [
            'status' => 'success',
            'message' => __('admin/modules.bizcn_sync_success'),
            'data' => $data,
        ];
    }

    /**
     * Poll transfer state. 71.com/webrrpdomain exposes getdomaininfo — presence
     * of an expiry/status implies the domain is in the account (transfer done);
     * a non-200 (not-yet-owned) implies still pending.
     *
     * @param  array  $params  Parameters
     * @return array
     */
    public function syncDomainTransfer(array $params)
    {
        if (empty($params['domain']) && empty($params['sld'])) {
            return [
                'status' => 'error',
                'message' => __('admin/modules.bizcn_missing_param', ['param' => 'domain']),
            ];
        }

        $domain = $this->getDomainFromParams($params);
        $apiParams = $this->buildBaseParams('getdomaininfo', $domain);

        $result = $this->apiCall($apiParams);

        if (empty($result)) {
            return [
                'status' => 'error',
                'message' => __('admin/modules.bizcn_api_empty_response'),
            ];
        }

        if ($this->isSuccessResponse($result)) {
            $info = $this->parseKeyValueResponse($result);
            $expiryRaw = $info['expiredate'] ?? ($info['expirydate'] ?? '');
            $ts = $expiryRaw !== '' ? strtotime($expiryRaw) : false;

            $data = [
                'domain' => $domain,
                'completed' => true,
                'pending' => false,
                'failed' => false,
            ];
            if ($ts !== false) {
                $data['expiry_date'] = date('Y-m-d', $ts);
            }

            return [
                'status' => 'success',
                'message' => __('admin/modules.bizcn_transfer_sync_completed'),
                'data' => $data,
            ];
        }

        // Not yet in the account → transfer still in progress.
        return [
            'status' => 'success',
            'message' => __('admin/modules.bizcn_transfer_sync_pending'),
            'data' => [
                'domain' => $domain,
                'completed' => false,
                'pending' => true,
                'failed' => false,
            ],
        ];
    }

    /**
     * Toggle WHOIS privacy. Command: startwhoisprotect / stopwhoisprotect
     * (api.cnobin.php:258-268).
     *
     * @param  array  $params  Parameters
     * @return array
     */
    public function updatePrivacySettings(array $params)
    {
        if (empty($params['domain']) && empty($params['sld'])) {
            return [
                'status' => 'error',
                'message' => __('admin/modules.bizcn_missing_param', ['param' => 'domain']),
            ];
        }

        $domain = $this->getDomainFromParams($params);
        $enable = (bool) ($params['enable'] ?? ($params['id_protection'] ?? ($params['status'] ?? false)));
        $module = $enable ? 'startwhoisprotect' : 'stopwhoisprotect';

        $apiParams = $this->buildBaseParams($module, $domain);

        $result = $this->apiCall($apiParams);

        if (empty($result)) {
            return [
                'status' => 'error',
                'message' => __('admin/modules.bizcn_api_empty_response'),
            ];
        }

        if ($this->isSuccessResponse($result)) {
            Log::info('Bizcn: Privacy updated', ['domain' => $domain, 'enabled' => $enable]);

            return [
                'status' => 'success',
                'message' => __('admin/modules.bizcn_set_privacy_success'),
                'data' => [
                    'domain' => $domain,
                    'id_protection' => $enable,
                ],
            ];
        }

        return [
            'status' => 'error',
            'message' => __('admin/modules.bizcn_set_privacy_failed', ['error' => $result]),
        ];
    }

    /**
     * List registered child nameservers (glue records).
     *
     * The 71.com/webrrpdomain API (cnobin api.cnobin.php) exposes no glue-list
     * action, and its getdomaininfo body only returns expiredate/status — no
     * host/ip glue pairs. Deriving dns_host1..13/dns_ip1..13 from that body was
     * fabricating fields the API never returns, so we honestly report the
     * capability as unsupported rather than manufacturing empty/garbage glue.
     *
     * @param  array  $params  Parameters
     * @return array
     */
    public function getChildNameservers(array $params)
    {
        return [
            'status' => 'error',
            'message' => __('admin/modules.bizcn_unsupported_child_ns_list'),
        ];
    }

    /**
     * Domain availability check — unsupported by the 71.com/webrrpdomain API
     * used by this module (no checkdomain action in the reference).
     *
     * @param  array  $params  Parameters
     * @return array
     */
    public function checkDomainAvailability(array $params)
    {
        return [
            'status' => 'error',
            'message' => __('admin/modules.bizcn_unsupported_availability'),
        ];
    }

    /**
     * Domain suggestions — unsupported by the 71.com/webrrpdomain API.
     *
     * @param  array  $params  Parameters
     * @return array
     */
    public function checkDomainSuggestions(array $params)
    {
        return [
            'status' => 'error',
            'message' => __('admin/modules.bizcn_unsupported_suggestions'),
        ];
    }
}
