package com.fs.audit.service.impl;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.fs.audit.chain.AuditChainBuilder;
import com.fs.audit.chain.AuditContext;
import com.fs.audit.chain.AuditResult;
import com.fs.audit.domain.Audit;
import com.fs.audit.domain.AuditFlow;
import com.fs.audit.domain.AuditTemp;
import com.fs.audit.dto.*;
import com.fs.audit.enums.AuditAction;
import com.fs.audit.enums.AuditStatus;
import com.fs.audit.event.AuditCreatedEvent;
import com.fs.audit.exception.BusinessException;
import com.fs.audit.mapper.AuditFlowMapper;
import com.fs.audit.mapper.AuditMapper;
import com.fs.audit.service.AuditService;
import com.fs.audit.service.AuditTempService;
import com.fs.audit.utils.AuditFlowUtils;
import com.fs.audit.vo.AuditDetailVO;
import com.fs.audit.vo.AuditFlowDetailVO;
import com.fs.audit.vo.QueryPendingAuditVO;
import com.fs.common.BeanCopyUtils;
import com.fs.common.core.domain.entity.SysUser;
import com.fs.common.utils.StringUtils;
import com.fs.company.cache.CompanyUserCacheService;
import com.fs.company.domain.Company;
import com.fs.company.domain.CompanyUser;
import com.fs.company.service.ICompanyService;
import com.fs.company.service.ICompanyUserService;
import com.fs.doctor.domain.Doctor;
import com.fs.doctor.service.IDoctorService;
import com.fs.task.domain.TaskInfo;
import com.fs.task.service.ITaskInfoService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.util.Asserts;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 审核服务实现
 */
@Slf4j
@Service
public class AuditServiceImpl implements AuditService {

    private final AuditMapper auditMapper;
    private final AuditFlowMapper auditFlowMapper;
    private final AuditTempService auditTempService;
    private final AuditChainBuilder auditChainBuilder;
    private final ApplicationEventPublisher eventPublisher;
    private final ICompanyUserService companyUserService;
    private final ITaskInfoService taskInfoService;



    public AuditServiceImpl(
            AuditMapper auditMapper,
            AuditFlowMapper auditFlowMapper,
            AuditTempService auditTempService,
            AuditChainBuilder auditChainBuilder,
            ApplicationEventPublisher eventPublisher,
            ICompanyUserService companyUserService,
            @Lazy ITaskInfoService taskInfoService, @Lazy IDoctorService doctorService) {
        this.auditMapper = auditMapper;
        this.auditFlowMapper = auditFlowMapper;
        this.auditTempService = auditTempService;
        this.auditChainBuilder = auditChainBuilder;
        this.eventPublisher = eventPublisher;
        this.companyUserService = companyUserService;
        this.taskInfoService = taskInfoService;
    }

    @Override
    public List<CustomerServicePendingAuditDTO> getPendingAuditsByCustomerServiceId(QueryPendingAuditVO param) {
        List<Audit> audits = auditMapper.selectPendingAuditsByUserId(param);

        return audits.stream()
                .map(audit -> {
                    CustomerServicePendingAuditDTO dto = new CustomerServicePendingAuditDTO();
                    dto.setId(audit.getId());
                    dto.setAuditName(audit.getAuditName());
                    dto.setAuditType(audit.getAuditType());
                    dto.setBusinessId(audit.getBusinessId());
                    dto.setBusinessType(audit.getBusinessType());
                    dto.setCurrentStep(audit.getCurrentStep());
                    dto.setStatus(audit.getStatus());
                    dto.setInitiatorId(audit.getInitiatorId());
                    dto.setCreateTime(audit.getCreateTime());

                    // 解析审核人ID列表
                    List<Long> auditUserIds = JSON.parseArray(audit.getAuditUserIds(), Long.class);
                    List<String> auditStr = new ArrayList<>();
                    for (Long auditUserId : auditUserIds) {
                        String companyUserNameById = CompanyUserCacheService.getCompanyUserNameById(auditUserId);
                        if(StringUtils.isNotBlank(companyUserNameById)){
                            auditStr.add(companyUserNameById);
                        }
                    }
                    dto.setAuditUserIds(auditUserIds);
                    dto.setAuditUserIdsStr(auditStr);
                    dto.setInitiatorName(CompanyUserCacheService.getCompanyUserNameById(audit.getInitiatorId()));

                    // 如果审核类型是ADUIT_CJRW或ADUIT_WCRWSH，查询业务数据
                    if ("ADUIT_CJRW".equals(audit.getAuditType()) || "ADUIT_WCRWSH".equals(audit.getAuditType())) {
                        try {
                            TaskInfo taskInfo = taskInfoService.selectTaskInfoById(audit.getBusinessId());
                            if (taskInfo != null) {
                                Map<String, Object> businessData = new HashMap<>();
                                businessData.put("taskInfo", taskInfo);
                                dto.setBusinessData(businessData);
                            }
                        } catch (Exception e) {
                            log.error("查询任务信息失败，businessId: {}", audit.getBusinessId(), e);
                        }
                    }

                    return dto;
                })
                .collect(Collectors.toList());
    }

