package com.haha.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.haha.entity.DeviceInventory;
import com.haha.entity.InventoryLog;
import com.haha.mapper.DeviceInventoryMapper;
import com.haha.service.DeviceInventoryService;
import com.haha.service.InventoryLogService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 设备库存服务实现类
 */
@Slf4j
@Service
public class DeviceInventoryServiceImpl extends ServiceImpl<DeviceInventoryMapper, DeviceInventory>
        implements DeviceInventoryService {

    @Autowired
    private DeviceInventoryMapper deviceInventoryMapper;

    @Autowired
    private InventoryLogService inventoryLogService;

    @Override
    public IPage<DeviceInventory> getPage(int page, int pageSize, Map<String, Object> params) {
        LambdaQueryWrapper<DeviceInventory> wrapper = new LambdaQueryWrapper<>();

        // 设备ID筛选
        String deviceId = (String) params.get("deviceId");
        if (StringUtils.hasText(deviceId)) {
            wrapper.eq(DeviceInventory::getDeviceId, deviceId);
        }

        // 商品名称模糊搜索
        String productName = (String) params.get("productName");
        if (StringUtils.hasText(productName)) {
            wrapper.like(DeviceInventory::getProductName, productName);
        }

        // 低库存筛选
        Object lowStock = params.get("lowStock");
        if (lowStock != null && Boolean.TRUE.equals(lowStock)) {
            wrapper.apply("stock <= warning_threshold");
        }

        // 按更新时间倒序
        wrapper.orderByDesc(DeviceInventory::getUpdateTime);

        return page(new Page<>(page, pageSize), wrapper);
    }

    @Override
    public List<Map<String, Object>> getInventoryWithProduct(String deviceId) {
        return deviceInventoryMapper.selectInventoryWithProduct(deviceId);
    }

    @Override
    public List<Map<String, Object>> getLowStockList() {
        return deviceInventoryMapper.selectLowStockInventories();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public DeviceInventory increaseStock(String deviceId, Long productId, String productCode, String productName,
                                         Integer quantity, Integer shelfNum, String position,
                                         Long operatorId, String operatorName, String activityId) {
        // 查询现有库存
        DeviceInventory inventory = deviceInventoryMapper.selectByDeviceAndProduct(deviceId, productId);

        int beforeStock = 0;
        if (inventory == null) {
            // 新建库存记录
            inventory = new DeviceInventory();
            inventory.setDeviceId(deviceId);
            inventory.setProductId(productId);
            inventory.setProductCode(productCode);
            inventory.setProductName(productName);
            inventory.setStock(quantity);
            inventory.setShelfNum(shelfNum);
            inventory.setPosition(position);
            inventory.setWarningThreshold(5); // 默认预警阈值
            inventory.setLastRestockTime(LocalDateTime.now());
            inventory.setCreateTime(LocalDateTime.now());
            inventory.setUpdateTime(LocalDateTime.now());
            save(inventory);
            beforeStock = 0;
        } else {
            // 更新库存
            beforeStock = inventory.getStock();
            inventory.setStock(beforeStock + quantity);
            inventory.setShelfNum(shelfNum);
            inventory.setPosition(position);
            inventory.setLastRestockTime(LocalDateTime.now());
            inventory.setUpdateTime(LocalDateTime.now());
            updateById(inventory);
        }

        // 记录日志
        inventoryLogService.logChange(deviceId, productId, productCode, productName,
                InventoryLog.TYPE_RESTOCK, quantity, beforeStock, inventory.getStock(),
                null, activityId, operatorId, operatorName, "上货增加库存");

        return inventory;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public DeviceInventory decreaseStock(String deviceId, Long productId, Integer quantity,
                                         String orderId, Long operatorId, String operatorName) {
        DeviceInventory inventory = deviceInventoryMapper.selectByDeviceAndProduct(deviceId, productId);

        if (inventory == null) {
            log.warn("库存记录不存在: deviceId={}, productId={}", deviceId, productId);
            return null;
        }

        int beforeStock = inventory.getStock();
        int newStock = Math.max(0, beforeStock - quantity);
        inventory.setStock(newStock);
        inventory.setUpdateTime(LocalDateTime.now());
        updateById(inventory);

        // 记录日志
        inventoryLogService.logChange(deviceId, productId, inventory.getProductCode(), inventory.getProductName(),
                InventoryLog.TYPE_SALE, -quantity, beforeStock, newStock,
                orderId, null, operatorId, operatorName, "销售扣减库存");

        return inventory;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public DeviceInventory adjustStock(String deviceId, Long productId, Integer newStock,
                                       String remark, Long operatorId, String operatorName) {
        DeviceInventory inventory = deviceInventoryMapper.selectByDeviceAndProduct(deviceId, productId);

        if (inventory == null) {
            log.warn("库存记录不存在: deviceId={}, productId={}", deviceId, productId);
            return null;
        }

        int beforeStock = inventory.getStock();
        int changeQuantity = newStock - beforeStock;
        int changeType = changeQuantity >= 0 ? InventoryLog.TYPE_ADJUST_ADD : InventoryLog.TYPE_ADJUST_SUB;

        inventory.setStock(newStock);
        inventory.setUpdateTime(LocalDateTime.now());
        updateById(inventory);

        // 记录日志
        inventoryLogService.logChange(deviceId, productId, inventory.getProductCode(), inventory.getProductName(),
                changeType, changeQuantity, beforeStock, newStock,
                null, null, operatorId, operatorName, remark);

        return inventory;
    }

    @Override
    public Map<String, Object> getStatistics() {
        Map<String, Object> stats = new HashMap<>();

        // 总库存记录数
        stats.put("totalRecords", count());

        // 总库存数量
        LambdaQueryWrapper<DeviceInventory> wrapper = new LambdaQueryWrapper<>();
        wrapper.select(DeviceInventory::getStock);
        List<DeviceInventory> allInventory = list(wrapper);
        int totalStock = allInventory.stream().mapToInt(i -> i.getStock() != null ? i.getStock() : 0).sum();
        stats.put("totalStock", totalStock);

        // 低库存数量
        long lowStockCount = count(new LambdaQueryWrapper<DeviceInventory>()
                .apply("stock <= warning_threshold"));
        stats.put("lowStockCount", lowStockCount);

        // 零库存数量
        long zeroStockCount = count(new LambdaQueryWrapper<DeviceInventory>()
                .eq(DeviceInventory::getStock, 0));
        stats.put("zeroStockCount", zeroStockCount);

        return stats;
    }

    @Override
    public DeviceInventory getByDeviceAndProduct(String deviceId, Long productId) {
        return deviceInventoryMapper.selectByDeviceAndProduct(deviceId, productId);
    }

    @Override
    public IPage<Map<String, Object>> getDeviceInventoryStats(int page, int pageSize, Map<String, Object> params) {
        Page<Map<String, Object>> pageParam = new Page<>(page, pageSize);

        String shopName = (String) params.get("shopName");
        String deviceName = (String) params.get("deviceName");
        String deviceId = (String) params.get("deviceId");
        Boolean hasUnknownProduct = null;
        Object hasUnknownObj = params.get("hasUnknownProduct");
        if (hasUnknownObj != null) {
            hasUnknownProduct = Boolean.valueOf(hasUnknownObj.toString());
        }
        Integer stockStatus = null;
        Object stockStatusObj = params.get("stockStatus");
        if (stockStatusObj != null && !stockStatusObj.toString().isEmpty()) {
            stockStatus = Integer.valueOf(stockStatusObj.toString());
        }

        IPage<Map<String, Object>> result = deviceInventoryMapper.selectDeviceInventoryStats(
                pageParam, shopName, deviceName, deviceId, hasUnknownProduct, stockStatus);

        // 处理每条记录，添加计算字段
        for (Map<String, Object> record : result.getRecords()) {
            // 计算库存占比
            Integer remainingStock = record.get("remaining_stock") != null ?
                    ((Number) record.get("remaining_stock")).intValue() : 0;
            Integer standardStock = record.get("standard_stock") != null ?
                    ((Number) record.get("standard_stock")).intValue() : 0;

            int stockRatio = standardStock > 0 ? (remainingStock * 100 / standardStock) : 0;
            record.put("stock_ratio", stockRatio);

            // 判断库存状态
            String stockStatusStr;
            Integer zeroStockCount = record.get("zero_stock_count") != null ?
                    ((Number) record.get("zero_stock_count")).intValue() : 0;
            Integer lowStockCount = record.get("low_stock_count") != null ?
                    ((Number) record.get("low_stock_count")).intValue() : 0;
            Integer productCount = record.get("product_count") != null ?
                    ((Number) record.get("product_count")).intValue() : 0;

            if (productCount == 0 || remainingStock == 0) {
                stockStatusStr = "缺货";
            } else if (lowStockCount > 0 || stockRatio < 50) {
                stockStatusStr = "低库存";
            } else {
                stockStatusStr = "正常";
            }
            record.put("stock_status", stockStatusStr);

            // 是否有未知商品
            Integer unknownProductCount = record.get("unknown_product_count") != null ?
                    ((Number) record.get("unknown_product_count")).intValue() : 0;
            record.put("has_unknown_product", unknownProductCount > 0);
        }

        return result;
    }
}
