package com.ruoyi.inventory.controller;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import javax.servlet.http.HttpServletResponse;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.ruoyi.asset.domain.TbAssetInformation;
import com.ruoyi.inventory.domain.TbAssetInventory;
import com.ruoyi.inventory.domain.TbInventoryCompare;
import com.ruoyi.inventory.domain.TbInventoryCompareResult;
import com.ruoyi.inventory.domain.dto.AssetInventoryStatement;
import com.ruoyi.inventory.domain.dto.AssetInventoryStatement2;
import com.ruoyi.inventory.domain.dto.AssetInventoryStatementDetail;
import com.ruoyi.inventory.domain.dto.InventoryCompareDTO;
import com.ruoyi.inventory.domain.enums.InventoryPlanResult;
import com.ruoyi.inventory.domain.enums.InventoryResult;
import com.ruoyi.inventory.domain.enums.InventoryStatus;
import com.ruoyi.inventory.mapper.TbInventoryDetailMapper;
import com.ruoyi.inventory.service.ITbAssetInventoryService;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.inventory.domain.TbInventoryDetail;
import com.ruoyi.inventory.service.ITbInventoryDetailService;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.core.page.TableDataInfo;

/**
 * 资产盘点明细Controller
 * 
 * @author ydl
 * @date 2023-06-01
 */
@RestController
@RequestMapping("/inventory/detail")
public class TbInventoryDetailController extends BaseController
{
    @Autowired
    private ITbInventoryDetailService tbInventoryDetailService;

    /**
     * 查询资产盘点明细列表
     */
    @PreAuthorize("@ss.hasPermi('inventory:detail:list')")
    @GetMapping("/list")
    public TableDataInfo list(TbInventoryDetail tbInventoryDetail)
    {
        startPage();
        List<TbInventoryDetail> list = tbInventoryDetailService.selectTbInventoryDetailList(tbInventoryDetail);
        return getDataTable(list);
    }

    /**
     * 查询全单位或者部门的资产对比分析报表
     * @return
     */
//    @PreAuthorize("@ss.hasPermi('inventory:compare:list')")
//    @GetMapping("/getDepAssetLossTb")
//    public TableDataInfo compareList(@RequestParam(required = false) String deptId){
//        startPage();
//        TbInventoryCompareResult tbInventoryCompareResult = new TbInventoryCompareResult();
//        List<TbInventoryCompareResult> tbInventoryCompareResultList = new ArrayList<>();
//
//        List<TbAssetInventory> tbAssetInventoryList = tbInventoryDetailService.selectTbInventoryCompareList(deptId);
//        if(tbAssetInventoryList.size() == 0){
//            throw new RuntimeException("该组织不存在盘点完毕的盘点或者该部门不存在盘点完毕的盘点");
//        }
//        if(tbAssetInventoryList.size() == 1){
//            throw new RuntimeException("该组织只存在一个盘点，不能进行盘点间类别数量损耗对比");
//        }
//
//        //最近一次盘点
//        String orderNumber = tbAssetInventoryList.get(0).getOrderNumber();
//        if (StrUtil.isBlank(orderNumber)) {
//            throw new RuntimeException("盘点计划编码不能为空");
//        }
//        List<TbInventoryDetail> tbInventoryDetailList1 = tbInventoryDetailMapper.selectTbInventoryDetailByOrderNumber(orderNumber);
//        List<AssetInventoryStatement> inventoryStatement1 = getInventoryStatement(tbAssetInventoryList.get(0), tbInventoryDetailList1);
//        List<TbInventoryCompare> tbInventoryCompareList = getTbInventoryCompareList(inventoryStatement1);
//        double total = 0.0;
//        for (TbInventoryCompare tbInventoryCompare : tbInventoryCompareList) {
//            total = tbInventoryCompare.getLossVal()+total;
//        }
//        tbInventoryCompareResult.setDate(tbAssetInventoryList.get(0).getInventoryDate());
//        tbInventoryCompareResult.setAssetResultList(tbInventoryCompareList);
//        tbInventoryCompareResult.setInventoryDepartment(tbAssetInventoryList.get(0).getInventoryDepartmentName());
//        tbInventoryCompareResult.setLossTotal(total);
//        tbInventoryCompareResultList.add(tbInventoryCompareResult);
//
//        //最近一次的上一次盘点
//        TbInventoryCompareResult tbInventoryCompareResult2 = new TbInventoryCompareResult();
//        orderNumber = tbAssetInventoryList.get(1).getOrderNumber();
//        if (StrUtil.isBlank(orderNumber)) {
//            throw new RuntimeException("盘点计划编码不能为空");
//        }
//        List<TbInventoryDetail> tbInventoryDetailList2 = tbInventoryDetailMapper.selectTbInventoryDetailByOrderNumber(orderNumber);
//        List<AssetInventoryStatement> inventoryStatement2 = getInventoryStatement(tbAssetInventoryList.get(0), tbInventoryDetailList2);
//        List<TbInventoryCompare> tbInventoryCompareList2 = getTbInventoryCompareList(inventoryStatement2);
//        total = 0.0;
//        for (TbInventoryCompare tbInventoryCompare : tbInventoryCompareList2) {
//            total = tbInventoryCompare.getLossVal()+total;
//        }
//        tbInventoryCompareResult2.setDate(tbAssetInventoryList.get(0).getInventoryDate());
//        tbInventoryCompareResult2.setAssetResultList(tbInventoryCompareList2);
//        tbInventoryCompareResult2.setInventoryDepartment(tbAssetInventoryList.get(1).getInventoryDepartmentName());
//        tbInventoryCompareResult2.setLossTotal(total);
//        tbInventoryCompareResultList.add(tbInventoryCompareResult2);
//
//        return getDataTable(tbInventoryCompareResultList);
//    }

