package com.ruoyi.inventory.controller;

import com.alibaba.excel.EasyExcel;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.Materials;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.inventory.domain.Inventory;
import com.ruoyi.inventory.domain.OutboundOrderItems;
import com.ruoyi.inventory.domain.StorageLocations;
import com.ruoyi.inventory.domain.Warehouses;
import com.ruoyi.inventory.domain.vo.InventoryExceedWarnVO;
import com.ruoyi.inventory.domain.vo.InventorySummaryVO;
import com.ruoyi.inventory.domain.vo.InventoryVo;
import com.ruoyi.inventory.mapper.MaterialsMapper;
import com.ruoyi.inventory.mapper.StorageLocationsMapper;
import com.ruoyi.inventory.mapper.WarehousesMapper;
import com.ruoyi.inventory.service.IInventoryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 库存Controller
 * 
 * @author ruoyi
 * @date 2025-12-03
 */
@RestController
@RequestMapping("/inventory/inventory")
public class InventoryController extends BaseController
{
    @Autowired
    private IInventoryService inventoryService;

    @Autowired
    private MaterialsMapper materialsMapper;

    @Autowired
    private WarehousesMapper warehousesMapper;

    @Autowired
    private StorageLocationsMapper storageLocationsMapper;

    /**
     * 查询库存列表
     */
    @PreAuthorize("@ss.hasPermi('inventory:inventory:list')")
    @GetMapping("/list")
    public TableDataInfo list(Inventory inventory)
    {
        startPage();
        List<Inventory> list = inventoryService.selectInventoryList(inventory);
        return getDataTable(list);
    }
    /**
     * 查询库存列表（按物料汇总统计）
     */
    @PreAuthorize("@ss.hasPermi('inventory:inventory:list')")
    @GetMapping("/listCount")
    public TableDataInfo listCount(Inventory inventory)
    {
        startPage();
        List<InventorySummaryVO> list = inventoryService.selectInventorySummaryList(inventory);
        return getDataTable(list);
    }

    /**
     * 查询库存明细列表（根据物料标识及检索条件）
     */
    @PreAuthorize("@ss.hasPermi('inventory:inventory:list')")
    @GetMapping("/detailList")
    public TableDataInfo detailList(Inventory inventory)
    {
        List<Inventory> list = inventoryService.selectInventoryDetailList(inventory);
        return getDataTable(list);
    }

    /**
     * 查询库存列表
     */
    @PreAuthorize("@ss.hasPermi('inventory:inventory:list')")
    @PostMapping("/listByMaterialId")
    public TableDataInfo listByMaterialId(@RequestBody OutboundOrderItems inventory)
    {
        startPage();
        List<Inventory> list = inventoryService.listByMatreialId(inventory);
        return getDataTable(list);
    }
    /**
     * 导出库存列表
     */
    @PreAuthorize("@ss.hasPermi('inventory:inventory:export')")
    @Log(title = "库存", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, Inventory inventory)
    {
        List<Inventory> list = inventoryService.selectInventoryList(inventory);
        ExcelUtil<Inventory> util = new ExcelUtil<Inventory>(Inventory.class);
        util.exportExcel(response, list, "库存数据");
    }
    /**
     * 导出库存列表（使用EasyExcel）
     */
    @PreAuthorize("@ss.hasPermi('inventory:inventory:export')")
    @Log(title = "库存", businessType = BusinessType.EXPORT)
    @PostMapping("/exportExcel")
    public void exportExcel(HttpServletResponse response, Inventory inventory)
    {
        List<InventoryVo> list = inventoryService.selectInventoryVoList(inventory);
        ExcelUtil<InventoryVo> util = new ExcelUtil<InventoryVo>(InventoryVo.class);
        util.exportExcel(response, list, "库存数据");
//        try {
//            List<InventorySummaryVO> list = inventoryService.selectInventorySummaryList(inventory);
//            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
//            response.setCharacterEncoding("utf-8");
//            String fileName = "库存明细数据_" + System.currentTimeMillis() + ".xlsx";
//            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + java.net.URLEncoder.encode(fileName, "UTF-8"));
//            EasyExcel.write(response.getOutputStream(), InventorySummaryVO.class)
//                    .sheet("库存明细")
//                    .doWrite(list);
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
    }

