<?php

namespace GriffinForms\Includes\Onboarding;

use GriffinForms\Traits\Singleton;

class Progress extends \GriffinForms\Format
{
    use Singleton;

    protected $feature_flags;
    protected $user_state_repository;

    protected function setFeatureFlags()
    {
        $this->feature_flags = FeatureFlags::getInstance();
    }

    protected function setUserStateRepository()
    {
        $this->user_state_repository = UserStateRepository::getInstance();
    }

    public function markEntry(string $entry_source = 'manual', int $user_id = 0): array
    {
        $state = $this->user_state_repository->getState($user_id);
        $current_version = $this->feature_flags->getExperienceVersion();

        if ($state['experience_version'] !== $current_version) {
            $state = $this->user_state_repository->getDefaultState();
        }

        if ($state['status'] === 'completed' && $state['experience_version'] === $current_version) {
            $state['entry_source'] = $this->sanitizeEntrySource($entry_source);
            $state['updated_at'] = current_time('mysql', true);
            $this->user_state_repository->saveState($state, $user_id);
            return $state;
        }

        $resolved_step = $this->resolveResumeStep($state);
        $now = current_time('mysql', true);

        $state['experience_version'] = $current_version;
        $state['status'] = 'in_progress';
        $state['seen'] = 1;
        $state['entry_source'] = $this->sanitizeEntrySource($entry_source);
        $state['current_step'] = $resolved_step;
        $state['first_seen_at'] = $state['first_seen_at'] ?: $now;
        $state['updated_at'] = $now;

        $this->user_state_repository->saveState($state, $user_id);

        return $state;
    }

    public function markDismissed(int $user_id = 0): array
    {
        $state = $this->user_state_repository->getState($user_id);
        $state['status'] = 'dismissed';
        $state['dismissed'] = 1;
        $state['dismissed_at'] = current_time('mysql', true);
        $state['updated_at'] = $state['dismissed_at'];

        if (!$this->feature_flags->isEnabled('resume')) {
            $state['current_step'] = $this->feature_flags->getFirstEnabledStep();
        }

        $this->user_state_repository->saveState($state, $user_id);

        return $state;
    }

    public function moveToStep(string $step_key, array $changes = [], int $user_id = 0): array
    {
        $state = $this->user_state_repository->getState($user_id);
        $resolved_step = $this->feature_flags->isStepEnabled($step_key)
            ? $step_key
            : $this->feature_flags->getFirstEnabledStep();

        $state = array_merge($state, $changes);
        $state['experience_version'] = $this->feature_flags->getExperienceVersion();
        $state['status'] = 'in_progress';
        $state['seen'] = 1;
        $state['dismissed'] = 0;
        $state['current_step'] = $resolved_step;
        $state['updated_at'] = current_time('mysql', true);

        $this->user_state_repository->saveState($state, $user_id);

        return $state;
    }

    public function markCompleted(array $changes = [], int $user_id = 0): array
    {
        $state = $this->user_state_repository->getState($user_id);
        $now = current_time('mysql', true);

        $state = array_merge($state, $changes);
        $state['experience_version'] = $this->feature_flags->getExperienceVersion();
        $state['status'] = 'completed';
        $state['seen'] = 1;
        $state['dismissed'] = 0;
        $state['completed'] = 1;
        $state['current_step'] = null;
        $state['completed_at'] = $now;
        $state['updated_at'] = $now;

        $this->user_state_repository->saveState($state, $user_id);

        return $state;
    }

    public function resolveResumeStep(array $state): ?string
    {
        if (!$this->feature_flags->isEnabled('resume')) {
            return $this->feature_flags->getFirstEnabledStep();
        }

        $current_step = isset($state['current_step']) && is_string($state['current_step'])
            ? sanitize_key($state['current_step'])
            : '';

        if ($current_step !== '' && $this->feature_flags->isStepEnabled($current_step)) {
            return $current_step;
        }

        return $this->feature_flags->getFirstEnabledStep();
    }

    protected function sanitizeEntrySource(string $entry_source): string
    {
        $entry_source = sanitize_key($entry_source);
        $allowed_sources = ['activation_redirect', 'forms_empty_state', 'manual'];
        return in_array($entry_source, $allowed_sources, true) ? $entry_source : 'manual';
    }
}
