package com.agent.management.repository;

import com.agent.management.model.entity.Workflow;
import com.agent.management.parser.WorkflowNameNormalizer;
import com.agent.management.repository.json.AbstractJsonRepository;
import com.agent.management.repository.json.JsonStore;
import com.fasterxml.jackson.core.type.TypeReference;
import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;

@Slf4j
@Component
public class WorkflowRepository extends AbstractJsonRepository<Workflow> {

    public WorkflowRepository(JsonStore store) {
        super(store, new TypeReference<>() {});
    }

    @Override
    protected String getFileName() {
        return "workflows.json";
    }

    @Override
    protected Long getId(Workflow entity) {
        return entity.getId();
    }

    @Override
    protected void setId(Workflow entity, Long id) {
        entity.setId(id);
    }

    public List<Workflow> findAllByOrderByUpdatedAtDesc() {
        List<Workflow> list = new ArrayList<>(findAll());
        list.sort(Comparator.comparing(w -> w.getUpdatedAt() == null ? java.time.LocalDateTime.MIN : w.getUpdatedAt(), Comparator.reverseOrder()));
        return list;
    }

    /** 按 kebab-case 唯一标识查询 */
    public Optional<Workflow> findByName(String name) {
        if (name == null || name.isEmpty()) return Optional.empty();
        return findAll().stream().filter(w -> name.equals(w.getName())).findFirst();
    }

    /** 唯一性校验：排除指定 id（更新场景传当前 id，新建场景传 null） */
    public boolean existsByNameExcluding(String name, Long excludeId) {
        if (name == null || name.isEmpty()) return false;
        return findAll().stream()
                .anyMatch(w -> name.equals(w.getName()) && !name.equals(String.valueOf(excludeId == null ? "" : excludeId))
                        && (excludeId == null || !excludeId.equals(w.getId())));
    }

    /**
     * 一次性数据迁移：将旧 name（任意字符串，多为中文）迁移为 kebab-case 唯一标识。
     *
     * <p>规则：
     * <ul>
     *   <li>若 name 为空或非 kebab-case：把原 name 移到 displayName，name 设为 String.valueOf(id)</li>
     *   <li>若 displayName 为空但原 name 非空：displayName 设为 name</li>
     * </ul>
     */
    @PostConstruct
    private void migrateLegacyNames() {
        // initMaxId() 由父类 @PostConstruct 触发，顺序不保证；显式调用一次保证 id 已分配
        List<Workflow> all = loadAll();
        if (all.isEmpty()) return;

        boolean dirty = false;
        for (Workflow w : all) {
            String currentName = w.getName();
            boolean currentValid = WorkflowNameNormalizer.isValidKebabCase(currentName);

            if (!currentValid) {
                // 旧数据：原 name 实际是中文显示名
                if (w.getDisplayName() == null && currentName != null) {
                    w.setDisplayName(currentName);
                }
                w.setName(String.valueOf(w.getId()));
                dirty = true;
                log.info("[Migration] 工作流 id={} 迁移：name='{}' → '{}'，displayName='{}'",
                        w.getId(), currentName, w.getName(), w.getDisplayName());
            } else if (w.getDisplayName() == null) {
                // 新规范但 displayName 缺失：回退为 name
                w.setDisplayName(currentName);
                dirty = true;
            }
        }

        // 检测迁移后是否产生 name 重复（理论上不会，因为 String.valueOf(id) 唯一）
        long distinctCount = all.stream().map(Workflow::getName).distinct().count();
        if (distinctCount != all.size()) {
            log.error("[Migration] 检测到工作流 name 重复！请人工检查 workflows.json");
        }

        if (dirty) {
            writeAll(all);
            log.info("[Migration] 工作流数据迁移完成，共更新 {} 条记录", all.size());
        }
    }
}