    /**
     * 获取库存详细信息
     */
    @PreAuthorize("@ss.hasPermi('inventory:inventory:query')")
    @GetMapping(value = "/{id}")
    public AjaxResult getInfo(@PathVariable("id") String id)
    {
        return success(inventoryService.selectInventoryById(id));
    }

    /**
     * 新增库存
     */
    @PreAuthorize("@ss.hasPermi('inventory:inventory:add')")
    @Log(title = "库存", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody Inventory inventory)
    {
        inventory.setId(UUID.randomUUID().toString());
        return toAjax(inventoryService.insertInventory(inventory));
    }

    /**
     * 修改库存
     */
    @PreAuthorize("@ss.hasPermi('inventory:inventory:edit')")
    @Log(title = "库存", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody Inventory inventory)
    {
        return toAjax(inventoryService.updateInventory(inventory));
    }

    /**
     * 删除库存
     */
    @PreAuthorize("@ss.hasPermi('inventory:inventory:remove')")
    @Log(title = "库存", businessType = BusinessType.DELETE)
	@DeleteMapping("/{ids}")
    public AjaxResult remove(@PathVariable String[] ids)
    {
        return toAjax(inventoryService.deleteInventoryByIds(ids));
    }

    /**
     * 批量新增库存
     */
    @PreAuthorize("@ss.hasPermi('inventory:inventory:add')")
    @Log(title = "库存", businessType = BusinessType.INSERT)
    @PostMapping("/batchAdd")
    public AjaxResult batchAdd(@Validated @RequestBody List<Inventory> inventoryList)
    {
        return toAjax(inventoryService.insertInventoryList(inventoryList));
    }

