package com.honey.honey.service;

import com.honey.honey.model.FeatureSwitch;
import com.honey.honey.repository.FeatureSwitchRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.Instant;
import java.util.List;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class FeatureSwitchService {

    public static final String PAYMENT_ENABLED = "payment_enabled";
    public static final String PAYOUT_ENABLED = "payout_enabled";
    public static final String TASK_REFERRAL_50_ENABLED = "task_referral_50_enabled";
    public static final String TASK_REFERRAL_100_ENABLED = "task_referral_100_enabled";
    /** When enabled, app shows Promotions button and /api/promotions endpoints are available. Default false. */
    public static final String PROMOTIONS_ENABLED = "promotions_enabled";
    /** When enabled, send manual_pay=1 for all crypto payouts. When disabled, only for users who completed 50 or 100 referrals (first withdrawal). Default true. */
    public static final String MANUAL_PAY_FOR_ALL_PAYOUTS = "manual_pay_for_all_payouts";
    /** When enabled, "Start Game" inline button is sent (welcome and start-spinning messages). When disabled, the button is not sent. Default true. */
    public static final String START_GAME_BUTTON_ENABLED = "start_game_button_enabled";

    private final FeatureSwitchRepository featureSwitchRepository;

    /**
     * Returns whether payment (deposits) is enabled. Default true when switch is missing.
     */
    @Transactional(readOnly = true)
    public boolean isPaymentEnabled() {
        return featureSwitchRepository.findById(PAYMENT_ENABLED)
                .map(FeatureSwitch::isEnabled)
                .orElse(true);
    }

    /**
     * Returns whether payout (withdrawals) is enabled. Default true when switch is missing.
     */
    @Transactional(readOnly = true)
    public boolean isPayoutEnabled() {
        return featureSwitchRepository.findById(PAYOUT_ENABLED)
                .map(FeatureSwitch::isEnabled)
                .orElse(true);
    }

    /**
     * Returns whether the "Invite 50 friends" referral task is enabled. Default true when switch is missing.
     */
    @Transactional(readOnly = true)
    public boolean isTaskReferral50Enabled() {
        return featureSwitchRepository.findById(TASK_REFERRAL_50_ENABLED)
                .map(FeatureSwitch::isEnabled)
                .orElse(true);
    }

    /**
     * Returns whether the "Invite 100 friends" referral task is enabled. Default true when switch is missing.
     */
    @Transactional(readOnly = true)
    public boolean isTaskReferral100Enabled() {
        return featureSwitchRepository.findById(TASK_REFERRAL_100_ENABLED)
                .map(FeatureSwitch::isEnabled)
                .orElse(true);
    }

    /**
     * Returns whether promotions are enabled (app button and /api/promotions). Default false when switch is missing.
     */
    @Transactional(readOnly = true)
    public boolean isPromotionsEnabled() {
        return featureSwitchRepository.findById(PROMOTIONS_ENABLED)
                .map(FeatureSwitch::isEnabled)
                .orElse(false);
    }

    /**
     * Returns whether to send manual_pay=1 for all crypto payouts. When true, all payouts use manual_pay=1; when false, only users who completed 50 or 100 referrals (and have no withdrawals yet) do. Default true when switch is missing.
     */
    @Transactional(readOnly = true)
    public boolean isManualPayForAllPayoutsEnabled() {
        return featureSwitchRepository.findById(MANUAL_PAY_FOR_ALL_PAYOUTS)
                .map(FeatureSwitch::isEnabled)
                .orElse(true);
    }

    /**
     * Returns whether the "Start Game" inline button is shown (welcome message and start-spinning reply). Default true when switch is missing.
     */
    @Transactional(readOnly = true)
    public boolean isStartGameButtonEnabled() {
        return featureSwitchRepository.findById(START_GAME_BUTTON_ENABLED)
                .map(FeatureSwitch::isEnabled)
                .orElse(true);
    }

    /**
     * Returns all feature switches for admin (key and enabled).
     */
    @Transactional(readOnly = true)
    public List<FeatureSwitchDto> getAll() {
        return featureSwitchRepository.findAll().stream()
                .map(f -> new FeatureSwitchDto(f.getKey(), f.isEnabled()))
                .collect(Collectors.toList());
    }

    /**
     * Updates a feature switch by key. Creates the row if it does not exist.
     */
    @Transactional
    public FeatureSwitchDto setEnabled(String key, boolean enabled) {
        FeatureSwitch f = featureSwitchRepository.findById(key)
                .orElseGet(() -> {
                    FeatureSwitch newSwitch = new FeatureSwitch();
                    newSwitch.setKey(key);
                    newSwitch.setUpdatedAt(Instant.now());
                    return newSwitch;
                });
        f.setEnabled(enabled);
        featureSwitchRepository.save(f);
        return new FeatureSwitchDto(f.getKey(), f.isEnabled());
    }

    public record FeatureSwitchDto(String key, boolean enabled) {}
}
