package com.aucma.production.service.impl;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import com.aucma.common.exception.ServiceException;
import com.aucma.common.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionTemplate;
import com.aucma.production.mapper.MrpComponentWeeklyReqMapper;
import com.aucma.production.mapper.MrpProdWeeklyPlanMapper;
import com.aucma.production.domain.MrpComponentWeeklyReq;
import com.aucma.production.domain.MrpProdWeeklyPlan;
import com.aucma.production.service.IMrpComponentWeeklyReqService;
import java.math.BigDecimal;

/**
 * 子件物料周需求Service业务层处理
 * 
 * @author Yinq
 * @date 2026-01-05
 */
@Service
public class MrpComponentWeeklyReqServiceImpl implements IMrpComponentWeeklyReqService 
{
    @Autowired
    private MrpComponentWeeklyReqMapper mrpComponentWeeklyReqMapper;
    
    @Autowired
    private MrpProdWeeklyPlanMapper mrpProdWeeklyPlanMapper;
    
    @Autowired
    private TransactionTemplate transactionTemplate;

    /**
     * 查询子件物料周需求
     * 
     * @param id 子件物料周需求主键
     * @return 子件物料周需求
     */
    @Override
    public MrpComponentWeeklyReq selectMrpComponentWeeklyReqById(Long id)
    {
        return mrpComponentWeeklyReqMapper.selectMrpComponentWeeklyReqById(id);
    }

    /**
     * 查询子件物料周需求列表
     * 
     * @param mrpComponentWeeklyReq 子件物料周需求
     * @return 子件物料周需求
     */
    @Override
    public List<MrpComponentWeeklyReq> selectMrpComponentWeeklyReqList(MrpComponentWeeklyReq mrpComponentWeeklyReq)
    {
        return mrpComponentWeeklyReqMapper.selectMrpComponentWeeklyReqList(mrpComponentWeeklyReq);
    }

    /**
     * 新增子件物料周需求
     * 
     * @param mrpComponentWeeklyReq 子件物料周需求
     * @return 结果
     */
    @Override
    public int insertMrpComponentWeeklyReq(MrpComponentWeeklyReq mrpComponentWeeklyReq)
    {
        return mrpComponentWeeklyReqMapper.insertMrpComponentWeeklyReq(mrpComponentWeeklyReq);
    }

    /**
     * 修改子件物料周需求
     * 
     * @param mrpComponentWeeklyReq 子件物料周需求
     * @return 结果
     */
    @Override
    public int updateMrpComponentWeeklyReq(MrpComponentWeeklyReq mrpComponentWeeklyReq)
    {
        return mrpComponentWeeklyReqMapper.updateMrpComponentWeeklyReq(mrpComponentWeeklyReq);
    }

    /**
     * 批量删除子件物料周需求
     * 
     * @param ids 需要删除的子件物料周需求主键
     * @return 结果
     */
    @Override
    public int deleteMrpComponentWeeklyReqByIds(Long[] ids)
    {
        return mrpComponentWeeklyReqMapper.deleteMrpComponentWeeklyReqByIds(ids);
    }

    /**
     * 删除子件物料周需求信息
     * 
     * @param id 子件物料周需求主键
     * @return 结果
     */
    @Override
    public int deleteMrpComponentWeeklyReqById(Long id)
    {
        return mrpComponentWeeklyReqMapper.deleteMrpComponentWeeklyReqById(id);
    }