    @Override
    public List<CustomerServicePendingAuditDTO> getPendingTaskAuditsByCustomerServiceId(QueryPendingAuditVO param) {
        List<Audit> audits = auditMapper.selectPendingAuditsByUserId(param);

        return audits.stream()
                .map(audit -> {
                    CustomerServicePendingAuditDTO dto = new CustomerServicePendingAuditDTO();
                    dto.setId(audit.getId());
                    dto.setAuditName(audit.getAuditName());
                    dto.setAuditType(audit.getAuditType());
                    dto.setBusinessId(audit.getBusinessId());
                    dto.setBusinessType(audit.getBusinessType());
                    dto.setCurrentStep(audit.getCurrentStep());
                    dto.setStatus(audit.getStatus());
                    dto.setInitiatorId(audit.getInitiatorId());
                    dto.setCreateTime(audit.getCreateTime());

                    // 解析审核人ID列表
                    List<Long> auditUserIds = JSON.parseArray(audit.getAuditUserIds(), Long.class);
                    List<String> auditStr = new ArrayList<>();
                    for (Long auditUserId : auditUserIds) {
                        String companyUserNameById = CompanyUserCacheService.getCompanyUserNameById(auditUserId);
                        if(StringUtils.isNotBlank(companyUserNameById)){
                            auditStr.add(companyUserNameById);
                        }
                    }
                    dto.setAuditUserIds(auditUserIds);
                    dto.setAuditUserIdsStr(auditStr);
                    dto.setInitiatorName(CompanyUserCacheService.getCompanyUserNameById(audit.getInitiatorId()));

                    // 如果审核类型是ADUIT_CJRW或ADUIT_WCRWSH，查询业务数据
                    if ("ADUIT_CJRW".equals(audit.getAuditType()) || "ADUIT_WCRWSH".equals(audit.getAuditType())) {
                        try {
                            TaskInfo taskInfo = taskInfoService.selectTaskInfoById(audit.getBusinessId());
                            if (taskInfo != null) {
                                Map<String, Object> businessData = new HashMap<>();
                                businessData.put("taskInfo", taskInfo);
                                dto.setBusinessData(businessData);
                            }
                        } catch (Exception e) {
                            log.error("查询任务信息失败，businessId: {}", audit.getBusinessId(), e);
                        }
                    }

                    return dto;
                })
                .collect(Collectors.toList());
    }

    @Override
    public Long getPendingAuditsCount(QueryPendingAuditVO param) {
        Long count = auditMapper.selectPendingAuditsByUserIdCount(param);

        return count;
    }

    @Override
    @Transactional
    public Long createAudit(CreateAuditRequestDTO request) {
        // 获取模板
        AuditTemp template = null;
        if(ObjectUtils.isNotNull(request.getTempId())){
            template = auditTempService.getTemplate(request.getTempId());
        } else if(ObjectUtils.isNotNull(request.getTempCode()) && ObjectUtils.isNotNull(request.getCompanyId())){
            template = auditTempService.getTemplate(request.getTempCode(), request.getCompanyId());
        } else {
            throw new IllegalArgumentException("模板ID或模板代码必填!");
        }

        TemplateConfigDTO config = auditTempService.parseTemplateConfig(template.getTempJson());

        // 获取第一步配置
        TemplateStepDTO firstStep = config.getSteps().get(0);

        // 创建审核实例
        Audit audit = new Audit();
        audit.setBusinessId(request.getBusinessId());
        audit.setBusinessType(request.getBusinessType());
        audit.setTempId(template.getId());
        audit.setCurrentStep(1);
        audit.setAuditUserIds(JSON.toJSONString(firstStep.getAuditUserIds()));
        audit.setStatus(AuditStatus.PENDING.getCode());
        audit.setInitiatorId(request.getInitiatorId());
        audit.setCompanyId(request.getCompanyId());
        audit.setAuditName(template.getTempName());
        audit.setAuditType(template.getTempCode());
        audit.setTempCode(template.getTempCode());
        audit.setCreateTime(LocalDateTime.now());
        audit.setUpdateTime(LocalDateTime.now());
        auditMapper.insert(audit);

        // 创建第一步流程记录
        AuditFlow firstFlow = new AuditFlow();
        firstFlow.setAuditId(audit.getId());
        firstFlow.setStepNumber(1);
        firstFlow.setStepDescription(firstStep.getDescription());
        firstFlow.setAuditUserIds(JSON.toJSONString(firstStep.getAuditUserIds()));
        firstFlow.setStatus(AuditStatus.PENDING.getCode());
        firstFlow.setCompanyId(request.getCompanyId());
        firstFlow.setCreateTime(LocalDateTime.now());
        firstFlow.setUpdateTime(LocalDateTime.now());
        auditFlowMapper.insert(firstFlow);

        log.info("创建审核实例成功，ID: {}, 业务ID: {}", audit.getId(), request.getBusinessId());

        // 发布审核创建事件
        eventPublisher.publishEvent(new AuditCreatedEvent(this, audit, firstFlow));

        return audit.getId();
    }

