package org.dromara.ems.info.controller;

import cn.idev.excel.FastExcel;
import cn.idev.excel.context.AnalysisContext;
import cn.idev.excel.event.AnalysisEventListener;
import org.dromara.common.log.annotation.Log;
import org.dromara.ems.common.web.EmsBaseController;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.utils.file.FileUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.ems.info.domain.SparePartsInventory;
import org.dromara.ems.info.domain.SparePartsInventoryExportVO;
import org.dromara.ems.info.service.ISparePartsInventoryService;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import cn.dev33.satoken.annotation.SaCheckPermission;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.*;

/**
 * 备件库记录主Controller
 * 
 * @author Yinq
 * @date 2024-12-13
 */
@RestController
@RequiredArgsConstructor

@RequestMapping("/ems/info/sparePartsInventory")
public class SparePartsInventoryController extends EmsBaseController
{

    private final ISparePartsInventoryService sparePartsInventoryService;

    /**
     * 查询备件库记录主列表
     */
    @SaCheckPermission("ems/info:sparePartsInventory:list")
    @GetMapping("/list")
    public TableDataInfo list(SparePartsInventory sparePartsInventory)
    {
        startPage();
        List<SparePartsInventory> list = sparePartsInventoryService.selectSparePartsInventoryList(sparePartsInventory);
        return getDataTable(list);
    }

    /**
     * 导出备件库记录主列表（支持动态列）
     */
    @SaCheckPermission("ems/info:sparePartsInventory:export")
    @Log(title = "备件库记录主", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, SparePartsInventory sparePartsInventory) throws IOException
    {
        List<SparePartsInventoryExportVO> list = sparePartsInventoryService.selectSparePartsInventoryExportList(sparePartsInventory);
        List<String> headers = buildExportHeaders(list);
        List<List<String>> head = headers.stream().map(Collections::singletonList).toList();
        List<List<Object>> rows = buildExportRows(list, headers);

        FileUtils.setAttachmentResponseHeader(response, "sparePartsInventory.xlsx");
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8");

        // 这里改为直接复用项目已有的 FastExcel 依赖，避免 EMS 控制器继续显式绑定 Apache POI。
        FastExcel.write(response.getOutputStream())
            .autoCloseStream(false)
            .head(head)
            .sheet("备件库记录")
            .doWrite(rows);
    }

    /**
     * 查询备件库记录主列表（包含动态列）
     */
    @SaCheckPermission("ems/info:sparePartsInventory:list")
    @GetMapping("/listWithDynamicColumns")
    public TableDataInfo listWithDynamicColumns(SparePartsInventory sparePartsInventory)
    {
        startPage();
        List<SparePartsInventoryExportVO> list = sparePartsInventoryService.selectSparePartsInventoryExportList(sparePartsInventory);
        return getDataTable(list);
    }

    /**
     * 获取备件库记录主详细信息
     */
    @SaCheckPermission("ems/info:sparePartsInventory:query")
    @GetMapping(value = "/{objid}")
    public R<?> getInfo(@PathVariable("objid") Long objid)
    {
        return success(sparePartsInventoryService.selectSparePartsInventoryByObjid(objid));
    }

    /**
     * 获取备件库记录主详细信息（包含动态列）
     */
    @SaCheckPermission("ems/info:sparePartsInventory:query")
    @GetMapping(value = "/withDynamicColumns/{objid}")
    public R<?> getInfoWithDynamicColumns(@PathVariable("objid") Long objid)
    {
        SparePartsInventoryExportVO vo = sparePartsInventoryService.selectSparePartsInventoryWithChecksByObjid(objid);
        return R.ok(vo);
    }

    /**
     * 新增备件库记录主
     */
    @SaCheckPermission("ems/info:sparePartsInventory:add")
    @Log(title = "备件库记录主", businessType = BusinessType.INSERT)
    @PostMapping
    public R<?> add(@RequestBody SparePartsInventory sparePartsInventory)
    {
        return toAjax(sparePartsInventoryService.insertSparePartsInventory(sparePartsInventory));
    }

    /**
     * 新增备件库记录主（包含动态列）
     */
    @SaCheckPermission("ems/info:sparePartsInventory:add")
    @Log(title = "备件库记录主", businessType = BusinessType.INSERT)
    @PostMapping("/withDynamicColumns")
    public R<?> addWithDynamicColumns(@RequestBody SparePartsInventoryExportVO sparePartsInventoryVO)
    {
        return toAjax(sparePartsInventoryService.insertSparePartsInventoryWithDynamicColumns(sparePartsInventoryVO));
    }

    /**
     * 修改备件库记录主
     */
    @SaCheckPermission("ems/info:sparePartsInventory:edit")
    @Log(title = "备件库记录主", businessType = BusinessType.UPDATE)
    @PutMapping
    public R<?> edit(@RequestBody SparePartsInventory sparePartsInventory)
    {
        return toAjax(sparePartsInventoryService.updateSparePartsInventory(sparePartsInventory));
    }

    /**
     * 修改备件库记录主（包含动态列）
     */
    @SaCheckPermission("ems/info:sparePartsInventory:edit")
    @Log(title = "备件库记录主", businessType = BusinessType.UPDATE)
    @PutMapping("/withDynamicColumns")
    public R<?> editWithDynamicColumns(@RequestBody SparePartsInventoryExportVO sparePartsInventoryVO)
    {
        return toAjax(sparePartsInventoryService.updateSparePartsInventoryWithDynamicColumns(sparePartsInventoryVO));
    }

    /**
     * 获取所有动态列名
     */
    @SaCheckPermission("ems/info:sparePartsInventory:list")
    @GetMapping("/dynamicColumns")
    public R<?> getDynamicColumns()
    {
        List<String> columns = sparePartsInventoryService.getAllCheckNames();
        return R.ok(columns);
    }