    @Autowired
    private ITbAssetInventoryService inventoryService;

    /**
     * 导出资产盘点明细列表
     */
    @PreAuthorize("@ss.hasPermi('inventory:detail:export')")
    @Log(title = "资产盘点明细", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, TbInventoryDetail tbInventoryDetail)
    {
        List<TbInventoryDetail> list = tbInventoryDetailService.selectTbInventoryDetailList(tbInventoryDetail);

        String orderNumber = tbInventoryDetail.getOrderNumber();
        if (StrUtil.isBlank(orderNumber)) {
            throw new RuntimeException("盘点计划编码不能为空");
        }

        TbAssetInventory tbAssetInventory = inventoryService.selectTbAssetInventoryByNumber(orderNumber);

        List<AssetInventoryStatement> assetInventoryStatements = getInventoryStatement(tbAssetInventory, list);

        ExcelUtil<AssetInventoryStatement> util = new ExcelUtil<>(AssetInventoryStatement.class);

        util.exportExcel(response, assetInventoryStatements, DateUtil.format(tbAssetInventory.getInventoryDate(), "yyyy年MM月dd日"), tbAssetInventory.getName());
    }

    /**
     * 导出资产盘点记录列表
     */
    @PreAuthorize("@ss.hasPermi('inventory:inventory:export')")
    @Log(title = "资产盘点报表", businessType = BusinessType.EXPORT)
    @PostMapping("/export/detail")
    public void exportDetail(HttpServletResponse response, TbAssetInventory tbAssetInventory)
    {
        List<TbAssetInventory> tbAssetInventoryList = inventoryService.selectTbAssetInventoryList(tbAssetInventory);
        List<AssetInventoryStatement2> assetInventoryStatements = new ArrayList<>();

        for (TbAssetInventory assetInventory : tbAssetInventoryList) {
            String orderNumber = assetInventory.getOrderNumber();

            List<TbInventoryDetail> tbInventoryDetails = tbInventoryDetailService.selectTbInventoryDetailByOrderNumber(orderNumber);
            AssetInventoryStatement2 assetInventoryStatement = getInventoryStatement2(assetInventory, tbInventoryDetails);
            assetInventoryStatements.add(assetInventoryStatement);
        }

        ExcelUtil<AssetInventoryStatement2> util = new ExcelUtil<>(AssetInventoryStatement2.class);

        util.exportExcel(response, assetInventoryStatements, "资产盘点报表");
    }

