package com.dne.ems.repository.impl;

import com.dne.ems.model.PollutantThreshold;
import com.dne.ems.repository.PollutantThresholdRepository;
import com.dne.ems.service.JsonStorageService;
import com.fasterxml.jackson.core.type.TypeReference;
import jakarta.annotation.PostConstruct;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Repository;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;

@Repository
@Primary
public class JsonPollutantThresholdRepositoryImpl implements PollutantThresholdRepository {

    private static final String FILE_NAME = "pollutant_thresholds.json";
    private final JsonStorageService jsonStorageService;
    private final List<PollutantThreshold> cache = new ArrayList<>();
    private final AtomicLong idCounter = new AtomicLong(0);

    public JsonPollutantThresholdRepositoryImpl(JsonStorageService jsonStorageService) {
        this.jsonStorageService = jsonStorageService;
    }

    @PostConstruct
    public void init() {
        List<PollutantThreshold> data = jsonStorageService.readData(FILE_NAME, new TypeReference<>() {});
        synchronized (cache) {
            cache.addAll(data);
            long maxId = data.stream()
                              .mapToLong(PollutantThreshold::getId)
                              .max()
                              .orElse(0L);
            idCounter.set(maxId);
        }
    }

    @Override
    public PollutantThreshold save(PollutantThreshold threshold) {
        synchronized (cache) {
            // Since there's no unique constraint on pollutantName in the model,
            // we'll just add/update based on ID. A more robust implementation
            // might enforce the name uniqueness here.
            if (threshold.getId() == null) {
                threshold.setId(idCounter.incrementAndGet());
                cache.add(threshold);
            } else {
                cache.removeIf(t -> t.getId().equals(threshold.getId()));
                cache.add(threshold);
            }
            jsonStorageService.writeData(FILE_NAME, cache);
            return threshold;
        }
    }

    @Override
    public List<PollutantThreshold> saveAll(Iterable<PollutantThreshold> thresholds) {
        synchronized (cache) {
            List<PollutantThreshold> savedThresholds = StreamSupport.stream(thresholds.spliterator(), false)
                .map(this::save)
                .collect(Collectors.toList());
            // 'save' already writes, but a single write after all operations would be more efficient.
            // For simplicity, we reuse the single save logic.
            return savedThresholds;
        }
    }

    @Override
    public List<PollutantThreshold> findAll() {
        synchronized (cache) {
            return new ArrayList<>(cache);
        }
    }

    @Override
    public Optional<PollutantThreshold> findByPollutantName(String pollutantName) {
        synchronized (cache) {
            return cache.stream()
                .filter(t -> t.getPollutantName() != null && t.getPollutantName().equalsIgnoreCase(pollutantName))
                .findFirst();
        }
    }
} 