package com.aegis.resource.procurement.service.impl;

import java.util.Date;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.aegis.common.constant.UserConstants;
import com.aegis.common.exception.ServiceException;
import com.aegis.common.utils.SecurityUtils;
import com.aegis.common.utils.StringUtils;
import com.aegis.resource.equipment.domain.Equipment;
import com.aegis.resource.equipment.service.IResourceEquipmentService;
import com.aegis.resource.material.domain.Material;
import com.aegis.resource.material.domain.MaterialInventory;
import com.aegis.resource.material.service.IResourceMaterialInventoryService;
import com.aegis.resource.material.service.IResourceMaterialService;
import com.aegis.resource.procurement.domain.Procurement;
import com.aegis.resource.procurement.domain.ProcurementItem;
import com.aegis.resource.procurement.domain.ProcurementQuote;
import com.aegis.resource.procurement.mapper.ResourceProcurementItemMapper;
import com.aegis.resource.procurement.mapper.ResourceProcurementMapper;
import com.aegis.resource.procurement.mapper.ResourceProcurementQuoteMapper;
import com.aegis.resource.procurement.service.IResourceProcurementService;
import com.aegis.resource.supplier.domain.Supplier;
import com.aegis.resource.supplier.service.IResourceSupplierService;

/**
 * 采购申请Service业务层处理
 * 
 * @author aegis
 */
@Service
public class ResourceProcurementServiceImpl implements IResourceProcurementService {

    @Autowired
    private ResourceProcurementMapper procurementMapper;

    @Autowired
    private ResourceProcurementItemMapper itemMapper;

    @Autowired
    private ResourceProcurementQuoteMapper quoteMapper;

    @Autowired
    private IResourceSupplierService supplierService;

    @Autowired
    private IResourceMaterialService materialService;

    @Autowired
    private IResourceMaterialInventoryService inventoryService;

    @Autowired
    private IResourceEquipmentService equipmentService;

    /**
     * 查询采购申请列表
     */
    @Override
    public List<Procurement> listProcurements(Procurement procurement) {
        return procurementMapper.selectProcurementList(procurement);
    }

    /**
     * 根据ID查询采购申请
     */
    @Override
    public Procurement getProcurementById(Long id) {
        return procurementMapper.selectProcurementById(id);
    }

    /**
     * 校验采购编号是否唯一
     */
    @Override
    public boolean isProcurementNoUnique(String procurementNo, Long id) {
        if (StringUtils.isEmpty(procurementNo)) {
            return UserConstants.UNIQUE; // 采购编号为空时认为唯一（由前端校验非空）
        }
        Long excludeId = StringUtils.isNull(id) ? -1L : id;
        Procurement info = procurementMapper.checkProcurementNoUnique(procurementNo, excludeId);
        if (StringUtils.isNotNull(info)) {
            return UserConstants.NOT_UNIQUE;
        }
        return UserConstants.UNIQUE;
    }

    /**
     * 新增采购申请
     */
    @Override
    @Transactional
    public int createProcurement(Procurement procurement) {
        // 校验采购编号唯一性（检查未删除的记录）
        if (!isProcurementNoUnique(procurement.getProcurementNo(), null)) {
            throw new ServiceException("新增采购申请'" + procurement.getTitle() + "'失败，采购编号已存在");
        }
        
        // 检查是否存在已删除的相同编号记录
        Procurement deletedProcurement = procurementMapper.selectDeletedProcurementByNo(procurement.getProcurementNo());
        if (deletedProcurement != null) {
            // 如果存在已删除的记录，则恢复并更新该记录
            String operator = SecurityUtils.getUsername();
            procurement.setId(deletedProcurement.getId());
            procurement.setCreateBy(deletedProcurement.getCreateBy()); // 保留原创建人
            procurement.setUpdateBy(operator);
            procurement.initializeDefaults(operator);
            return procurementMapper.restoreProcurement(procurement);
        }
        
        // 不存在已删除记录，正常插入新记录
        procurement.setCreateBy(SecurityUtils.getUsername());
        procurement.initializeDefaults(SecurityUtils.getUsername());
        return procurementMapper.insertProcurement(procurement);
    }

