package com.aegis.emergency.report.service.impl;

import com.aegis.common.exception.ServiceException;
import com.aegis.common.utils.SecurityUtils;
import com.aegis.common.utils.StringUtils;
import com.aegis.emergency.event.domain.Event;
import com.aegis.emergency.event.service.IEventService;
import com.aegis.emergency.report.domain.ProvinceReport;
import com.aegis.emergency.report.domain.ReportTemplate;
import com.aegis.emergency.report.dto.ProvinceReportRequest;
import com.aegis.emergency.report.mapper.ProvinceReportMapper;
import com.aegis.emergency.report.service.IProvinceReportService;
import com.aegis.emergency.report.service.IReportTemplateService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 省厅上报记录 Service 实现
 * 
 * @author aegis
 */
@Service
public class ProvinceReportServiceImpl extends ServiceImpl<ProvinceReportMapper, ProvinceReport>
        implements IProvinceReportService {

    @Autowired
    private IEventService eventService;

    @Autowired
    private IReportTemplateService reportTemplateService;

    @Override
    public List<ProvinceReport> listReports(ProvinceReport condition) {
        // 1. 使用 LambdaQueryWrapper 查询基础数据
        LambdaQueryWrapper<ProvinceReport> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ProvinceReport::getDelFlag, "0");
        
        if (condition != null) {
            wrapper.eq(condition.getEventId() != null, 
                ProvinceReport::getEventId, condition.getEventId());
            wrapper.eq(StringUtils.isNotBlank(condition.getStatus()), 
                ProvinceReport::getStatus, condition.getStatus());
            // 不暴露 reportType 作为查询条件
            
            // 时间范围查询
            if (condition.getBeginCreateTime() != null && condition.getEndCreateTime() != null) {
                wrapper.between(ProvinceReport::getCreateTime, 
                    condition.getBeginCreateTime(), condition.getEndCreateTime());
            }
        }
        
        wrapper.orderByDesc(ProvinceReport::getCreateTime);
        List<ProvinceReport> reports = this.list(wrapper);
        
        // 2. 如果查询条件包含 eventNo，需要先查询事件ID
        if (condition != null && StringUtils.isNotBlank(condition.getEventNo())) {
            // 使用 overridden 方法而不是 raw list()
            Event eventCondition = new Event();
            eventCondition.setEventNo(condition.getEventNo());
            List<Event> events = eventService.listByCondition(eventCondition);
            List<Long> eventIds = events.stream()
                .map(Event::getId)
                .collect(Collectors.toList());
            
            if (eventIds.isEmpty()) {
                return java.util.Collections.emptyList();
            }
            
            // 重新查询，只包含匹配的事件ID
            wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(ProvinceReport::getDelFlag, "0")
                .in(ProvinceReport::getEventId, eventIds);
            if (StringUtils.isNotBlank(condition.getStatus())) {
                wrapper.eq(ProvinceReport::getStatus, condition.getStatus());
            }
            wrapper.orderByDesc(ProvinceReport::getCreateTime);
            reports = this.list(wrapper);
        }
        
        // 3. 关联查询，填充关联字段
        enrichReports(reports);
        
        return reports;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ProvinceReport submit(ProvinceReportRequest request) {
        // 1. 校验事件是否可以上报
        String error = validateEventReportable(request.getEventId());
        if (error != null) {
            throw new ServiceException(error);
        }

        // 2. 校验模板是否存在
        ReportTemplate template = reportTemplateService.getById(request.getTemplateId());
        if (template == null) {
            throw new ServiceException("模板不存在或已删除");
        }

        // 3. 判断上报类型和序号（使用 MyBatis-Plus 的 count）
        LambdaQueryWrapper<ProvinceReport> countWrapper = new LambdaQueryWrapper<>();
        countWrapper.eq(ProvinceReport::getEventId, request.getEventId())
            .eq(ProvinceReport::getDelFlag, "0");
        long existingCount = this.count(countWrapper);
        
        String reportType = existingCount == 0 ? "initial" : "followup";
        int sequence = (int)existingCount + 1;

        // 4. 创建上报记录
        ProvinceReport report = new ProvinceReport();
        report.setEventId(request.getEventId());
        report.setTemplateId(request.getTemplateId());
        report.setReportType(reportType);
        report.setReportSequence(sequence);
        report.setFields(request.getFields());
        report.setStatus("submitting"); // 直接设置为提交中
        report.setRetryCount(0);
        report.setRemark(request.getRemark());
        report.setDelFlag("0");
        
        // Set audit fields (createBy, createTime, updateBy, updateTime)
        String operator = SecurityUtils.getUsername();
        Date now = new Date();
        report.setCreateBy(operator);
        report.setCreateTime(now);
        report.setUpdateBy(operator);
        report.setUpdateTime(now);

        this.save(report);

        // 5. 立即提交到省厅接口
        try {
            // TODO: 调用省厅接口
            // ProvinceReportClient client = provinceReportClient;
            // Map<String, Object> provinceRequest = buildRequest(report);
            // Map<String, Object> response = client.submit(provinceRequest);
            
            report.setStatus("success");
            report.setRequestPayload(null); // TODO: 设置实际请求数据
            report.setResponsePayload(null); // TODO: 设置实际响应数据
            report.setErrorMessage(null);
        } catch (Exception e) {
            report.setStatus("failed");
            report.setErrorMessage(e.getMessage());
            report.setRetryCount(report.getRetryCount() + 1);
            report.setLastRetryTime(new Date());
        }

        this.updateById(report);
        return report;
    }

    @Override
    public ProvinceReport getById(Serializable id) {
        LambdaQueryWrapper<ProvinceReport> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ProvinceReport::getId, id)
            .eq(ProvinceReport::getDelFlag, "0");
        return this.getOne(wrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean save(ProvinceReport entity) {
        if (entity == null) {
            return false;
        }
        if (StringUtils.isBlank(entity.getDelFlag())) {
            entity.setDelFlag("0");
        }
        // Set audit fields if not already set
        if (entity.getCreateTime() == null) {
            String operator = SecurityUtils.getUsername();
            Date now = new Date();
            if (StringUtils.isBlank(entity.getCreateBy())) {
                entity.setCreateBy(operator);
            }
            entity.setCreateTime(now);
            if (StringUtils.isBlank(entity.getUpdateBy())) {
                entity.setUpdateBy(operator);
            }
            entity.setUpdateTime(now);
        }
        return super.save(entity);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateById(ProvinceReport entity) {
        if (entity == null || entity.getId() == null) {
            return false;
        }
        // Set update audit fields
        String operator = SecurityUtils.getUsername();
        entity.setUpdateBy(operator);
        entity.setUpdateTime(new Date());
        return super.updateById(entity);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @SuppressWarnings("unchecked")
    public boolean removeByIds(Collection<?> idList) {
        if (idList == null || idList.isEmpty()) {
            return false;
        }
        List<ProvinceReport> reports = super.listByIds((Collection<? extends Serializable>) idList);
        reports.forEach(r -> r.setDelFlag("2"));
        return this.updateBatchById(reports);
    }

    /**
     * 关联查询，填充事件和模板信息
     */
    private void enrichReports(List<ProvinceReport> reports) {
        if (reports == null || reports.isEmpty()) {
            return;
        }
        
        // 收集所有需要查询的ID
        List<Long> eventIds = reports.stream()
            .map(ProvinceReport::getEventId)
            .distinct()
            .collect(Collectors.toList());
        List<Long> templateIds = reports.stream()
            .map(ProvinceReport::getTemplateId)
            .distinct()
            .collect(Collectors.toList());
        
        // 批量查询事件
        Map<Long, Event> eventMap = eventService.listByIds(eventIds).stream()
            .collect(Collectors.toMap(Event::getId, e -> e));
        
        // 批量查询模板
        Map<Long, ReportTemplate> templateMap = reportTemplateService.listByIds(templateIds).stream()
            .collect(Collectors.toMap(ReportTemplate::getId, t -> t));
        
        // 填充关联字段
        reports.forEach(report -> {
            Event event = eventMap.get(report.getEventId());
            if (event != null) {
                report.setEventNo(event.getEventNo());
                report.setEventTitle(event.getTitle());
                report.setEventLevel(event.getLevel());
            }
            
            ReportTemplate template = templateMap.get(report.getTemplateId());
            if (template != null) {
                report.setTemplateName(template.getName());
            }
        });
    }

    /**
     * 检查事件是否可以上报（内部方法）
     * 
     * @param eventId 事件ID
     * @return 错误信息，null表示可以上报
     */
    private String validateEventReportable(Long eventId) {
        Event event = eventService.getById(eventId);
        if (event == null) {
            return "事件不存在或已删除";
        }

        // 草稿状态不能上报
        if ("draft".equals(event.getStatus())) {
            return "草稿状态的事件不能上报";
        }

        return null; // 可以上报
    }
}