    /**
     * 导入子件物料周需求数据（批量插入，事务性）
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String importData(List<MrpComponentWeeklyReq> list, boolean updateSupport, String operName, String weekStartDate)
    {
        if (StringUtils.isNull(list) || list.size() == 0)
        {
            throw new ServiceException("导入数据不能为空！");
        }
        if (StringUtils.isEmpty(weekStartDate))
        {
            throw new ServiceException("请选择周一日期！");
        }
        // 解析周一日期并计算年第周
        Date mondayDate;
        String yearWeek;
        try
        {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            mondayDate = sdf.parse(weekStartDate);
            Calendar cal = Calendar.getInstance();
            cal.setFirstDayOfWeek(Calendar.MONDAY);
            cal.setMinimalDaysInFirstWeek(4);
            cal.setTime(mondayDate);
            int year = cal.get(Calendar.YEAR);
            int week = cal.get(Calendar.WEEK_OF_YEAR);
            yearWeek = String.format("%d%02d", year, week);
        }
        catch (Exception e)
        {
            throw new ServiceException("周一日期格式错误，请使用yyyy-MM-dd格式！");
        }
        
        // 预处理数据，校验并填充字段（跳过空行）
        List<MrpComponentWeeklyReq> validList = new ArrayList<>();
        int skipNum = 0;
        Date now = new Date();
        
        for (MrpComponentWeeklyReq item : list)
        {
            // 跳过物料编码为空的行（视为空行）
            if (StringUtils.isEmpty(item.getItemCode()))
            {
                skipNum++;
                continue;
            }
            // 自动填充年第周和周一日期
            item.setYearWeek(yearWeek);
            item.setWeekStartDate(mondayDate);
            item.setCreatedAt(now);
            validList.add(item);
        }
        
        if (validList.isEmpty())
        {
            throw new ServiceException("没有有效的数据可导入！所有行的物料编码都为空。");
        }
        
        // 新增：收集需要同步到周排产计划的数据
        List<MrpProdWeeklyPlan> planListToInsert = new ArrayList<>();
        for (MrpComponentWeeklyReq item : validList)
        {
            // 检查周排产计划表中是否已存在该itemCode + weekStartDate
            MrpProdWeeklyPlan query = new MrpProdWeeklyPlan();
            query.setItemCode(item.getItemCode());
            query.setWeekStartDate(mondayDate);
            List<MrpProdWeeklyPlan> existingPlans = mrpProdWeeklyPlanMapper.selectMrpProdWeeklyPlanList(query);
            
            if (existingPlans == null || existingPlans.isEmpty())
            {
                // 不存在则创建
                MrpProdWeeklyPlan plan = convertToProdPlan(item);
                planListToInsert.add(plan);
            }
        }
        
        // 逐条插入（Oracle INSERT ALL不支持SEQUENCE.NEXTVAL）
        int total = validList.size();
        int count = 0;
        long startTime = System.currentTimeMillis();
        System.out.println("开始导入子件物料周需求，共 " + total + " 条数据");
        
        // 先插入周排产计划
        int planInsertCount = 0;
        for (MrpProdWeeklyPlan plan : planListToInsert)
        {
            mrpProdWeeklyPlanMapper.insertMrpProdWeeklyPlan(plan);
            planInsertCount++;
        }
        if (planInsertCount > 0)
        {
            System.out.println("同步导入周排产计划 " + planInsertCount + " 条");
        }
        
        // 再插入子件物料周需求
        for (MrpComponentWeeklyReq item : validList)
        {
            mrpComponentWeeklyReqMapper.insertMrpComponentWeeklyReq(item);
            count++;
            // 每500条打印进度
            if (count % 500 == 0)
            {
                long elapsed = (System.currentTimeMillis() - startTime) / 1000;
                System.out.println("已导入 " + count + "/" + total + " 条，耗时 " + elapsed + " 秒");
            }
        }
        
        long totalTime = (System.currentTimeMillis() - startTime) / 1000;
        System.out.println("导入完成，共 " + total + " 条，总耗时 " + totalTime + " 秒");
        
        String msg = "数据导入成功！共导入 " + total + " 条子件物料需求";
        if (planInsertCount > 0)
        {
            msg += "，同步导入周排产计划 " + planInsertCount + " 条";
        }
        if (skipNum > 0)
        {
            msg += "，跳过空行 " + skipNum + " 条";
        }
        return msg;
    }

    /**
     * 异步导入子件物料周需求数据（不阻塞前端）
     * 使用分批提交事务，避免长事务导致连接超时
     */
    @Async
    @Override
    public void importDataAsync(List<MrpComponentWeeklyReq> list, boolean updateSupport, String operName, String weekStartDate)
    {
        System.out.println("========== 异步导入开始 ==========");
        
        // 解析周一日期和年第周
        String yearWeek;
        Date mondayDate;
        try
        {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            mondayDate = sdf.parse(weekStartDate);
            Calendar cal = Calendar.getInstance();
            cal.setFirstDayOfWeek(Calendar.MONDAY);
            cal.setMinimalDaysInFirstWeek(4);
            cal.setTime(mondayDate);
            int year = cal.get(Calendar.YEAR);
            int week = cal.get(Calendar.WEEK_OF_YEAR);
            yearWeek = String.format("%d%02d", year, week);
        }
        catch (Exception e)
        {
            System.out.println("异步导入失败: 周一日期格式错误");
            return;
        }
        
        // 预处理数据
        List<MrpComponentWeeklyReq> validList = new ArrayList<>();
        Date now = new Date();
        for (MrpComponentWeeklyReq item : list)
        {
            if (StringUtils.isEmpty(item.getItemCode()))
            {
                continue;
            }
            item.setYearWeek(yearWeek);
            item.setWeekStartDate(mondayDate);
            item.setCreatedAt(now);
            validList.add(item);
        }
        
        if (validList.isEmpty())
        {
            System.out.println("异步导入失败: 没有有效数据");
            return;
        }
        
        // 新增：收集需要同步到周排产计划的数据
        final Date finalMondayDate = mondayDate;
        List<MrpProdWeeklyPlan> planListToInsert = new ArrayList<>();
        for (MrpComponentWeeklyReq item : validList)
        {
            // 检查周排产计划表中是否已存在该itemCode + weekStartDate
            MrpProdWeeklyPlan query = new MrpProdWeeklyPlan();
            query.setItemCode(item.getItemCode());
            query.setWeekStartDate(finalMondayDate);
            List<MrpProdWeeklyPlan> existingPlans = mrpProdWeeklyPlanMapper.selectMrpProdWeeklyPlanList(query);
            
            if (existingPlans == null || existingPlans.isEmpty())
            {
                MrpProdWeeklyPlan plan = convertToProdPlan(item);
                planListToInsert.add(plan);
            }
        }
        
        // 先插入周排产计划
        int planInsertCount = 0;
        if (!planListToInsert.isEmpty())
        {
            try
            {
                transactionTemplate.execute(status -> {
                    for (MrpProdWeeklyPlan plan : planListToInsert)
                    {
                        mrpProdWeeklyPlanMapper.insertMrpProdWeeklyPlan(plan);
                    }
                    return null;
                });
                planInsertCount = planListToInsert.size();
                System.out.println("同步导入周排产计划 " + planInsertCount + " 条");
            }
            catch (Exception e)
            {
                System.out.println("同步周排产计划失败: " + e.getMessage());
            }
        }
        
        int total = validList.size();
        int batchSize = 500;  // 每批500条提交一次事务
        int successCount = 0;
        int failCount = 0;
        long startTime = System.currentTimeMillis();
        
        System.out.println("开始分批导入子件物料需求，共 " + total + " 条，每批 " + batchSize + " 条");
        
        // 分批处理，每批独立事务
        for (int i = 0; i < total; i += batchSize)
        {
            int end = Math.min(i + batchSize, total);
            List<MrpComponentWeeklyReq> batch = validList.subList(i, end);
            
            try
            {
                // 使用事务模板，每批独立提交
                transactionTemplate.execute(status -> {
                    for (MrpComponentWeeklyReq item : batch)
                    {
                        mrpComponentWeeklyReqMapper.insertMrpComponentWeeklyReq(item);
                    }
                    return null;
                });
                successCount += batch.size();
            }
            catch (Exception e)
            {
                failCount += batch.size();
                System.out.println("批次 " + (i / batchSize + 1) + " 导入失败: " + e.getMessage());
            }
            
            // 打印进度
            long elapsed = (System.currentTimeMillis() - startTime) / 1000;
            System.out.println("已处理 " + end + "/" + total + " 条，成功 " + successCount + "，失败 " + failCount + "，耗时 " + elapsed + " 秒");
        }
        
        long totalTime = (System.currentTimeMillis() - startTime) / 1000;
        System.out.println("========== 异步导入完成 ==========");
        System.out.println("总计: " + total + " 条子件物料需求，成功: " + successCount + "，失败: " + failCount + "，同步周排产计划: " + planInsertCount + " 条，总耗时: " + totalTime + " 秒");
    }
    
    /**
     * 将子件物料周需求转换为周排产计划
     */
    private MrpProdWeeklyPlan convertToProdPlan(MrpComponentWeeklyReq req)
    {
        MrpProdWeeklyPlan plan = new MrpProdWeeklyPlan();
        plan.setYearWeek(req.getYearWeek());
        plan.setWeekStartDate(req.getWeekStartDate());
        plan.setItemCode(req.getItemCode());
        plan.setItemDesc(req.getItemDesc());
        
        // 每日需求量映射
        plan.setPlanD1(req.getReqMon());
        plan.setPlanD2(req.getReqTue());
        plan.setPlanD3(req.getReqWed());
        plan.setPlanD4(req.getReqThu());
        plan.setPlanD5(req.getReqFri());
        plan.setPlanD6(req.getReqSat());
        plan.setPlanD7(req.getReqSun());
        
        // 默认值
        plan.setSeqNo(new BigDecimal("1"));
        plan.setCreatedAt(new Date());
        
        return plan;
    }
}