    /**
     * 修改采购申请
     */
    @Override
    @Transactional
    public int modifyProcurement(Procurement procurement) {
        Procurement oldProcurement = procurementMapper.selectProcurementById(procurement.getId());
        if (oldProcurement == null) {
            // 如果未删除的记录不存在，检查是否存在已删除的记录
            Procurement deletedProcurement = procurementMapper.selectDeletedProcurementByNo(procurement.getProcurementNo());
            if (deletedProcurement != null && deletedProcurement.getId().equals(procurement.getId())) {
                // 如果存在已删除的记录且ID匹配，则恢复并更新
                String operator = SecurityUtils.getUsername();
                procurement.setCreateBy(deletedProcurement.getCreateBy()); // 保留原创建人
                procurement.setUpdateBy(operator);
                procurement.initializeDefaults(operator);
                return procurementMapper.restoreProcurement(procurement);
            }
            throw new ServiceException("采购申请不存在");
        }
        oldProcurement.ensureEditable();
        
        // 如果采购编号发生变化，检查新采购编号是否已被使用（包括已删除的记录）
        if (!oldProcurement.getProcurementNo().equals(procurement.getProcurementNo())) {
            // 校验新采购编号唯一性（检查未删除的记录）
            if (!isProcurementNoUnique(procurement.getProcurementNo(), procurement.getId())) {
                throw new ServiceException("修改采购申请'" + procurement.getTitle() + "'失败，采购编号已存在");
            }
            // 检查新采购编号是否存在已删除的记录
            Procurement deletedProcurementWithNewNo = procurementMapper.selectDeletedProcurementByNo(procurement.getProcurementNo());
            if (deletedProcurementWithNewNo != null) {
                throw new ServiceException("修改采购申请'" + procurement.getTitle() + "'失败，该采购编号已被删除，请先恢复该记录");
            }
        }
        // 使用领域方法更新字段
        if (StringUtils.isNotBlank(procurement.getTitle()) && !procurement.getTitle().equals(oldProcurement.getTitle())) {
            oldProcurement.changeTitle(procurement.getTitle(), SecurityUtils.getUsername());
        }
        if (StringUtils.isNotBlank(procurement.getUrgency()) && !procurement.getUrgency().equals(oldProcurement.getUrgency())) {
            oldProcurement.changeUrgency(procurement.getUrgency(), SecurityUtils.getUsername());
        }
        if (StringUtils.isNotBlank(procurement.getRemark()) && !procurement.getRemark().equals(oldProcurement.getRemark())) {
            oldProcurement.changeRemark(procurement.getRemark(), SecurityUtils.getUsername());
        }
        return procurementMapper.updateProcurement(oldProcurement);
    }

    /**
     * 批量删除采购申请
     */
    @Override
    @Transactional
    public int removeProcurements(Long[] ids) {
        for (Long id : ids) {
            Procurement procurement = procurementMapper.selectProcurementById(id);
            if (procurement == null) {
                throw new ServiceException("采购申请不存在，ID: " + id);
            }
            procurement.markDeleted(SecurityUtils.getUsername());
            // 删除关联的明细和报价
            itemMapper.deleteProcurementItemByProcurementId(id);
            quoteMapper.deleteProcurementQuoteByProcurementId(id);
            procurementMapper.updateProcurement(procurement);
        }
        return ids.length;
    }

    /**
     * 删除采购申请信息
     */
    @Override
    @Transactional
    public int removeProcurement(Long id) {
        Procurement procurement = procurementMapper.selectProcurementById(id);
        if (procurement == null) {
            throw new ServiceException("采购申请不存在");
        }
        procurement.markDeleted(SecurityUtils.getUsername());
        // 删除关联的明细和报价
        itemMapper.deleteProcurementItemByProcurementId(id);
        quoteMapper.deleteProcurementQuoteByProcurementId(id);
        return procurementMapper.updateProcurement(procurement);
    }