    @Override
    @Transactional
    public AuditResult doAudit(AuditRequestDTO request) {
        // 获取审核实例
        Audit audit = getAudit(request.getAuditId());

        // 获取模板配置
        AuditTemp template = auditTempService.getTemplate(audit.getTempId());
        TemplateConfigDTO config = auditTempService.parseTemplateConfig(template.getTempJson());

        // 获取当前步骤流程记录
        AuditFlow currentFlow = auditFlowMapper.selectCurrentFlow(
                audit.getId(), audit.getCurrentStep());

        if (currentFlow == null) {
            throw new BusinessException("当前步骤流程记录不存在");
        }

        // 构建审核上下文
        AuditContext context = new AuditContext();
        context.setAudit(audit);
        context.setCurrentFlow(currentFlow);
        context.setSteps(config.getSteps());
        context.setCurrentStepIndex(audit.getCurrentStep() - 1); // 转为0-based索引
        context.setUserId(request.getUserId());
        context.setApproved(AuditAction.APPROVE.getCode().equals(request.getAction()));
        context.setComment(request.getComment());
        context.setCompanyId(request.getCompanyId());
        context.setUserType(request.getUserType());
        // 执行责任链
        AuditResult result = auditChainBuilder.execute(context);


//
        log.info("审核执行完成，审核ID: {}, 结果: {}", request.getAuditId(), result.getMessage());




        return result;
    }

    @Override
    public Audit getAudit(Long auditId) {
        Audit audit = auditMapper.selectById(auditId);
        if (audit == null) {
            throw new BusinessException("审核实例不存在: " + auditId);
        }
        return audit;
    }

    @Override
    public Audit getAuditByBusinessId(String businessId, String businessType) {
        LambdaQueryWrapper<Audit> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Audit::getBusinessId, businessId)
               .eq(Audit::getBusinessType, businessType);
        return auditMapper.selectOne(wrapper);
    }

    @Override
    public List<AuditFlow> getAuditFlows(Long auditId) {
        Audit audit = auditMapper.selectById(auditId);

        Asserts.notNull(audit,String.format("审核实例 %d 不存在！",auditId));


        List<AuditFlow> allFlows = new ArrayList<>();

        AuditFlow firstFlow = new AuditFlow();
        firstFlow.setAuditId(audit.getId());
        firstFlow.setStepNumber(0);
        firstFlow.setStepDescription("申请人");
        firstFlow.setStatus(0);
        firstFlow.setCompanyId(audit.getCompanyId());
        firstFlow.setCreateTime(audit.getCreateTime()); // 使用审核实例的创建时间
        firstFlow.setUpdateTime(audit.getCreateTime());
        firstFlow.setAuditUserIds(String.format("[%d]",audit.getInitiatorId()));
        // 设置申请人用户类型：0-销售/公司用户（默认）
        // 医生审核通常由公司用户发起
        firstFlow.setAuditUserType(0);
        allFlows.add(firstFlow);

        List<AuditFlow> auditFlows = auditFlowMapper.selectByAuditId(auditId);
        allFlows.addAll(auditFlows);
        return allFlows;
    }

    @Override
    public List<Audit> getPendingAuditsByUserId(Long userId) {
        // 查询待审核的实例
        LambdaQueryWrapper<Audit> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Audit::getStatus, AuditStatus.PENDING.getCode());

        List<Audit> allPending = auditMapper.selectList(wrapper);

        // 过滤当前用户是审核人的
        return allPending.stream()
                .filter(audit -> {
                    List<Long> auditUserIds = JSON.parseArray(
                            audit.getAuditUserIds(), Long.class);
                    return auditUserIds != null && auditUserIds.contains(userId);
                })
                .collect(Collectors.toList());
    }

    @Override
    public List<Audit> getMyInitiatedAudits(Long userId) {
        LambdaQueryWrapper<Audit> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Audit::getInitiatorId, userId)
               .orderByDesc(Audit::getCreateTime);
        return auditMapper.selectList(wrapper);
    }

    @Override
    public AuditDetailVO<?> getAuditDetail(Long auditId) {
        return null;
    }
}

