package com.erp.warehouse.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.erp.warehouse.dto.OutboundOrderDTO;
import com.erp.warehouse.entity.OutboundOrder;
import com.erp.warehouse.entity.Warehouse;
import com.erp.warehouse.mapper.OutboundOrderMapper;
import com.erp.warehouse.mapper.WarehouseMapper;
import com.erp.warehouse.service.OutboundService;
import com.erp.warehouse.service.StockService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.atomic.AtomicLong;

/**
 * 出库管理服务实现
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class OutboundServiceImpl implements OutboundService {

    private final OutboundOrderMapper outboundOrderMapper;
    private final WarehouseMapper warehouseMapper;
    private final StockService stockService;

    private static final AtomicLong ORDER_COUNTER = new AtomicLong(System.currentTimeMillis() % 100000);

    @Override
    @Transactional
    public OutboundOrder createOutboundOrder(OutboundOrderDTO.CreateRequest request, Long operatorId) {
        Warehouse warehouse = warehouseMapper.selectById(request.getWarehouseId());
        if (warehouse == null) {
            throw new IllegalArgumentException("仓库不存在: " + request.getWarehouseId());
        }
        if ("transfer".equals(request.getOutboundType()) && request.getTargetWarehouseId() == null) {
            throw new IllegalArgumentException("调拨出库必须指定目标仓库");
        }

        String outboundNo = generateOutboundNo(request.getOutboundType());

        OutboundOrder order = OutboundOrder.builder()
                .outboundNo(outboundNo)
                .outboundType(request.getOutboundType())
                .warehouseId(request.getWarehouseId())
                .targetWarehouseId(request.getTargetWarehouseId())
                .relatedNo(request.getRelatedNo())
                .customerId(request.getCustomerId())
                .customerName(request.getCustomerName())
                .status("pending")
                .remark(request.getRemark())
                .operatorId(operatorId)
                .createTime(LocalDateTime.now())
                .updateTime(LocalDateTime.now())
                .build();

        outboundOrderMapper.insert(order);
        log.info("创建出库单: outboundNo={}, type={}, warehouseId={}", outboundNo, request.getOutboundType(), request.getWarehouseId());
        return order;
    }

    @Override
    @Transactional
    public OutboundOrder confirmOutbound(Long outboundOrderId, OutboundOrderDTO.ShipRequest request) {
        OutboundOrder order = outboundOrderMapper.selectById(outboundOrderId);
        if (order == null) {
            throw new IllegalArgumentException("出库单不存在: " + outboundOrderId);
        }
        if (!"pending".equals(order.getStatus()) && !"partial".equals(order.getStatus())) {
            throw new IllegalStateException("出库单状态不允许出库: " + order.getStatus());
        }

        for (OutboundOrderDTO.ShipItem item : request.getItems()) {
            // 出库扣减库存
            if (item.getQuantity() != null && item.getQuantity() > 0) {
                stockService.outbound(
                        item.getSkuCode(),
                        order.getWarehouseId(),
                        item.getQuantity(),
                        order.getOutboundNo(),
                        request.getTrackingNo(),
                        order.getOperatorId()
                );
            }
        }

        order.setLogisticsCompany(request.getLogisticsCompany());
        order.setTrackingNo(request.getTrackingNo());
        order.setStatus("completed");
        order.setOutboundTime(LocalDateTime.now());
        order.setUpdateTime(LocalDateTime.now());
        outboundOrderMapper.updateById(order);

        log.info("确认出库: outboundNo={}, trackingNo={}", order.getOutboundNo(), request.getTrackingNo());
        return order;
    }

    @Override
    @Transactional
    public void cancelOutbound(Long outboundOrderId) {
        OutboundOrder order = outboundOrderMapper.selectById(outboundOrderId);
        if (order == null) {
            throw new IllegalArgumentException("出库单不存在: " + outboundOrderId);
        }
        if ("completed".equals(order.getStatus()) || "cancelled".equals(order.getStatus())) {
            throw new IllegalStateException("出库单状态不允许取消: " + order.getStatus());
        }

        order.setStatus("cancelled");
        order.setUpdateTime(LocalDateTime.now());
        outboundOrderMapper.updateById(order);

        log.info("取消出库单: outboundNo={}", order.getOutboundNo());
    }

    @Override
    public IPage<OutboundOrder> listOutboundOrders(String outboundType, Long warehouseId, String status, int page, int limit) {
        Page<OutboundOrder> pageParam = new Page<>(page, limit);
        return outboundOrderMapper.selectPageList(pageParam, outboundType, warehouseId, status);
    }

    @Override
    public OutboundOrder getOutboundOrder(Long id) {
        return outboundOrderMapper.selectById(id);
    }

    @Override
    public OutboundOrder getOutboundOrderByNo(String outboundNo) {
        return outboundOrderMapper.findByOutboundNo(outboundNo);
    }

    private String generateOutboundNo(String outboundType) {
        String prefix = switch (outboundType) {
            case "sale" -> "XSCK";
            case "transfer" -> "DBCK";
            default -> "CK";
        };
        return prefix + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"))
                + String.format("%05d", ORDER_COUNTER.incrementAndGet() % 100000);
    }
}