    /**
     * 提交采购申请（draft → submitted）
     */
    @Override
    @Transactional
    public int submitProcurement(Long id) {
        Procurement procurement = procurementMapper.selectProcurementById(id);
        if (procurement == null) {
            throw new ServiceException("采购申请不存在");
        }
        // 检查是否有采购明细
        List<ProcurementItem> items = itemMapper.selectProcurementItemListByProcurementId(id);
        if (items == null || items.isEmpty()) {
            throw new ServiceException("采购申请必须至少包含一条采购明细");
        }
        procurement.submit(SecurityUtils.getUsername());
        return procurementMapper.updateProcurement(procurement);
    }

    /**
     * 审核通过（submitted → approved）
     */
    @Override
    @Transactional
    public int approveProcurement(Long id, String comment) {
        Procurement procurement = procurementMapper.selectProcurementById(id);
        if (procurement == null) {
            throw new ServiceException("采购申请不存在");
        }
        procurement.approve(SecurityUtils.getUserId(), SecurityUtils.getUsername(), comment, SecurityUtils.getUsername());
        return procurementMapper.updateProcurement(procurement);
    }

    /**
     * 审核驳回（submitted → rejected）
     */
    @Override
    @Transactional
    public int rejectProcurement(Long id, String comment) {
        Procurement procurement = procurementMapper.selectProcurementById(id);
        if (procurement == null) {
            throw new ServiceException("采购申请不存在");
        }
        procurement.reject(SecurityUtils.getUserId(), SecurityUtils.getUsername(), comment, SecurityUtils.getUsername());
        return procurementMapper.updateProcurement(procurement);
    }

    /**
     * 重新提交（rejected → submitted）
     * 驳回后修改完成，直接提交审核
     */
    @Override
    @Transactional
    public int resubmitProcurement(Long id) {
        Procurement procurement = procurementMapper.selectProcurementById(id);
        if (procurement == null) {
            throw new ServiceException("采购申请不存在");
        }
        // 检查是否有明细，没有明细不能提交
        List<ProcurementItem> items = itemMapper.selectProcurementItemListByProcurementId(id);
        if (items == null || items.isEmpty()) {
            throw new ServiceException("采购申请没有明细，无法提交");
        }
        procurement.resubmit(SecurityUtils.getUsername());
        return procurementMapper.updateProcurement(procurement);
    }

    /**
     * 确认中标供应商（approved → in_progress）
     */
    @Override
    @Transactional
    public int awardProcurement(Long id, Long quoteId) {
        Procurement procurement = procurementMapper.selectProcurementById(id);
        if (procurement == null) {
            throw new ServiceException("采购申请不存在");
        }
        ProcurementQuote quote = quoteMapper.selectProcurementQuoteById(quoteId);
        if (quote == null) {
            throw new ServiceException("报价记录不存在");
        }
        if (!quote.getProcurementId().equals(id)) {
            throw new ServiceException("报价记录不属于该采购申请");
        }
        // 取消所有中标标记
        quoteMapper.cancelAwardedByProcurementId(id);
        // 设置新的中标标记
        quoteMapper.setAwarded(quoteId);
        // 使用领域方法更新采购申请
        procurement.award(quote.getSupplierId(), SecurityUtils.getUsername());
        return procurementMapper.updateProcurement(procurement);
    }

