package easydo.technology.service.impl;

import easydo.technology.components.JdbcClient;
import easydo.technology.enums.MESEnum;
import easydo.technology.exception.BizException;
import easydo.technology.model.*;
import easydo.technology.service.FlowNoService;
import easydo.technology.service.ProductPlanService;
import easydo.technology.system.model.SysUser;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.util.List;
import java.util.Map;

@Service
public class ProductPlanServiceImpl implements ProductPlanService {

    @Resource
    private JdbcClient jdbcClient;
    @Resource
    private DataSource dataSource;
    @Resource
    private FlowNoService flowNoService;

    @Override
    @SuppressWarnings("unchecked")
    public Map<String, Object> getPage(Map<String, Object> map) throws Exception {
        // 说明：该接口按 Go 版本的实现方式进行 1:1 同步，采用“分页查询 + 循环逐条补齐关联数据”的方式组装返回结果。
        // 注意：这种写法会产生较多的数据库访问（N+1 查询），但可以确保前端一次请求拿到完整的数据树结构。
        Connection connection = dataSource.getConnection();
        try {
            // 1) 查询生产计划分页数据（基础字段来自 product_plan 表）
            Map<String, Object> result = jdbcClient.getJdbcPage(map, ProductPlan.class, connection);
            List<ProductPlan> list = (List<ProductPlan>) result.get("records");
            if (list == null || list.isEmpty()) {
                return result;
            }

            for (ProductPlan model : list) {
                // 2) 查询并回填生产计划的附件（Minio 文件列表）
                jdbcClient.getMinioFile(model, connection);

                // 3) 查询并回填关联销售订单（SaleOrder）及其附件、明细、明细物料信息
                if (model.getSaleOrderId() != null) {
                    // 3.1) 按 saleOrderId 查询销售订单主表
                    SaleOrder saleOrderParam = new SaleOrder();
                    saleOrderParam.setId(model.getSaleOrderId());
                    SaleOrder saleOrder = jdbcClient.getJdbcModelById(saleOrderParam, connection);
                    if (saleOrder != null) {
                        // 3.2) 查询并回填销售订单附件
                        jdbcClient.getMinioFile(saleOrder, connection);

                        // 3.3) 查询销售订单明细（SaleOrderDetail 列表）
                        SaleOrderDetail detailParam = new SaleOrderDetail();
                        detailParam.setOrderId(saleOrder.getId());
                        List<SaleOrderDetail> detailList = jdbcClient.getJdbcList(detailParam, connection);
                        if (detailList != null) {
                            for (SaleOrderDetail detail : detailList) {
                                // 3.4) 对每条明细查询物料信息（ProductMaterial）并回填到 detail.material
                                ProductMaterial materialParam = new ProductMaterial();
                                materialParam.setCode(detail.getMaterialCode());
                                ProductMaterial material = jdbcClient.getJdbcModel(materialParam, connection);
                                detail.setMaterial(material);
                            }
                        }
                        // 3.5) 将明细列表回填到 saleOrder.childrenList，并将 saleOrder 回填到 plan.saleOrder
                        saleOrder.setChildrenList(detailList);
                        model.setSaleOrder(saleOrder);
                    }
                }

                // 4) 查询并回填计划 BOM 列表（ProductPlanBom），并补齐其关联：工艺路线/质检方案/产品BOM
                ProductPlanBom bomParam = new ProductPlanBom();
                bomParam.setPlanId(model.getId());
                List<ProductPlanBom> bomList = jdbcClient.getJdbcList(bomParam, connection);
                if (bomList != null) {
                    for (ProductPlanBom planBom : bomList) {
                        // 4.1) 工艺路线（ProcessRoute）
                        if (planBom.getRouteId() != null) {
                            ProcessRoute routeParam = new ProcessRoute();
                            routeParam.setId(planBom.getRouteId());
                            planBom.setProcessRoute(jdbcClient.getJdbcModelById(routeParam, connection));
                        }
                        // 4.2) 质检方案（QualityInspectProgram）
                        if (planBom.getInspectProgramId() != null) {
                            QualityInspectProgram programParam = new QualityInspectProgram();
                            programParam.setId(planBom.getInspectProgramId());
                            planBom.setInspectProgram(jdbcClient.getJdbcModelById(programParam, connection));
                        }
                        // 4.3) 产品 BOM（ProductBom）
                        if (planBom.getBomId() != null) {
                            ProductBom productBomParam = new ProductBom();
                            productBomParam.setId(planBom.getBomId());
                            ProductBom productBom = jdbcClient.getJdbcModelById(productBomParam, connection);
                            
                            // 4.3.1) 查询 ProductBom 的物料信息（ProductMaterial）
                            if (productBom != null && productBom.getMaterialCode() != null) {
                                ProductMaterial materialParam = new ProductMaterial();
                                materialParam.setCode(productBom.getMaterialCode());
                                productBom.setMaterial(jdbcClient.getJdbcModel(materialParam, connection));
                            }
                            
                            planBom.setProductBom(productBom);
                        }
                    }
                }
                model.setBomList(bomList);

                // 5) 查询并回填计划设备列表（ProductPlanDevice），并补齐设备基础信息（Device）
                ProductPlanDevice deviceParam = new ProductPlanDevice();
                deviceParam.setPlanId(model.getId());
                List<ProductPlanDevice> deviceList = jdbcClient.getJdbcList(deviceParam, connection);
                if (deviceList != null) {
                    for (ProductPlanDevice planDevice : deviceList) {
                        if (planDevice.getDeviceId() != null) {
                            Device deviceModel = new Device();
                            deviceModel.setId(planDevice.getDeviceId());
                            planDevice.setDevice(jdbcClient.getJdbcModelById(deviceModel, connection));
                        }
                    }
                }
                model.setDeviceList(deviceList);

                // 6) 查询并回填计划人员列表（ProductPlanUser），并补齐人员信息（SysUser）
                ProductPlanUser userParam = new ProductPlanUser();
                userParam.setPlanId(model.getId());
                List<ProductPlanUser> userList = jdbcClient.getJdbcList(userParam, connection);
                if (userList != null) {
                    for (ProductPlanUser planUser : userList) {
                        if (planUser.getUserId() != null) {
                            SysUser userModel = new SysUser();
                            userModel.setId(planUser.getUserId());
                            planUser.setUser(jdbcClient.getJdbcModelById(userModel, connection));
                        }
                    }
                }
                model.setUserList(userList);
            }

            return result;
        } catch (Exception e) {
            throw new BizException(e.getMessage());
        } finally {
            connection.close();
        }
    }

