package com.infoepoch.pms.agent.platform.agent.application;

import com.infoepoch.pms.agent.platform.agent.application.dto.AgentFieldResponse;
import com.infoepoch.pms.agent.platform.agent.application.dto.CreateAgentFieldRequest;
import com.infoepoch.pms.agent.platform.agent.application.dto.UpdateAgentFieldRequest;
import com.infoepoch.pms.agent.platform.agent.domain.Agent;
import com.infoepoch.pms.agent.platform.agent.domain.AgentField;
import com.infoepoch.pms.agent.platform.agent.domain.irepository.IAgentFieldRepository;
import com.infoepoch.pms.agent.platform.agent.domain.irepository.IAgentRepository;
import com.infoepoch.pms.agent.platform.shared.exception.BusinessException;
import com.infoepoch.pms.agent.platform.shared.response.ResultCode;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * 智能体字段管理服务。
 * <p>
 * 负责指定智能体下的字段 CRUD 操作，更新/删除时校验字段归属。
 * </p>
 */
@Service
@RequiredArgsConstructor
public class AgentFieldService {

    private final IAgentRepository agentRepository;
    private final IAgentFieldRepository fieldRepository;

    /**
     * 查询指定智能体的所有字段，按排序序号升序排列。
     *
     * @param agentId 智能体 ID
     * @return 字段响应列表
     * @throws BusinessException AGENT_NOT_FOUND 若智能体不存在
     */
    @Transactional(readOnly = true)
    public List<AgentFieldResponse> listByAgent(String agentId) {
        Agent agent = getAgentOrThrow(agentId);
        return fieldRepository.findAllByAgentIdOrderBySortOrderAsc(agentId)
                .stream()
                .peek(field -> field.setAgent(agent))
                .map(AgentFieldResponse::new)
                .toList();
    }

    /**
     * 在指定智能体下创建字段。
     *
     * @param agentId 智能体 ID
     * @param req     创建请求 DTO
     * @return 字段响应
     * @throws BusinessException AGENT_NOT_FOUND 若智能体不存在
     */
    @Transactional
    public AgentFieldResponse create(String agentId, CreateAgentFieldRequest req) {
        Agent agent = getAgentOrThrow(agentId);
        AgentField field = new AgentField(agent, req.getFieldName(), req.getFieldLabel(),
                req.getFieldType(), req.getDateFormat(), req.getEnumOptions(),
                req.getRequired(), req.getDescription(), req.getSortOrder());
        return new AgentFieldResponse(fieldRepository.save(field));
    }

    /**
     * 更新字段配置。
     *
     * @param agentId 智能体 ID（校验归属）
     * @param fieldId 字段 ID
     * @param req     更新请求 DTO
     * @return 更新后的字段响应
     * @throws BusinessException AGENT_FIELD_NOT_FOUND 若字段不存在或不属于该智能体
     */
    @Transactional
    public AgentFieldResponse update(String agentId, String fieldId, UpdateAgentFieldRequest req) {
        AgentField field = getFieldOrThrow(fieldId);
        if (!field.getAgentId().equals(agentId)) {
            throw new BusinessException(ResultCode.AGENT_FIELD_NOT_FOUND,
                    "字段 ID=" + fieldId + " 不属于智能体 ID=" + agentId);
        }
        field.modify(req.getFieldName(), req.getFieldLabel(), req.getFieldType(),
                req.getDateFormat(), req.getEnumOptions(), req.getRequired(),
                req.getDescription(), req.getSortOrder());
        return new AgentFieldResponse(fieldRepository.save(field));
    }

    /**
     * 删除字段。
     *
     * @param agentId 智能体 ID（校验归属）
     * @param fieldId 字段 ID
     * @throws BusinessException AGENT_FIELD_NOT_FOUND 若字段不存在或不属于该智能体
     */
    @Transactional
    public void delete(String agentId, String fieldId) {
        AgentField field = getFieldOrThrow(fieldId);
        if (!field.getAgentId().equals(agentId)) {
            throw new BusinessException(ResultCode.AGENT_FIELD_NOT_FOUND,
                    "字段 ID=" + fieldId + " 不属于智能体 ID=" + agentId);
        }
        fieldRepository.delete(field.getId());
    }

    /**
     * 查询智能体，不存在时抛出业务异常。
     *
     * @param agentId 智能体 ID
     * @return 智能体实体
     */
    private Agent getAgentOrThrow(String agentId) {
        return agentRepository.findById(agentId)
                .orElseThrow(() -> new BusinessException(ResultCode.AGENT_NOT_FOUND,
                        "智能体 ID=" + agentId + " 不存在"));
    }

    /**
     * 查询字段，不存在时抛出业务异常。
     *
     * @param fieldId 字段 ID
     * @return 字段实体
     */
    private AgentField getFieldOrThrow(String fieldId) {
        AgentField field = fieldRepository.findById(fieldId)
                .orElseThrow(() -> new BusinessException(ResultCode.AGENT_FIELD_NOT_FOUND,
                        "字段 ID=" + fieldId + " 不存在"));
        if (field.getAgentId() != null) {
            field.setAgent(getAgentOrThrow(field.getAgentId()));
        }
        return field;
    }
}