    /**
     * 采购入库（in_progress → received）
     */
    @Override
    @Transactional
    public int receiveProcurement(Long id, Long warehouseId) {
        Procurement procurement = procurementMapper.selectProcurementById(id);
        if (procurement == null) {
            throw new ServiceException("采购申请不存在");
        }
        if (!"in_progress".equals(procurement.getStatus())) {
            throw new ServiceException("只有进行中状态的采购申请才能入库");
        }
        // 查询采购明细
        List<ProcurementItem> items = itemMapper.selectProcurementItemListByProcurementId(id);
        if (items == null || items.isEmpty()) {
            throw new ServiceException("采购申请没有明细，无法入库");
        }
        // 处理每个明细
        for (ProcurementItem item : items) {
            if ("material".equals(item.getCategory())) {
                // 物资入库
                if (warehouseId == null) {
                    throw new ServiceException("物资入库必须指定仓库ID");
                }
                Long materialId = item.getTargetMaterialId();
                if (materialId == null) {
                    // 创建新物资
                    Material material = new Material();
                    // 生成物资编码：MAT-{timestamp}-{random}
                    String materialCode = "MAT-" + System.currentTimeMillis() + "-" + (int)(Math.random() * 1000);
                    material.setMaterialCode(materialCode);
                    // 从spec解析物资名称，如果没有则使用默认名称
                    if (StringUtils.isNotEmpty(item.getSpec())) {
                        material.setMaterialName(item.getSpec());
                        material.setSpec(item.getSpec());
                    } else {
                        material.setMaterialName("采购物资-" + materialCode);
                    }
                    material.setUnit(item.getUnit());
                    // 如果isReusable不为空，设置reusable
                    if (item.getIsReusable() != null) {
                        material.setReusable(item.getIsReusable());
                    }
                    material.setCreateBy(SecurityUtils.getUsername());
                    // 创建物资
                    materialService.save(material);
                    materialId = material.getId();
                    // 更新采购明细的targetMaterialId，便于后续追踪
                    item.setTargetMaterialId(materialId);
                    item.setUpdateBy(SecurityUtils.getUsername());
                    itemMapper.updateProcurementItem(item);
                }
                // 更新库存
                MaterialInventory inventory = new MaterialInventory();
                inventory.setMaterialId(materialId);
                inventory.setWarehouseId(warehouseId);
                inventory.setTotalQty(item.getQty());
                inventoryService.addInventory(inventory);
            } else if ("equipment".equals(item.getCategory())) {
                // 装备入库（创建装备记录）
                // 根据数量创建多条装备记录
                int quantity = item.getQty().intValue();
                if (quantity <= 0) {
                    throw new ServiceException("装备数量必须大于0");
                }
                // 使用基础时间戳，确保同一批次装备编码唯一
                long baseTimestamp = System.currentTimeMillis();
                for (int i = 0; i < quantity; i++) {
                    Equipment equipment = new Equipment();
                    // 生成装备编码：EQ-{timestamp}-{index}，每次循环增加时间戳避免重复
                    String equipmentCode = "EQ-" + (baseTimestamp + i) + "-" + (int)(Math.random() * 1000);
                    equipment.setEquipmentCode(equipmentCode);
                    // 从spec解析装备名称，如果没有则使用默认名称
                    if (StringUtils.isNotEmpty(item.getSpec())) {
                        // 尝试从spec中解析装备名称、类型、品牌、型号等信息
                        String spec = item.getSpec();
                        equipment.setEquipmentName(spec);
                        // 如果spec包含分隔符，可以进一步解析
                        if (spec.contains("|")) {
                            String[] parts = spec.split("\\|");
                            if (parts.length > 0) {
                                equipment.setEquipmentName(parts[0].trim());
                            }
                            if (parts.length > 1) {
                                equipment.setEquipmentType(parts[1].trim());
                            }
                            if (parts.length > 2) {
                                equipment.setBrand(parts[2].trim());
                            }
                            if (parts.length > 3) {
                                equipment.setModel(parts[3].trim());
                            }
                        } else {
                            equipment.setEquipmentName(spec);
                        }
                    } else {
                        equipment.setEquipmentName("采购装备-" + equipmentCode);
                    }
                    // 设置采购日期为当前日期
                    equipment.setPurchaseDate(new Date());
                    equipment.setStatus("available");
                    equipment.setCreateBy(SecurityUtils.getUsername());
                    // 创建装备
                    equipmentService.insertEquipment(equipment);
                }
            }
        }
        // 使用领域方法更新采购申请状态
        procurement.receive(SecurityUtils.getUsername());
        return procurementMapper.updateProcurement(procurement);
    }

    /**
     * 查询采购明细列表
     */
    @Override
    public List<ProcurementItem> listProcurementItems(ProcurementItem item) {
        return itemMapper.selectProcurementItemList(item);
    }

    /**
     * 根据采购申请ID查询明细列表
     */
    @Override
    public List<ProcurementItem> listProcurementItemsByProcurementId(Long procurementId) {
        return itemMapper.selectProcurementItemListByProcurementId(procurementId);
    }