    @Override
    public ProductPlan save(ProductPlan model) throws Exception {
        Connection connection = dataSource.getConnection();
        connection.setAutoCommit(false);
        try {
            // 1) 生成编码（支持手填校验 + 自动生成）
            String code = flowNoService.generateProductPlanCode(model, connection);
            model.setCode(code);

            // 2) 设置初始状态为 pending
            model.setStatus(MESEnum.PRODUCT_PLAN_OF_STATUS_PENDING.getValue());

            // 3) 插入主表（会自动保存附件 fileList）
            jdbcClient.jdbcInsert(model, connection);

            // 4) 插入 BOM 列表
            List<ProductPlanBom> bomList = model.getBomList();
            if (bomList != null) {
                for (ProductPlanBom bom : bomList) {
                    bom.setPlanId(model.getId());

                    // 根据 bomId 查询 product_bom 表获取工艺路线ID
                    if (bom.getBomId() != null) {
                        ProductBom productBomParam = new ProductBom();
                        productBomParam.setId(bom.getBomId());
                        ProductBom productBom = jdbcClient.getJdbcModelById(productBomParam, connection);
                        if (productBom != null && productBom.getRouteId() != null) {
                            bom.setRouteId(productBom.getRouteId());

                            // 根据工艺路线ID查询工艺路线表获取质检方案ID
                            ProcessRoute processRouteParam = new ProcessRoute();
                            processRouteParam.setId(productBom.getRouteId());
                            ProcessRoute processRoute = jdbcClient.getJdbcModelById(processRouteParam, connection);
                            if (processRoute != null && processRoute.getInspectProgramId() != null) {
                                bom.setInspectProgramId(processRoute.getInspectProgramId());
                            }
                        }
                    }

                    jdbcClient.jdbcInsert(bom, connection);
                }
            }

            // 5) 插入设备列表
            List<ProductPlanDevice> deviceList = model.getDeviceList();
            if (deviceList != null) {
                for (ProductPlanDevice device : deviceList) {
                    device.setPlanId(model.getId());
                    jdbcClient.jdbcInsert(device, connection);
                }
            }

            // 6) 插入人员列表
            List<ProductPlanUser> userList = model.getUserList();
            if (userList != null) {
                for (ProductPlanUser user : userList) {
                    user.setPlanId(model.getId());
                    jdbcClient.jdbcInsert(user, connection);
                }
            }

            connection.commit();
            return model;
        } catch (Exception e) {
            connection.rollback();
            throw new BizException(e.getMessage());
        } finally {
            connection.close();
        }
    }