    /**
     * 导出全单位或者部门的资产对比分析报表
     * @param response
     */
//    @PreAuthorize("@ss.hasPermi('inventory:compare:export')")
//    @Log(title = "全单位资产对比分析报表", businessType = BusinessType.EXPORT)
//    @PostMapping("/exportDepAssetLossTb")
//    public void exportCompare(HttpServletResponse response,@RequestParam(required = false) String deptId){
//        TbInventoryCompareResult tbInventoryCompareResult = new TbInventoryCompareResult();
//        List<TbInventoryCompareResult> tbInventoryCompareResultList = new ArrayList<>();
//
//        List<TbAssetInventory> tbAssetInventoryList = tbInventoryDetailService.selectTbInventoryCompareList(deptId);
//        if(tbAssetInventoryList.size() == 0){
//            throw new RuntimeException("该组织不存在盘点完毕的盘点或者该部门不参在盘点完毕的盘点");
//        }
//        if(tbAssetInventoryList.size() == 1){
//            throw new RuntimeException("该组织只存在一个盘点，不能进行盘点间类别数量损耗对比");
//        }
//
//        //最近一次盘点
//        String orderNumber = tbAssetInventoryList.get(0).getOrderNumber();
//        if (StrUtil.isBlank(orderNumber)) {
//            throw new RuntimeException("盘点计划编码不能为空");
//        }
//        List<TbInventoryDetail> tbInventoryDetailList1 = tbInventoryDetailMapper.selectTbInventoryDetailByOrderNumber(orderNumber);
//        List<AssetInventoryStatement> inventoryStatement1 = getInventoryStatement(tbAssetInventoryList.get(0), tbInventoryDetailList1);
//        List<TbInventoryCompare> tbInventoryCompareList = getTbInventoryCompareList(inventoryStatement1);
//        double total = 0.0;
//        for (TbInventoryCompare tbInventoryCompare : tbInventoryCompareList) {
//            total = tbInventoryCompare.getLossVal()+total;
//        }
//        tbInventoryCompareResult.setDate(tbAssetInventoryList.get(0).getInventoryDate());
//        tbInventoryCompareResult.setAssetResultList(tbInventoryCompareList);
//        tbInventoryCompareResult.setInventoryDepartment(tbAssetInventoryList.get(0).getInventoryDepartmentName());
//        tbInventoryCompareResult.setLossTotal(total);
//        tbInventoryCompareResultList.add(tbInventoryCompareResult);
//
//        //最近一次的上一次盘点
//        TbInventoryCompareResult tbInventoryCompareResult2 = new TbInventoryCompareResult();
//        orderNumber = tbAssetInventoryList.get(1).getOrderNumber();
//        if (StrUtil.isBlank(orderNumber)) {
//            throw new RuntimeException("盘点计划编码不能为空");
//        }
//        List<TbInventoryDetail> tbInventoryDetailList2 = tbInventoryDetailMapper.selectTbInventoryDetailByOrderNumber(orderNumber);
//        List<AssetInventoryStatement> inventoryStatement2 = getInventoryStatement(tbAssetInventoryList.get(0), tbInventoryDetailList2);
//        List<TbInventoryCompare> tbInventoryCompareList2 = getTbInventoryCompareList(inventoryStatement2);
//        total = 0.0;
//        for (TbInventoryCompare tbInventoryCompare : tbInventoryCompareList2) {
//            total = tbInventoryCompare.getLossVal()+total;
//        }
//        tbInventoryCompareResult2.setDate(tbAssetInventoryList.get(0).getInventoryDate());
//        tbInventoryCompareResult2.setAssetResultList(tbInventoryCompareList2);
//        tbInventoryCompareResult2.setInventoryDepartment(tbAssetInventoryList.get(1).getInventoryDepartmentName());
//        tbInventoryCompareResult2.setLossTotal(total);
//        tbInventoryCompareResultList.add(tbInventoryCompareResult2);
//
//        ExcelUtil<TbInventoryCompareResult> util = new ExcelUtil<>(TbInventoryCompareResult.class);
//
//        util.exportExcel(response, tbInventoryCompareResultList , "资产对比分析报表");
//    }

