package com.sino.mci.flow.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.sino.mci.exception.BusinessException;
import com.sino.mci.flow.dto.CreateFlowRequest;
import com.sino.mci.flow.entity.FlowDefinition;
import com.sino.mci.flow.repository.FlowDefinitionMapper;
import com.sino.mci.shared.util.JsonUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
@RequiredArgsConstructor
public class FlowDefinitionService {

    private final FlowDefinitionMapper flowDefinitionMapper;

    @Transactional
    public FlowDefinition createFlow(String tenantCode, CreateFlowRequest request) {
        FlowDefinition existing = flowDefinitionMapper.selectOne(
                new LambdaQueryWrapper<FlowDefinition>()
                        .eq(FlowDefinition::getTenantCode, tenantCode)
                        .eq(FlowDefinition::getFlowCode, request.getFlowCode()));
        if (existing != null) {
            throw new BusinessException("流程编码已存在: " + request.getFlowCode());
        }

        FlowDefinition flow = new FlowDefinition();
        flow.setTenantCode(tenantCode);
        flow.setFlowCode(request.getFlowCode());
        flow.setFlowName(request.getFlowName());
        flow.setFlowType(parseFlowType(request.getFlowType()));
        flow.setDefinitionJson(JsonUtils.toJson(request.getDefinitionJson()));
        flow.setStatus(0);
        flowDefinitionMapper.insert(flow);
        return flow;
    }

    public FlowDefinition getFlow(String tenantCode, String flowCode) {
        FlowDefinition flow = flowDefinitionMapper.selectOne(
                new LambdaQueryWrapper<FlowDefinition>()
                        .eq(FlowDefinition::getTenantCode, tenantCode)
                        .eq(FlowDefinition::getFlowCode, flowCode));
        if (flow == null) {
            throw new BusinessException("流程不存在: " + flowCode);
        }
        return flow;
    }

    public List<FlowDefinition> listFlows(String tenantCode) {
        return flowDefinitionMapper.selectList(
                new LambdaQueryWrapper<FlowDefinition>()
                        .eq(FlowDefinition::getTenantCode, tenantCode)
                        .eq(FlowDefinition::getDeleted, 0)
                        .orderByDesc(FlowDefinition::getCreateTime));
    }

    public List<FlowDefinition> listFlowsByType(String tenantCode, Integer flowType) {
        return flowDefinitionMapper.selectList(
                new LambdaQueryWrapper<FlowDefinition>()
                        .eq(FlowDefinition::getTenantCode, tenantCode)
                        .eq(FlowDefinition::getFlowType, flowType)
                        .eq(FlowDefinition::getDeleted, 0)
                        .orderByDesc(FlowDefinition::getCreateTime));
    }

    @Transactional
    public FlowDefinition updateFlow(String tenantCode, String flowCode, CreateFlowRequest request) {
        FlowDefinition flow = getFlow(tenantCode, flowCode);
        flow.setFlowName(request.getFlowName());
        flow.setFlowType(parseFlowType(request.getFlowType()));
        flow.setDefinitionJson(JsonUtils.toJson(request.getDefinitionJson()));
        flowDefinitionMapper.updateById(flow);
        return flow;
    }

    @Transactional
    public void publishFlow(String tenantCode, String flowCode) {
        FlowDefinition flow = getFlow(tenantCode, flowCode);
        flow.setStatus(1);
        flowDefinitionMapper.updateById(flow);
    }

    @Transactional
    public void offlineFlow(String tenantCode, String flowCode) {
        FlowDefinition flow = getFlow(tenantCode, flowCode);
        flow.setStatus(2);
        flowDefinitionMapper.updateById(flow);
    }

    @Transactional
    public void deleteFlow(String tenantCode, String flowCode) {
        FlowDefinition flow = getFlow(tenantCode, flowCode);
        flowDefinitionMapper.deleteById(flow.getId());
    }

    private Integer parseFlowType(String flowType) {
        if (flowType == null || flowType.isBlank()) {
            return 1;
        }
        String normalized = flowType.trim().toLowerCase();
        return switch (normalized) {
            case "inbound", "1" -> 1;
            case "ivr", "2" -> 2;
            default -> 1;
        };
    }
}