    /**
     * 删除备件库记录主
     */
    @SaCheckPermission("ems/info:sparePartsInventory:remove")
    @Log(title = "备件库记录主", businessType = BusinessType.DELETE)
	@DeleteMapping("/{objids}")
    public R<?> remove(@PathVariable Long[] objids)
    {
        return toAjax(sparePartsInventoryService.deleteSparePartsInventoryByObjids(objids));
    }

    /**
     * 导入备件库记录主数据（支持动态列）
     */
    @SaCheckPermission("ems/info:sparePartsInventory:add")
    @Log(title = "备件库记录主", businessType = BusinessType.IMPORT)
    @PostMapping("/importData")
    public R<?> importData(MultipartFile file, @RequestParam(value = "updateSupport", defaultValue = "false") boolean updateSupport) throws Exception
    {
        List<SparePartsInventoryExportVO> dataList = parseExcelWithDynamicColumns(file);
        String message = sparePartsInventoryService.importSparePartsInventoryWithDynamicColumns(dataList, updateSupport, getUsername());
        return R.ok(message);
    }

    /**
     * 解析包含动态列的Excel文件
     */
    private List<SparePartsInventoryExportVO> parseExcelWithDynamicColumns(MultipartFile file) throws Exception {
        DynamicInventoryImportListener listener = new DynamicInventoryImportListener();
        FastExcel.read(file.getInputStream(), listener).autoCloseStream(false).sheet().doRead();
        return listener.getDataList();
    }

    /**
     * 获取备件库记录主导入模板
     */
    @SaCheckPermission("ems/info:sparePartsInventory:add")
    @PostMapping("/importTemplate")
    public void importTemplate(HttpServletResponse response)
    {
        ExcelUtil.exportExcel(new ArrayList<>(), "备件库记录主数据", SparePartsInventory.class, response);
    }

    private List<String> buildExportHeaders(List<SparePartsInventoryExportVO> list) {
        List<String> headers = new ArrayList<>(List.of("主键", "入库时间", "采购方式", "库存位置", "物品名称", "原厂编号", "型号", "入库数量", "剩余数量", "库存阈值", "备注"));
        Set<String> dynamicHeaders = new TreeSet<>();
        for (SparePartsInventoryExportVO vo : list) {
            if (vo.getCheckData() != null) {
                dynamicHeaders.addAll(vo.getCheckData().keySet());
            }
        }
        headers.addAll(dynamicHeaders);
        return headers;
    }

    private List<List<Object>> buildExportRows(List<SparePartsInventoryExportVO> list, List<String> headers) {
        List<List<Object>> rows = new ArrayList<>();
        for (SparePartsInventoryExportVO vo : list) {
            List<Object> row = new ArrayList<>();
            row.add(vo.getObjid());
            row.add(vo.getWarehouseDate());
            row.add(vo.getPurchaseMethod());
            row.add(vo.getStorageLocation());
            row.add(vo.getItemName());
            row.add(vo.getOriginalPartNumber());
            row.add(vo.getModel());
            row.add(vo.getWarehouseQuantity());
            row.add(vo.getRemainingQuantity());
            row.add(vo.getThreshold());
            row.add(vo.getRemarks());
            for (int i = 11; i < headers.size(); i++) {
                row.add(vo.getCheckValue(headers.get(i)));
            }
            rows.add(row);
        }
        return rows;
    }

    private static class DynamicInventoryImportListener extends AnalysisEventListener<Map<Integer, String>> {

        private final List<SparePartsInventoryExportVO> dataList = new ArrayList<>();
        private Map<Integer, String> headMap = Collections.emptyMap();

        @Override
        public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
            this.headMap = new LinkedHashMap<>(headMap);
        }

        @Override
        public void invoke(Map<Integer, String> data, AnalysisContext context) {
            SparePartsInventoryExportVO vo = new SparePartsInventoryExportVO();
            for (Map.Entry<Integer, String> entry : headMap.entrySet()) {
                String columnName = entry.getValue();
                String cellValue = trimToNull(data.get(entry.getKey()));
                if (cellValue == null) {
                    continue;
                }
                switch (columnName) {
                    case "主键" -> vo.setObjid(parseLong(cellValue));
                    case "入库时间" -> vo.setWarehouseDate(cellValue);
                    case "采购方式" -> vo.setPurchaseMethod(cellValue);
                    case "库存位置" -> vo.setStorageLocation(cellValue);
                    case "物品名称" -> vo.setItemName(cellValue);
                    case "原厂编号" -> vo.setOriginalPartNumber(cellValue);
                    case "型号" -> vo.setModel(cellValue);
                    case "入库数量" -> vo.setWarehouseQuantity(parseLong(cellValue));
                    case "剩余数量" -> vo.setRemainingQuantity(parseLong(cellValue));
                    case "库存阈值" -> vo.setThreshold(parseLong(cellValue));
                    case "备注" -> vo.setRemarks(cellValue);
                    default -> vo.setCheckValue(columnName, parseLong(cellValue));
                }
            }
            dataList.add(vo);
        }

        @Override
        public void doAfterAllAnalysed(AnalysisContext context) {
        }

        public List<SparePartsInventoryExportVO> getDataList() {
            return dataList;
        }

        private static Long parseLong(String value) {
            if (value == null || value.isBlank()) {
                return null;
            }
            return Long.parseLong(value.trim().contains(".") ? value.substring(0, value.indexOf('.')) : value.trim());
        }

        private static String trimToNull(String value) {
            if (value == null) {
                return null;
            }
            String trimmed = value.trim();
            return trimmed.isEmpty() ? null : trimmed;
        }
    }
}
