<?php

namespace MintyPHP\Service\Settings;

class SettingsUserLifecycleGateway
{
    private const USER_INACTIVITY_DEACTIVATE_DAYS_FALLBACK = 180;
    private const USER_INACTIVITY_DELETE_DAYS_FALLBACK = 365;
    private const USER_INACTIVITY_DAYS_MIN = 0;
    private const USER_INACTIVITY_DAYS_MAX = 3650;

    public function __construct(private readonly SettingsMetadataGateway $settingsMetadataGateway)
    {
    }

    public function getUserInactivityDeactivateDays(): int
    {
        $value = $this->settingsMetadataGateway->getInt(SettingKeys::USER_INACTIVITY_DEACTIVATE_DAYS_KEY);
        if ($value !== null && $this->isValidInactivityDays($value)) {
            return $value;
        }

        return self::USER_INACTIVITY_DEACTIVATE_DAYS_FALLBACK;
    }

    public function setUserInactivityDeactivateDays(?int $days, ?string $description = null): bool
    {
        $value = $days ?? self::USER_INACTIVITY_DEACTIVATE_DAYS_FALLBACK;
        if (!$this->isValidInactivityDays($value)) {
            return false;
        }
        if ($value === 0) {
            $deleteUpdated = $this->settingsMetadataGateway->set(
                SettingKeys::USER_INACTIVITY_DELETE_DAYS_KEY,
                '0',
                'setting.user_inactivity_delete_days'
            );
            if (!$deleteUpdated) {
                return false;
            }
        }

        $desc = $description ?? 'setting.user_inactivity_deactivate_days';
        return $this->settingsMetadataGateway->set(SettingKeys::USER_INACTIVITY_DEACTIVATE_DAYS_KEY, (string) $value, $desc);
    }

    public function getUserInactivityDeleteDays(): int
    {
        $deactivateDays = $this->getUserInactivityDeactivateDays();
        if ($deactivateDays <= 0) {
            return 0;
        }

        $value = $this->settingsMetadataGateway->getInt(SettingKeys::USER_INACTIVITY_DELETE_DAYS_KEY);
        if ($value !== null && $this->isValidInactivityDays($value)) {
            return $value;
        }

        return self::USER_INACTIVITY_DELETE_DAYS_FALLBACK;
    }

    public function setUserInactivityDeleteDays(?int $days, ?string $description = null): bool
    {
        $value = $days ?? self::USER_INACTIVITY_DELETE_DAYS_FALLBACK;
        if (!$this->isValidInactivityDays($value)) {
            return false;
        }
        if ($value > 0 && $this->getUserInactivityDeactivateDays() <= 0) {
            return false;
        }

        $desc = $description ?? 'setting.user_inactivity_delete_days';
        return $this->settingsMetadataGateway->set(SettingKeys::USER_INACTIVITY_DELETE_DAYS_KEY, (string) $value, $desc);
    }

    private function isValidInactivityDays(int $days): bool
    {
        return $days >= self::USER_INACTIVITY_DAYS_MIN && $days <= self::USER_INACTIVITY_DAYS_MAX;
    }

    /**
     * Record the completion of a UserLifecycleService::run() invocation.
     *
     * The two state keys (created_at, status) are written even when no users
     * were processed (no-op runs) so that the lifecycle cockpit can show the
     * tile correctly in every case. Audit-log entries cover what was done;
     * these settings cover that the run itself happened.
     */
    public function recordLastRun(string $createdAtUtc, string $status): bool
    {
        $atOk = $this->settingsMetadataGateway->set(
            SettingKeys::USER_LIFECYCLE_LAST_RUN_AT_KEY,
            $createdAtUtc
        );
        $statusOk = $this->settingsMetadataGateway->set(
            SettingKeys::USER_LIFECYCLE_LAST_RUN_STATUS_KEY,
            $status
        );
        return $atOk && $statusOk;
    }

    /**
     * @return array{created_at: string, status: string}|null
     *         null when no run has been recorded yet.
     */
    public function getLastRun(): ?array
    {
        $createdAt = $this->settingsMetadataGateway->getValue(SettingKeys::USER_LIFECYCLE_LAST_RUN_AT_KEY);
        if ($createdAt === null || $createdAt === '') {
            return null;
        }
        $status = (string) ($this->settingsMetadataGateway->getValue(SettingKeys::USER_LIFECYCLE_LAST_RUN_STATUS_KEY) ?? '');
        return [
            'created_at' => $createdAt,
            'status' => $status,
        ];
    }
}