    /**
     * 根据ID查询采购明细
     */
    @Override
    public ProcurementItem getProcurementItemById(Long id) {
        return itemMapper.selectProcurementItemById(id);
    }

    /**
     * 新增采购明细
     */
    @Override
    @Transactional
    public int createProcurementItem(ProcurementItem item) {
        // 校验采购申请是否存在
        Procurement procurement = procurementMapper.selectProcurementById(item.getProcurementId());
        if (procurement == null) {
            throw new ServiceException("采购申请不存在");
        }
        // 只有草稿或驳回状态才能添加明细
        procurement.ensureEditable();
        item.setCreateBy(SecurityUtils.getUsername());
        return itemMapper.insertProcurementItem(item);
    }

    /**
     * 修改采购明细
     */
    @Override
    @Transactional
    public int modifyProcurementItem(ProcurementItem item) {
        ProcurementItem oldItem = itemMapper.selectProcurementItemById(item.getId());
        if (oldItem == null) {
            throw new ServiceException("采购明细不存在");
        }
        // 校验采购申请状态
        Procurement procurement = procurementMapper.selectProcurementById(oldItem.getProcurementId());
        if (procurement == null) {
            throw new ServiceException("采购申请不存在");
        }
        procurement.ensureEditable();
        item.setUpdateBy(SecurityUtils.getUsername());
        return itemMapper.updateProcurementItem(item);
    }

    /**
     * 删除采购明细
     */
    @Override
    @Transactional
    public int removeProcurementItem(Long id) {
        ProcurementItem item = itemMapper.selectProcurementItemById(id);
        if (item == null) {
            throw new ServiceException("采购明细不存在");
        }
        // 校验采购申请状态
        Procurement procurement = procurementMapper.selectProcurementById(item.getProcurementId());
        if (procurement != null) {
            procurement.ensureEditable();
        }
        return itemMapper.deleteProcurementItemById(id);
    }

    /**
     * 供应商报价
     */
    @Override
    @Transactional
    public int submitQuote(ProcurementQuote quote) {
        // 校验采购申请是否存在
        Procurement procurement = procurementMapper.selectProcurementById(quote.getProcurementId());
        if (procurement == null) {
            throw new ServiceException("采购申请不存在");
        }
        // 只有已审核通过状态的采购申请才能报价
        if (!"approved".equals(procurement.getStatus())) {
            throw new ServiceException("只有已审核通过状态的采购申请才能报价");
        }
        // 校验供应商是否存在且不是黑名单
        Supplier supplier = supplierService.getSupplierById(quote.getSupplierId());
        if (supplier == null) {
            throw new ServiceException("供应商不存在");
        }
        if ("blacklisted".equals(supplier.getStatus())) {
            throw new ServiceException("黑名单供应商不能报价");
        }
        // 检查是否已报价
        ProcurementQuote existingQuote = quoteMapper.selectProcurementQuoteByProcurementAndSupplier(
            quote.getProcurementId(), quote.getSupplierId());
        if (existingQuote != null) {
            // 更新报价
            quote.setId(existingQuote.getId());
            quote.setUpdateBy(SecurityUtils.getUsername());
            return quoteMapper.updateProcurementQuote(quote);
        } else {
            // 新增报价
            quote.setCreateBy(SecurityUtils.getUsername());
            return quoteMapper.insertProcurementQuote(quote);
        }
    }

    /**
     * 查询报价列表
     */
    @Override
    public List<ProcurementQuote> listProcurementQuotes(ProcurementQuote quote) {
        return quoteMapper.selectProcurementQuoteList(quote);
    }

    /**
     * 根据采购申请ID查询报价列表
     */
    @Override
    public List<ProcurementQuote> listProcurementQuotesByProcurementId(Long procurementId) {
        return quoteMapper.selectProcurementQuoteListByProcurementId(procurementId);
    }

    /**
     * 根据ID查询报价
     */
    @Override
    public ProcurementQuote getProcurementQuoteById(Long id) {
        return quoteMapper.selectProcurementQuoteById(id);
    }
}