package com.agent.management.repository.json;

import com.fasterxml.jackson.core.type.TypeReference;
import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Predicate;

/**
 * JSON 文件仓库基类
 *
 * 子类需：
 * 1. 实现 getFileName()、getEntityClass()、getId()/setId()
 * 2. 通过构造器注入 JsonStore
 *
 * ID 策略：自增，从所有记录的 maxId + 1 分配
 */
@Slf4j
public abstract class AbstractJsonRepository<T> {

    protected final JsonStore store;
    private final TypeReference<List<T>> typeRef;
    private AtomicLong nextId = new AtomicLong(1);

    protected AbstractJsonRepository(JsonStore store, TypeReference<List<T>> typeRef) {
        this.store = store;
        this.typeRef = typeRef;
    }

    /** 子类指定数据文件名，如 "ai-models.json" */
    protected abstract String getFileName();

    /** 子类提供从实体读取 ID 的方法 */
    protected abstract Long getId(T entity);

    /** 子类提供向实体写入 ID 的方法 */
    protected abstract void setId(T entity, Long id);

    @PostConstruct
    void initMaxId() {
        List<T> all = loadAll();
        long max = all.stream().mapToLong(e -> {
            Long id = getId(e);
            return id != null ? id : 0L;
        }).max().orElse(0L);
        nextId.set(max + 1);
        log.info("[{}] 初始化完成，当前记录数={}，下一ID={}", getFileName(), all.size(), max + 1);
    }

    // ==================== 基础读写 ====================

    protected List<T> loadAll() {
        return store.loadAll(getFileName(), typeRef);
    }

    protected void writeAll(List<T> data) {
        store.saveAll(getFileName(), data);
    }

    // ==================== CRUD ====================

    public List<T> findAll() {
        return loadAll();
    }

    public Optional<T> findById(Long id) {
        return loadAll().stream().filter(e -> id.equals(getId(e))).findFirst();
    }

    public List<T> findAll(Predicate<T> filter) {
        List<T> result = new ArrayList<>();
        for (T e : loadAll()) {
            if (filter.test(e)) result.add(e);
        }
        return result;
    }

    /**
     * 保存（新增或更新）
     */
    public T save(T entity) {
        List<T> all = loadAll();
        Long id = getId(entity);
        if (id == null) {
            // 新增：分配新 ID
            id = nextId.getAndIncrement();
            setId(entity, id);
            all.add(entity);
        } else {
            // 更新：找到同 ID 替换
            boolean found = false;
            for (int i = 0; i < all.size(); i++) {
                if (id.equals(getId(all.get(i)))) {
                    all.set(i, entity);
                    found = true;
                    break;
                }
            }
            if (!found) {
                all.add(entity);
            }
        }
        writeAll(all);
        return entity;
    }

    public List<T> saveAll(Iterable<T> entities) {
        List<T> all = loadAll();
        for (T entity : entities) {
            Long id = getId(entity);
            if (id == null) {
                id = nextId.getAndIncrement();
                setId(entity, id);
                all.add(entity);
            } else {
                boolean found = false;
                for (int i = 0; i < all.size(); i++) {
                    if (id.equals(getId(all.get(i)))) {
                        all.set(i, entity);
                        found = true;
                        break;
                    }
                }
                if (!found) {
                    all.add(entity);
                }
            }
        }
        writeAll(all);
        List<T> saved = new ArrayList<>();
        entities.forEach(saved::add);
        return saved;
    }

    public void deleteById(Long id) {
        List<T> all = loadAll();
        boolean removed = all.removeIf(e -> id.equals(getId(e)));
        if (removed) {
            writeAll(all);
        }
    }

    public void deleteAll(Predicate<T> filter) {
        List<T> all = loadAll();
        boolean removed = all.removeIf(filter);
        if (removed) {
            writeAll(all);
        }
    }

    /** 批量删除指定的实体集合 */
    public void deleteAll(Iterable<T> entities) {
        List<T> all = loadAll();
        java.util.Set<Long> idsToRemove = new java.util.HashSet<>();
        for (T e : entities) {
            Long id = getId(e);
            if (id != null) idsToRemove.add(id);
        }
        boolean removed = all.removeIf(e -> idsToRemove.contains(getId(e)));
        if (removed) {
            writeAll(all);
        }
    }

    public boolean existsById(Long id) {
        return findById(id).isPresent();
    }

    public long count() {
        return loadAll().size();
    }
}
