<?php

namespace PloverCRM\Core\Api\V1;

use PloverCRM\Common\RoleManager;
use PloverCRM\Core\Api\AbstractEndpoint;
use PloverCRM\Core\Services\CrmSettingsLogger;
use PloverCRM\Core\Services\GeneralSettingsPayloadBuilder;
use PloverCRM\Core\Services\SystemFieldProvisioner;
use WP_REST_Request;

/**
 * General Settings Endpoint
 *
 * GET /wp-json/plover-crm/v1/settings/general
 * PUT /wp-json/plover-crm/v1/settings/general
 */
class GeneralSettingsEndpoint extends AbstractEndpoint
{
    public function checkPermission(WP_REST_Request $request)
    {
        $passwordAuth = $this->authenticateWithPassword($request);

        if ($passwordAuth) {
            wp_set_current_user((int) $passwordAuth['user_id']);
        }

        $user = wp_get_current_user();

        if (!$user || !$user->ID) {
            return new \WP_Error(
                'unauthorized',
                'Authentication is required to access this resource',
                ['status' => 401]
            );
        }

        if (!RoleManager::isSuperAdmin((int) $user->ID)) {
            return new \WP_Error(
                'forbidden',
                'Only super administrators can manage CRM settings.',
                ['status' => 403]
            );
        }

        return true;
    }

    public function getRoute(): string
    {
        return '/settings/general';
    }

    public function getMethod()
    {
        return ['GET', 'PUT'];
    }

    public function handle(WP_REST_Request $request)
    {
        if ($request->get_method() === 'GET') {
            return $this->success(GeneralSettingsPayloadBuilder::build($this->container));
        }

        return $this->updateSettings($request);
    }

    private function updateSettings(WP_REST_Request $request)
    {
        $payload = $request->get_json_params();
        $logger = new CrmSettingsLogger();

        if (!is_array($payload)) {
            return $this->error(
                'Settings payload must be a JSON object.',
                422,
                'general_settings_invalid_payload'
            );
        }

        $crmNeedsRefresh = false;
        $currentSelectedProviderId = (string) get_option('plover_crm_selected_crm', '');
        $currentReplyToEmail = (string) get_option(GeneralSettingsPayloadBuilder::REPLY_TO_EMAIL_OPTION, '');

        if (array_key_exists('selectedProviderId', $payload)) {
            $selectedProviderId = sanitize_text_field((string) $payload['selectedProviderId']);
            $validationError = $this->validateProviderSelection($selectedProviderId);

            if ($validationError) {
                return $validationError;
            }

            update_option('plover_crm_selected_crm', $selectedProviderId);
            $crmNeedsRefresh = true;

            if ($selectedProviderId !== $currentSelectedProviderId) {
                $logger->info('CRM provider updated', [
                    'from_provider' => $currentSelectedProviderId,
                    'to_provider' => $selectedProviderId,
                ]);
            }
        }

        if (array_key_exists('replyToEmail', $payload)) {
            $replyToEmail = sanitize_email((string) $payload['replyToEmail']);

            if ($replyToEmail !== '' && !is_email($replyToEmail)) {
                return $this->error(
                    'Please provide a valid reply-to email address.',
                    422,
                    'general_settings_invalid_reply_to_email'
                );
            }

            update_option(GeneralSettingsPayloadBuilder::REPLY_TO_EMAIL_OPTION, $replyToEmail);

            if ($replyToEmail !== $currentReplyToEmail) {
                $logger->info('Reply-to email updated', [
                    'from_email' => $currentReplyToEmail,
                    'to_email' => $replyToEmail,
                ]);
            }
        }

        if (array_key_exists('activeColumns', $payload)) {
            if (!is_array($payload['activeColumns'])) {
                return $this->error(
                    'Active columns must be an array of field slugs.',
                    422,
                    'general_settings_invalid_active_columns'
                );
            }

            $validColumns = GeneralSettingsPayloadBuilder::getSelectableColumnSlugs($this->container);
            $activeColumns = array_values(array_filter(array_map(static function ($column) {
                return sanitize_text_field((string) $column);
            }, $payload['activeColumns']), static function ($column) use ($validColumns) {
                return $column !== '' && in_array($column, $validColumns, true);
            }));

            update_option(GeneralSettingsPayloadBuilder::ACTIVE_COLUMNS_OPTION, $activeColumns);
        }

        if ($crmNeedsRefresh) {
            GeneralSettingsPayloadBuilder::refreshCrmService($this->container);
            $provisioner = new SystemFieldProvisioner($this->container);
            $provisioner->syncForProviderSwitch();
        }

        return $this->success(
            GeneralSettingsPayloadBuilder::build($this->container)
        );
    }

    private function validateProviderSelection(string $selectedProviderId)
    {
        if ($selectedProviderId === '') {
            return $this->error(
                'Please choose a CRM provider.',
                422,
                'general_settings_missing_provider'
            );
        }

        $crmManager = new \PloverCRM\Core\CRM\CRMManager();
        $providers = $crmManager->getAvailableProviders();
        $provider = $providers[$selectedProviderId] ?? null;

        if (!$provider) {
            return $this->error(
                'The selected CRM provider does not exist.',
                422,
                'general_settings_invalid_provider'
            );
        }

        if (empty($provider['enabled'])) {
            return $this->error(
                'The selected CRM provider is currently disabled.',
                422,
                'general_settings_disabled_provider'
            );
        }

        if (empty($provider['available'])) {
            return $this->error(
                'The selected CRM provider is not available on this site.',
                422,
                'general_settings_unavailable_provider'
            );
        }

        return null;
    }
}