    /**
     * Excel 导入库存（表头占第1行，从第2行开始数据）
     * 表头：日期、SAPNo、物料名称、TS Code、批号、计划数量、件重、约数、件数、件重、库位、仓库
     * 规则：
     * - SAPNo 查物料表取 material_id
     * - 仓库名称查仓库表取 warehouses_code、id
     * - 库位名称+仓库ID 查库位表取 location_id
     * - 计划数量 -> quantity，件重(首个) -> unit_weight，第二个件重 -> total_weight（若存在）
     * - 日期 -> last_inbound_time
     */
    @PreAuthorize("@ss.hasPermi('inventory:inventory:import')")
    @Log(title = "库存导入", businessType = BusinessType.IMPORT)
    @PostMapping("/import")
    public AjaxResult importInventory(@RequestParam("file") MultipartFile file) {
        if (file == null || file.isEmpty()) {
            return error("上传文件为空");
        }
        try {
            List<Map<Integer, String>> rows = EasyExcel.read(file.getInputStream())
                    .headRowNumber(1)
                    .sheet()
                    .doReadSync();

            if (rows == null || rows.isEmpty()) {
                return error("未读取到数据");
            }

            List<Inventory> toInsert = new ArrayList<>();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

            for (int i = 0; i < rows.size(); i++) {
                Map<Integer, String> row = rows.get(i);
                // 基础字段取值
                String dateStr = row.get(0);
                String sapNo = row.get(1);
                String batchId = row.get(4);
                String planQtyStr = row.get(5);
                String unitWeightStr = row.get(6);
                String secondWeightStr = row.get(9);
                String locationName = row.get(10);
                String warehouseName = row.get(11);

                if (StringUtils.isEmpty(sapNo)) {
                    return error("第" + (i + 2) + "行SAPNo为空");
                }
                List<Materials> materialsList = materialsMapper.selectMaterialsBySapNo(sapNo);
                if (materialsList == null || materialsList.isEmpty()) {
                    return error("第" + (i + 2) + "行SAPNo未找到物料：" + sapNo);
                }
                Materials materials = materialsList.get(0);

                if (StringUtils.isEmpty(warehouseName)) {
                    return error("第" + (i + 2) + "行仓库名称为空");
                }
                Warehouses warehouses = warehousesMapper.selectWarehousesByName(warehouseName);
                if (warehouses == null) {
                    return error("第" + (i + 2) + "行仓库未找到：" + warehouseName);
                }

                if (StringUtils.isEmpty(locationName)) {
                    return error("第" + (i + 2) + "行库位名称为空");
                }
                StorageLocations location = storageLocationsMapper.selectStorageLocationsByNameAndWarehouse(locationName, warehouses.getId());
                if (location == null) {
                    return error("第" + (i + 2) + "行库位未找到：" + locationName + "（仓库：" + warehouseName + "）");
                }

                Integer qty = parseInteger(planQtyStr, "计划数量", i);
                Double unitWeight = parseDouble(unitWeightStr);
                Double totalWeight = parseDouble(secondWeightStr);

                Inventory inventory = new Inventory();
                inventory.setId(UUID.randomUUID().toString());
                inventory.setInventoryType(1L);
                inventory.setOrderId(null);
                inventory.setMaterialId(materials.getId());
                inventory.setBatchId(batchId);
                inventory.setWarehousesCode(warehouses.getWarehousesCode());
                inventory.setLocationId(location.getId());
                inventory.setQuantity(qty == null ? 0 : qty.longValue());
                inventory.setLockedQuantity(0L);
                inventory.setUnitWeight(unitWeight == null ? null : Math.round(unitWeight));
                inventory.setTotalWeight(totalWeight == null ? null : Math.round(totalWeight));
                inventory.setInventoryStatus(1L);
                inventory.setIsUsed(1L);
                inventory.setCreateTime(new Date());
                inventory.setLastInboundTime(parseDate(sdf, dateStr));

                toInsert.add(inventory);
            }

            int count = inventoryService.insertInventoryList(toInsert);
            return success("导入成功，新增记录数：" + count);
        } catch (IOException e) {
            return error("读取文件失败：" + e.getMessage());
        }
    }

    private Integer parseInteger(String val, String field, int rowIndex) {
        if (StringUtils.isEmpty(val)) {
            return null;
        }
        try {
            return (int) Double.parseDouble(val);
        } catch (NumberFormatException e) {
            throw new IllegalArgumentException("第" + (rowIndex + 2) + "行" + field + "格式错误：" + val);
        }
    }

    private Double parseDouble(String val) {
        if (StringUtils.isEmpty(val)) {
            return null;
        }
        try {
            return Double.parseDouble(val);
        } catch (NumberFormatException e) {
            return null;
        }
    }

    private Date parseDate(SimpleDateFormat sdf, String val) {
        if (StringUtils.isEmpty(val)) {
            return null;
        }
        try {
            return sdf.parse(val);
        } catch (ParseException e) {
            return null;
        }
    }

    /**
     * 统计库存物料超出预警值
     */
    @GetMapping("/exceed")
    public AjaxResult exceedWarnValue()
    {
        List<InventoryExceedWarnVO> list = inventoryService.selectInventoryExceedWarnList();
        return AjaxResult.success(list);
    }


    /**
     * 本月库存物料top10库存
     */
    @PostMapping("/inventoryTopTenByAmount")
    public TableDataInfo inventoryTopTenByAmount()
    {
        startPage();
        List<Map<String,String>> list = inventoryService.inventoryTopTenByAmount();
        return getDataTable(list);
    }
    /**
     * 本月库存物料top10金额
     */
    @PostMapping("/inventoryTopTenByQuantity")
    public TableDataInfo inventoryTopTenByQuantity()
    {
        startPage();
        List<Map<String,String>> list = inventoryService.inventoryTopTenByQuantity();
        return getDataTable(list);
    }
}