    @Override
    public ProductPlan update(ProductPlan model) throws Exception {
        Connection connection = dataSource.getConnection();
        connection.setAutoCommit(false);
        try {
            // 1) 更新主表（会自动保存附件 fileList）
            jdbcClient.jdbcUpdateById(model, connection);

            // 2) 删除旧 BOM 列表
            ProductPlanBom bomRemoveParam = new ProductPlanBom();
            bomRemoveParam.setPlanId(model.getId());
            jdbcClient.jdbcRemove(bomRemoveParam, connection);

            // 3) 插入新 BOM 列表
            List<ProductPlanBom> bomList = model.getBomList();
            if (bomList != null) {
                for (ProductPlanBom bom : bomList) {
                    bom.setPlanId(model.getId());

                    // 根据 bomId 查询 product_bom 表获取工艺路线ID
                    if (bom.getBomId() != null) {
                        ProductBom productBomParam = new ProductBom();
                        productBomParam.setId(bom.getBomId());
                        ProductBom productBom = jdbcClient.getJdbcModelById(productBomParam, connection);
                        if (productBom != null && productBom.getRouteId() != null) {
                            bom.setRouteId(productBom.getRouteId());

                            // 根据工艺路线ID查询工艺路线表获取质检方案ID
                            ProcessRoute processRouteParam = new ProcessRoute();
                            processRouteParam.setId(productBom.getRouteId());
                            ProcessRoute processRoute = jdbcClient.getJdbcModelById(processRouteParam, connection);
                            if (processRoute != null && processRoute.getInspectProgramId() != null) {
                                bom.setInspectProgramId(processRoute.getInspectProgramId());
                            }
                        }
                    }
                    
                    jdbcClient.jdbcInsert(bom, connection);
                }
            }

            // 4) 删除旧设备列表
            ProductPlanDevice deviceRemoveParam = new ProductPlanDevice();
            deviceRemoveParam.setPlanId(model.getId());
            jdbcClient.jdbcRemove(deviceRemoveParam, connection);

            // 5) 插入新设备列表
            List<ProductPlanDevice> deviceList = model.getDeviceList();
            if (deviceList != null) {
                for (ProductPlanDevice device : deviceList) {
                    device.setPlanId(model.getId());
                    jdbcClient.jdbcInsert(device, connection);
                }
            }

            // 6) 删除旧人员列表
            ProductPlanUser userRemoveParam = new ProductPlanUser();
            userRemoveParam.setPlanId(model.getId());
            jdbcClient.jdbcRemove(userRemoveParam, connection);

            // 7) 插入新人员列表
            List<ProductPlanUser> userList = model.getUserList();
            if (userList != null) {
                for (ProductPlanUser user : userList) {
                    user.setPlanId(model.getId());
                    jdbcClient.jdbcInsert(user, connection);
                }
            }

            connection.commit();
            return model;
        } catch (Exception e) {
            connection.rollback();
            throw new BizException(e.getMessage());
        } finally {
            connection.close();
        }
    }

    @Override
    public ProductPlan remove(ProductPlan model) throws Exception {
        Connection connection = dataSource.getConnection();
        connection.setAutoCommit(false);
        try {
            // 1) 删除主表（JdbcClient 会自动删除附件）
            jdbcClient.jdbcRemoveById(model, connection);

            // 2) 删除 BOM 列表
            ProductPlanBom bomRemoveParam = new ProductPlanBom();
            bomRemoveParam.setPlanId(model.getId());
            jdbcClient.jdbcRemove(bomRemoveParam, connection);

            // 3) 删除设备列表
            ProductPlanDevice deviceRemoveParam = new ProductPlanDevice();
            deviceRemoveParam.setPlanId(model.getId());
            jdbcClient.jdbcRemove(deviceRemoveParam, connection);

            // 4) 删除人员列表
            ProductPlanUser userRemoveParam = new ProductPlanUser();
            userRemoveParam.setPlanId(model.getId());
            jdbcClient.jdbcRemove(userRemoveParam, connection);

            connection.commit();
            return model;
        } catch (Exception e) {
            connection.rollback();
            throw new BizException(e.getMessage());
        } finally {
            connection.close();
        }
    }
}