    /**
     * 获取盘点报表
     *
     * @param tbAssetInventory 盘点计划信息
     * @param list 盘点详细列表
     * @return 盘点报表列表
     */
    private List<AssetInventoryStatement> getInventoryStatement(TbAssetInventory tbAssetInventory, List<TbInventoryDetail> list) {
        List<AssetInventoryStatement> assetInventoryStatements = new ArrayList<>();

        for (TbInventoryDetail inventoryDetail : list) {
            AssetInventoryStatement assetInventoryStatement = new AssetInventoryStatement();
            // 设置盘点编码
            assetInventoryStatement.setOrderNumber(tbAssetInventory.getOrderNumber());

            // 设置计划名称
            assetInventoryStatement.setOrderName(tbAssetInventory.getName());

            // 设置盘点部门
            assetInventoryStatement.setInventoryDepartmentName(tbAssetInventory.getInventoryDepartmentName());

            // 解析资产信息
            TbAssetInformation assetInformation = JSONUtil.toBean(inventoryDetail.getInventoryMetadata(), TbAssetInformation.class);

            // 设置资产编码
            assetInventoryStatement.setAssetNumber(assetInformation.getNumber());

            // 设置资产名称
            assetInventoryStatement.setAssetName(assetInformation.getName());

            // 设置所在位置
//            String ancestorLocationName = assetInformation.getAncestorLocationName();
//            if (StrUtil.isBlank(ancestorLocationName)) {
//                ancestorLocationName = "";
//            }
//            String parentLocationName = assetInformation.getParentLocationName();
//            if (StrUtil.isBlank(parentLocationName)) {
//                parentLocationName = "";
//            }
            String locationName = assetInformation.getLocationName();
//            assetInventoryStatement.setAssetLocation(ancestorLocationName + parentLocationName + locationName);
            assetInventoryStatement.setAssetLocation(locationName);

            // 设置资产分类
            String categoryName = assetInformation.getCategoryName();
            assetInventoryStatement.setAssetCategory(categoryName);

            // 设置盘点状态
            Integer inventoryStatus = inventoryDetail.getInventoryStatus();
            String inventoryStatusName = InventoryStatus.getName(inventoryStatus);
            assetInventoryStatement.setInventoryStatus(inventoryStatusName);

            // 设置资产数量
            Integer quantity = assetInformation.getQuantity();
            assetInventoryStatement.setQuantity(quantity);

            // 设置盘点数量
            Integer inventoryQuantity = inventoryDetail.getInventoryQuantity();
            assetInventoryStatement.setInventoryQuantity(inventoryQuantity);

            int difference = inventoryQuantity - quantity;
            String differenceQuantity = (difference <= 0 ? "" : "+") + difference;
            assetInventoryStatement.setDifferenceQuantity(differenceQuantity);

            // 设置计量单位
            assetInventoryStatement.setUnits(assetInformation.getUnits());

            // 设置盘点结果
            Integer inventoryResult = inventoryDetail.getInventoryResult();
            String inventoryResultName = InventoryResult.getName(inventoryResult);
            assetInventoryStatement.setInventoryResult(inventoryResultName);

            // 设置盘点位置
            assetInventoryStatement.setInventoryLocation(tbAssetInventory.getInventoryLocationName());

            // 设置盘点时间
            assetInventoryStatement.setInventoryDate(tbAssetInventory.getInventoryDate());

            // 设置盘点计划结果
            Integer inventoryPlanResult = tbAssetInventory.getInventoryResult();
            String inventoryPlanResultName = InventoryPlanResult.getName(inventoryPlanResult);
            assetInventoryStatement.setInventoryPlanResult(inventoryPlanResultName);

            // 设置资产原值
            assetInventoryStatement.setOriginalValue(assetInformation.getOriginalValue());

            // 设置备注
            assetInventoryStatement.setRemark(inventoryDetail.getRemark());

            assetInventoryStatements.add(assetInventoryStatement);
        }

        return assetInventoryStatements;
    }

