package research.loghunter.service;

import jakarta.annotation.PostConstruct;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import research.loghunter.dto.SettingDto;
import research.loghunter.entity.Setting;
import research.loghunter.repository.SettingRepository;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class SettingService {

    private final SettingRepository settingRepository;

    // 기본 설정 키
    public static final String KEY_EXPORT_PATH = "export.path";
    public static final String KEY_RETENTION_DAYS = "retention.days";
    public static final String KEY_SERVER_PORT = "server.port";

    @PostConstruct
    @Transactional
    public void initDefaultSettings() {
        createIfNotExists(KEY_EXPORT_PATH, "./exports", "HTML/TXT 내보내기 경로");
        createIfNotExists(KEY_RETENTION_DAYS, "30", "로그 보관 기간 (일)");
        createIfNotExists(KEY_SERVER_PORT, "8080", "웹 서버 포트");
    }

    public List<SettingDto> findAll() {
        return settingRepository.findAll().stream()
                .map(this::toDto)
                .collect(Collectors.toList());
    }

    public Map<String, String> findAllAsMap() {
        return settingRepository.findAll().stream()
                .collect(Collectors.toMap(Setting::getKey, Setting::getValue));
    }

    public String getValue(String key) {
        return settingRepository.findById(key)
                .map(Setting::getValue)
                .orElse(null);
    }

    public String getValue(String key, String defaultValue) {
        return settingRepository.findById(key)
                .map(Setting::getValue)
                .orElse(defaultValue);
    }

    public Integer getIntValue(String key, Integer defaultValue) {
        String value = getValue(key);
        if (value == null) return defaultValue;
        try {
            return Integer.parseInt(value);
        } catch (NumberFormatException e) {
            return defaultValue;
        }
    }

    @Transactional
    public SettingDto save(SettingDto dto) {
        Setting setting = settingRepository.findById(dto.getKey())
                .orElse(new Setting());
        
        setting.setKey(dto.getKey());
        setting.setValue(dto.getValue());
        if (dto.getDescription() != null) {
            setting.setDescription(dto.getDescription());
        }

        return toDto(settingRepository.save(setting));
    }

    @Transactional
    public void saveAll(Map<String, String> settings) {
        settings.forEach((key, value) -> {
            Setting setting = settingRepository.findById(key)
                    .orElse(new Setting());
            setting.setKey(key);
            setting.setValue(value);
            settingRepository.save(setting);
        });
    }

    @Transactional
    public void delete(String key) {
        settingRepository.deleteById(key);
    }

    private void createIfNotExists(String key, String defaultValue, String description) {
        if (!settingRepository.existsById(key)) {
            Setting setting = Setting.builder()
                    .key(key)
                    .value(defaultValue)
                    .description(description)
                    .build();
            settingRepository.save(setting);
        }
    }

    private SettingDto toDto(Setting setting) {
        return SettingDto.builder()
                .key(setting.getKey())
                .value(setting.getValue())
                .description(setting.getDescription())
                .build();
    }
}
