<?php

namespace PloverCRM\Core\Services;

use PloverCRM\Common\Permissions;

/**
 * Versioned workspace setup state for first-run onboarding.
 */
class WorkspaceSetupService
{
    public const OPTION_NAME = 'plover_crm_workspace_setup_state';
    public const VERSION = 1;

    public const STEP_BUSINESS_INFORMATION = 'business_information';
    public const STEP_PIPELINE = 'pipeline';

    public static function isEnabled(): bool
    {
        return (bool) apply_filters('plover_crm_workspace_setup_enabled', false);
    }

    public static function getState(): array
    {
        $isEnabled = self::isEnabled();
        $stored = self::getStoredState();
        $storedCompletedSteps = self::normalizeCompletedSteps($stored['completed_steps'] ?? []);

        $completedSteps = [
            self::STEP_BUSINESS_INFORMATION => $storedCompletedSteps[self::STEP_BUSINESS_INFORMATION] || self::hasBusinessInformation(),
            self::STEP_PIPELINE => $storedCompletedSteps[self::STEP_PIPELINE],
        ];

        return [
            'version' => self::VERSION,
            'isEnabled' => $isEnabled,
            'isCompleted' => !$isEnabled || !empty($stored['is_completed']),
            'canManage' => Permissions::isSuperAdmin(),
            'completedAt' => self::sanitizeTimestamp($stored['completed_at'] ?? ''),
            'updatedAt' => self::sanitizeTimestamp($stored['updated_at'] ?? ''),
            'completedSteps' => $completedSteps,
            'steps' => self::buildStepPayloads($completedSteps),
        ];
    }

    /**
     * Update setup progress and optionally mark onboarding complete.
     *
     * @param array $payload
     * @return array|\WP_Error
     */
    public static function updateState(array $payload)
    {
        $stored = self::getStoredState();
        $storedCompletedSteps = self::normalizeCompletedSteps($stored['completed_steps'] ?? []);
        $incomingCompletedSteps = self::normalizeCompletedSteps($payload['completed_steps'] ?? []);

        $completedSteps = [
            self::STEP_BUSINESS_INFORMATION => $incomingCompletedSteps[self::STEP_BUSINESS_INFORMATION] || $storedCompletedSteps[self::STEP_BUSINESS_INFORMATION] || self::hasBusinessInformation(),
            self::STEP_PIPELINE => $incomingCompletedSteps[self::STEP_PIPELINE] || $storedCompletedSteps[self::STEP_PIPELINE],
        ];

        $shouldComplete = array_key_exists('is_completed', $payload)
            ? !empty($payload['is_completed'])
            : !empty($stored['is_completed']);

        if ($shouldComplete && !self::areAllRequiredStepsComplete($completedSteps)) {
            return new \WP_Error(
                'workspace_setup_incomplete',
                'Complete the required setup steps before finishing onboarding.',
                [
                    'status' => 422,
                    'missing_steps' => self::getMissingRequiredSteps($completedSteps),
                ]
            );
        }

        $updatedAt = self::currentTimestamp();
        $completedAt = self::sanitizeTimestamp($stored['completed_at'] ?? '');

        if ($shouldComplete && $completedAt === null) {
            $completedAt = $updatedAt;
        }

        $nextState = [
            'version' => self::VERSION,
            'is_completed' => $shouldComplete,
            'completed_steps' => $completedSteps,
            'completed_at' => $completedAt,
            'updated_at' => $updatedAt,
        ];

        update_option(self::OPTION_NAME, $nextState);

        return self::getState();
    }

    private static function getStoredState(): array
    {
        $value = get_option(self::OPTION_NAME, null);

        return is_array($value) ? $value : [];
    }

    private static function normalizeCompletedSteps($value): array
    {
        $steps = is_array($value) ? $value : [];

        return [
            self::STEP_BUSINESS_INFORMATION => !empty($steps[self::STEP_BUSINESS_INFORMATION]),
            self::STEP_PIPELINE => !empty($steps[self::STEP_PIPELINE]),
        ];
    }

    private static function buildStepPayloads(array $completedSteps): array
    {
        return [
            [
                'key' => self::STEP_BUSINESS_INFORMATION,
                'label' => 'Business details',
                'description' => 'Add your business name and core contact details for this workspace.',
                'isRequired' => true,
                'isCompleted' => $completedSteps[self::STEP_BUSINESS_INFORMATION],
            ],
            [
                'key' => self::STEP_PIPELINE,
                'label' => 'Pipeline',
                'description' => 'Choose the starting stages your team will use to move contacts through the workspace.',
                'isRequired' => true,
                'isCompleted' => $completedSteps[self::STEP_PIPELINE],
            ],
        ];
    }

    private static function areAllRequiredStepsComplete(array $completedSteps): bool
    {
        foreach (self::getRequiredStepKeys() as $stepKey) {
            if (empty($completedSteps[$stepKey])) {
                return false;
            }
        }

        return true;
    }

    private static function getMissingRequiredSteps(array $completedSteps): array
    {
        return array_values(array_filter(
            self::getRequiredStepKeys(),
            static fn (string $stepKey): bool => empty($completedSteps[$stepKey])
        ));
    }

    private static function getRequiredStepKeys(): array
    {
        return [
            self::STEP_BUSINESS_INFORMATION,
            self::STEP_PIPELINE,
        ];
    }

    private static function hasBusinessInformation(): bool
    {
        $businessInformation = BusinessInformationService::get();

        if (!is_array($businessInformation)) {
            return false;
        }

        return trim((string) ($businessInformation['businessName'] ?? '')) !== '';
    }

    private static function currentTimestamp(): string
    {
        return current_datetime()->setTimezone(new \DateTimeZone('UTC'))->format(DATE_ATOM);
    }

    private static function sanitizeTimestamp($value): ?string
    {
        $value = is_string($value) ? sanitize_text_field($value) : '';

        return $value !== '' ? $value : null;
    }
}