    private AssetInventoryStatement2 getInventoryStatement2(TbAssetInventory tbAssetInventory, List<TbInventoryDetail> list) {
        AssetInventoryStatement2 assetInventoryStatement = new AssetInventoryStatement2();

        // 设置盘点编码
        assetInventoryStatement.setOrderNumber(tbAssetInventory.getOrderNumber());

        // 设置计划名称
        assetInventoryStatement.setOrderName(tbAssetInventory.getName());

        // 设置盘点部门
        assetInventoryStatement.setInventoryDepartmentName(tbAssetInventory.getInventoryDepartmentName());

        // 设置盘点位置
        assetInventoryStatement.setInventoryLocation(tbAssetInventory.getInventoryLocationName());

        // 设置盘点时间
        assetInventoryStatement.setInventoryDate(tbAssetInventory.getInventoryDate());

        // 设置盘点计划结果
        Integer inventoryPlanResult = tbAssetInventory.getInventoryResult();
        String inventoryPlanResultName = InventoryPlanResult.getName(inventoryPlanResult);
        assetInventoryStatement.setInventoryPlanResult(inventoryPlanResultName);

        List<AssetInventoryStatementDetail> assetInventoryStatementDetailList = new ArrayList<>();

        for (TbInventoryDetail inventoryDetail : list) {
            AssetInventoryStatementDetail assetInventoryStatementDetail = new AssetInventoryStatementDetail();

            // 解析资产信息
            TbAssetInformation assetInformation = JSONUtil.toBean(inventoryDetail.getInventoryMetadata(), TbAssetInformation.class);

            // 设置资产编码
            assetInventoryStatementDetail.setAssetNumber(assetInformation.getNumber());

            // 设置资产名称
            assetInventoryStatementDetail.setAssetName(assetInformation.getName());

            // 设置所在位置
//            String ancestorLocationName = assetInformation.getAncestorLocationName();
//            if (StrUtil.isBlank(ancestorLocationName)) {
//                ancestorLocationName = "";
//            }
//            String parentLocationName = assetInformation.getParentLocationName();
//            if (StrUtil.isBlank(parentLocationName)) {
//                parentLocationName = "";
//            }
            String locationName = assetInformation.getLocationName();
//            assetInventoryStatement.setAssetLocation(ancestorLocationName + parentLocationName + locationName);
            assetInventoryStatementDetail.setAssetLocation(locationName);

            // 设置资产分类
            String categoryName = assetInformation.getCategoryName();
            assetInventoryStatementDetail.setAssetCategory(categoryName);

            // 设置盘点状态
            Integer inventoryStatus = inventoryDetail.getInventoryStatus();
            String inventoryStatusName = InventoryStatus.getName(inventoryStatus);
            assetInventoryStatementDetail.setInventoryStatus(inventoryStatusName);

            // 设置资产数量
            Integer quantity = assetInformation.getQuantity();
            assetInventoryStatementDetail.setQuantity(quantity);

            // 设置盘点数量
            Integer inventoryQuantity = inventoryDetail.getInventoryQuantity();
            assetInventoryStatementDetail.setInventoryQuantity(inventoryQuantity);

            int difference = inventoryQuantity - quantity;
            String differenceQuantity = (difference <= 0 ? "" : "+") + difference;
            assetInventoryStatementDetail.setDifferenceQuantity(differenceQuantity);

            // 设置计量单位
            assetInventoryStatementDetail.setUnits(assetInformation.getUnits());

            // 设置盘点结果
            Integer inventoryResult = inventoryDetail.getInventoryResult();
            String inventoryResultName = InventoryResult.getName(inventoryResult);
            assetInventoryStatementDetail.setInventoryResult(inventoryResultName);

            // 设置资产原值
            assetInventoryStatementDetail.setOriginalValue(assetInformation.getOriginalValue());

            // 设置备注
            assetInventoryStatementDetail.setRemark(inventoryDetail.getRemark());

            assetInventoryStatementDetailList.add(assetInventoryStatementDetail);
        }

        assetInventoryStatement.setAssetInventoryStatementDetailList(assetInventoryStatementDetailList);

        return assetInventoryStatement;
    }

    /**
     * 获取资产盘点明细详细信息
     */
    @PreAuthorize("@ss.hasPermi('inventory:detail:query')")
    @GetMapping(value = "/{id}")
    public AjaxResult getInfo(@PathVariable("id") Long id)
    {
        return success(tbInventoryDetailService.selectTbInventoryDetailById(id));
    }

    /**
     * 新增资产盘点明细
     */
    @PreAuthorize("@ss.hasPermi('inventory:detail:add')")
    @Log(title = "资产盘点明细", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody TbInventoryDetail tbInventoryDetail)
    {
        return toAjax(tbInventoryDetailService.insertTbInventoryDetail(tbInventoryDetail));
    }

    /**
     * 修改资产盘点明细
     */
    @PreAuthorize("@ss.hasPermi('inventory:detail:edit')")
    @Log(title = "资产盘点明细", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody TbInventoryDetail tbInventoryDetail)
    {
        return toAjax(tbInventoryDetailService.updateTbInventoryDetail(tbInventoryDetail));
    }

    /**
     * 删除资产盘点明细
     */
    @PreAuthorize("@ss.hasPermi('inventory:detail:remove')")
    @Log(title = "资产盘点明细", businessType = BusinessType.DELETE)
	@DeleteMapping("/{ids}")
    public AjaxResult remove(@PathVariable Long[] ids)
    {
        return toAjax(tbInventoryDetailService.deleteTbInventoryDetailByIds(ids));
    }

    /**
     * 获取全单位资产对比分析报表
     * @param inventoryStatementList
     * @return
     */
    private List<TbInventoryCompare> getTbInventoryCompareList
            (List<AssetInventoryStatement> inventoryStatementList){
        List<TbInventoryCompare> tbInventoryCompareList = new ArrayList<>();

        for (AssetInventoryStatement assetInventoryStatement : inventoryStatementList) {
            String inventoryStatus = assetInventoryStatement.getInventoryStatus();
            if(inventoryStatus.equals("已盘点")) {
                TbInventoryCompare tbInventoryCompare = new TbInventoryCompare();
                String assetName = assetInventoryStatement.getAssetName();
                String inventoryLocation = assetInventoryStatement.getAssetLocation();
                Integer quantity = assetInventoryStatement.getQuantity();
                Integer inventoryQuantity = assetInventoryStatement.getInventoryQuantity();
                tbInventoryCompare.setInventoryName(assetName);
                tbInventoryCompare.setInventoryLocationName(inventoryLocation);
                tbInventoryCompare.setExpectInventoryNumber(quantity);
                tbInventoryCompare.setRealityInventoryNumber(inventoryQuantity);
                if(quantity>inventoryQuantity){
                    tbInventoryCompare.setLossNumber(quantity - inventoryQuantity);
                    tbInventoryCompare.setLossVal(assetInventoryStatement.getOriginalValue()*(quantity - inventoryQuantity));

                }else {
                    tbInventoryCompare.setLossNumber(0);
                    tbInventoryCompare.setLossVal(0.0);
                }
                tbInventoryCompare.setUnits(assetInventoryStatement.getUnits());
                tbInventoryCompareList.add(tbInventoryCompare);
            }
        }
        return tbInventoryCompareList;
    }
}
