package com.yiqi.admin.controller.core;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.yiqi.common.core.page.TableDataInfo;
import com.yiqi.common.exception.ServiceException;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yiqi.common.constant.UrlConstants;
import com.yiqi.common.core.controller.BaseController;
import com.yiqi.common.core.domain.BaseEntity;
import com.yiqi.common.core.domain.R;
import com.yiqi.common.enums.SettlementStatusType;
import com.yiqi.common.enums.SourceType;
import com.yiqi.common.enums.StatusType;
import com.yiqi.common.utils.DateUtils;
import com.yiqi.common.utils.SecurityUtils;
import com.yiqi.common.utils.bean.BeanUtils;
import com.yiqi.core.domain.SettlementBalanceRecord;
import com.yiqi.core.domain.SettlementManageBill;
import com.yiqi.core.domain.SettlementManageFactory;
import com.yiqi.core.domain.SettlementManageStore;
import com.yiqi.core.domain.dto.SettlementBillAddDTO;
import com.yiqi.core.domain.dto.SettlementBillListQueryDTO;
import com.yiqi.core.domain.dto.SettlementListQueryDTO;
import com.yiqi.core.domain.dto.SettlementStoreSubmitDTO;
import com.yiqi.core.domain.vo.SettlementManageFactoryQueryVO;
import com.yiqi.core.domain.vo.SettlementManageStoreInfoVO;
import com.yiqi.core.domain.vo.SettlementManageStoreQueryVO;
import com.yiqi.core.service.ISettlementBalanceRecordService;
import com.yiqi.core.service.ISettlementManageBillService;
import com.yiqi.core.service.ISettlementManageFactoryService;
import com.yiqi.core.service.ISettlementManageStoreService;
import com.yiqi.system.domain.ManageFactory;
import com.yiqi.system.domain.SysSettlementRate;
import com.yiqi.system.domain.SysStore;
import com.yiqi.system.service.IManageFactoryService;
import com.yiqi.system.service.ISysSettlementRateService;
import com.yiqi.system.service.ISysStoreService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 结算管理Controller
 *
 * @author ruoyi
 * @date 2024-02-15
 */
@Api(tags = "管理后台 - 结算账单管理")
@RestController
@RequestMapping(UrlConstants.managerApi + "/settlement/bill")
public class SettlementManageBillController extends BaseController {
    @Autowired
    private ISettlementManageBillService settlementManageBillService;
    @Autowired
    private ISettlementManageFactoryService settlementManageFactoryService;
    @Autowired
    private ISettlementManageStoreService settlementManageStoreService;
    @Autowired
    private IManageFactoryService manageFactoryService;
    @Autowired
    private ISettlementBalanceRecordService settlementBalanceRecordService;
    @Autowired
    private ISysSettlementRateService sysSettlementRateService;
    @Autowired
    private ISysStoreService sysStoreService;

    /**
     * 查询结算账单列表
     */
    @PreAuthorize("@ss.hasPermi('settlement:bill:list')")
    @GetMapping("/listSettlementBill")
    @ApiOperation(value = "查询结算账单列表")
    public TableDataInfo listSettlementBill(SettlementBillListQueryDTO settlementBillListQueryDTO) {
        startPage();
        LambdaQueryWrapper<SettlementManageBill> queryWrapper = new QueryWrapper<SettlementManageBill>().lambda()
                .eq(SettlementManageBill::getDelFlag, StatusType.OK.getCode());
        if (StrUtil.isNotEmpty(settlementBillListQueryDTO.getMonthTime())){
            queryWrapper.eq(SettlementManageBill::getBeginTime, settlementBillListQueryDTO.getMonthTime() + "-01");
        }
        if (StrUtil.isNotEmpty(settlementBillListQueryDTO.getTitle())){
            queryWrapper.like(SettlementManageBill::getTitle, settlementBillListQueryDTO.getTitle());
        }
        queryWrapper.orderByDesc(BaseEntity::getCreateTime);
        List<SettlementManageBill> list = settlementManageBillService.list(queryWrapper);
        return getDataTable(list);
    }

    /**
     * 查询工厂结算列表
     */
    @PreAuthorize("@ss.hasPermi('settlement:bill:list')")
    @PostMapping("/listFactorySettlement")
    @ApiOperation(value = "查询工厂结算列表")
    public R<Page<SettlementManageFactoryQueryVO>> listFactorySettlement(@RequestBody SettlementListQueryDTO settlementListQueryDTO) {
        LambdaQueryWrapper<SettlementManageFactory> queryWrapper = new QueryWrapper<SettlementManageFactory>().lambda();
        if (settlementListQueryDTO.getBillId() != null){
            queryWrapper.eq(SettlementManageFactory::getBillId, settlementListQueryDTO.getBillId());
        }
        queryWrapper.orderByDesc(SettlementManageFactory::getBeginTime);
        Page<SettlementManageFactory> factoryPage = settlementManageFactoryService.page(new Page<>(
                settlementListQueryDTO.getPageNum(), settlementListQueryDTO.getPageSize()), queryWrapper);
        List<SettlementManageFactory> factoryList = factoryPage.getRecords();
        Page<SettlementManageFactoryQueryVO> page = new Page<>();
        if (CollUtil.isEmpty(factoryList)){
            return R.ok(page);
        }
        List<ManageFactory> list = manageFactoryService.list(new QueryWrapper<ManageFactory>().lambda()
                .in(ManageFactory::getId, factoryList.stream().map(SettlementManageFactory::getOrgId).collect(Collectors.toList())));
        Map<Long, String> map = list.stream().collect(Collectors.toMap(ManageFactory::getId, ManageFactory::getFactoryName));
        List<SettlementManageFactoryQueryVO> queryVOList = new ArrayList<>();
        for (SettlementManageFactory factory : factoryList) {
            SettlementManageFactoryQueryVO vo = new SettlementManageFactoryQueryVO();
            BeanUtils.copyProperties(factory, vo);
            if (map.containsKey(factory.getOrgId())){
                vo.setOrgName(map.get(factory.getOrgId()));
            }
            queryVOList.add(vo);
        }
        page.setRecords(queryVOList);
        page.setTotal(factoryPage.getTotal());
        return R.ok(page);
    }

    /**
     * 查询门店结算列表
     */
    @PreAuthorize("@ss.hasPermi('settlement:bill:list')")
    @PostMapping("/listStoreSettlement")
    @ApiOperation(value = "查询门店结算列表")
    public R<Page<SettlementManageStoreQueryVO>> listStoreSettlement(@RequestBody SettlementListQueryDTO settlementListQueryDTO) {
        LambdaQueryWrapper<SettlementManageStore> queryWrapper = new QueryWrapper<SettlementManageStore>().lambda();
        if (settlementListQueryDTO.getBillId() != null){
            queryWrapper.eq(SettlementManageStore::getBillId, settlementListQueryDTO.getBillId());
        }
        if (!SourceType.MANAGER.getCode().equals(SecurityUtils.getLoginUser().getSourceType())){
            queryWrapper.eq(SettlementManageStore::getSourceType, SecurityUtils.getLoginUser().getSourceType());
            queryWrapper.eq(SettlementManageStore::getOrgId, SecurityUtils.getLoginUser().getOrgId());
        }
        queryWrapper.orderByDesc(SettlementManageStore::getBeginTime);
        Page<SettlementManageStore> pageVO = settlementManageStoreService.page(new Page<>(
                settlementListQueryDTO.getPageNum(), settlementListQueryDTO.getPageSize()), queryWrapper);
        List<SettlementManageStore> stores = pageVO.getRecords();
        Page<SettlementManageStoreQueryVO> page = new Page<>();
        if (CollUtil.isEmpty(stores)){
            return R.ok(page);
        }
        List<SysStore> list = sysStoreService.list(new QueryWrapper<SysStore>().lambda()
                .in(SysStore::getId, stores.stream().map(SettlementManageStore::getOrgId).collect(Collectors.toList())));
        Map<Long, String> map = list.stream().collect(Collectors.toMap(SysStore::getId, SysStore::getName));
        List<SettlementManageStoreQueryVO> queryVOList = new ArrayList<>();
        for (SettlementManageStore store : stores) {
            SettlementManageStoreQueryVO vo = new SettlementManageStoreQueryVO();
            BeanUtils.copyProperties(store, vo);
            if (map.containsKey(store.getOrgId())){
                vo.setOrgName(map.get(store.getOrgId()));
            }
            queryVOList.add(vo);
        }
        page.setRecords(queryVOList);
        page.setTotal(pageVO.getTotal());
        return R.ok(page);
    }

    /**
     * 新增结算账单
     */
    @PreAuthorize("@ss.hasPermi('settlement:bill:add')")
    @PostMapping("/insertSettlementBill")
    @ApiOperation(value = "新增结算账单")
    public R insertSettlementManageBill(@RequestBody SettlementBillAddDTO settlementBillAddDTO) {
        settlementManageBillService.insertSettlementManageBill(settlementBillAddDTO);
        return R.ok();
    }

    /**
     * 删除结算账单
     */
    @PreAuthorize("@ss.hasPermi('settlement:bill:remove')")
    @DeleteMapping("/{ids}")
    @ApiOperation(value = "删除结算账单")
    public R deleteSettlementBill(@PathVariable Long[] ids) {
        return R.ok(settlementManageBillService.update(new UpdateWrapper<SettlementManageBill>().lambda()
                .set(SettlementManageBill::getDelFlag, StatusType.DELETED.getCode())
                .in(SettlementManageBill::getId, Arrays.asList(ids))
                .eq(SettlementManageBill::getDelFlag, StatusType.OK.getCode())));
    }

    /**
     * 门店结算详情
     */
    @PreAuthorize("@ss.hasPermi('settlement:bill:edit')")
    @GetMapping("/getInfoByStore")
    @ApiOperation(value = "门店结算详情")
    public R<SettlementManageStoreInfoVO> getInfoByStore(@RequestParam("id") Long id){
        SettlementManageStoreInfoVO settlementManageStoreInfoVO = new SettlementManageStoreInfoVO();
        SettlementManageStore settlementManageStore = settlementManageStoreService.getOne(new QueryWrapper<SettlementManageStore>().lambda()
                .eq(SettlementManageStore::getId, id));
        if (settlementManageStore == null){
            throw new ServiceException("未查询到门店结算信息");
        }
        settlementManageStoreInfoVO.setSettlementManageStore(settlementManageStore);
        if (settlementManageStore.getOrgId() != null){
            settlementManageStoreInfoVO.setSysStore(sysStoreService.getById(settlementManageStore.getOrgId()));
            settlementManageStoreInfoVO.setSysSettlementRate(
                    sysSettlementRateService.getOne(new QueryWrapper<SysSettlementRate>().lambda()
                            .eq(SysSettlementRate::getOrgId, settlementManageStore.getOrgId())
                            .eq(SysSettlementRate::getSourceType, SourceType.STORE.getCode()))
            );
        }
        return R.ok(settlementManageStoreInfoVO);
    }

    /**
     * 提交门店结算
     */
    @Transactional(rollbackFor = Exception.class)
    @PreAuthorize("@ss.hasPermi('settlement:bill:edit')")
    @PostMapping("/submitStoreSettlement")
    @ApiOperation(value = "提交门店结算")
    public R submitStoreSettlement(@RequestBody @Valid SettlementStoreSubmitDTO settlementStoreSubmitDTO){
        SettlementManageStore settlementManageStore = settlementManageStoreService.getOne(new QueryWrapper<SettlementManageStore>().lambda()
                .eq(SettlementManageStore::getId, settlementStoreSubmitDTO.getSettleId()));
        if (settlementManageStore == null){
            throw new ServiceException("未查询到门店结算信息");
        }
        if (SettlementStatusType.YES.getCode().equals(settlementManageStore.getStatus())){
            throw new ServiceException("该期账单已清算，无法再次操作");
        }
        // 更新结算信息
        BeanUtils.copyProperties(settlementStoreSubmitDTO, settlementManageStore);
        settlementManageStore.setSettleTime(DateUtils.getNowDate());
        settlementManageStore.setSettlementAmount(settlementStoreSubmitDTO.getRealSettlementAmount());
        settlementManageStore.setStatus(SettlementStatusType.YES.getCode());

        // 更新收取的清算金额
        settlementManageStore.setPaidDeposit(settlementManageStore.getPaidDeposit().multiply(settlementStoreSubmitDTO.getSettlePaidDeposit()));
        settlementManageStore.setPaidWelfareDeposit(settlementManageStore.getPaidWelfareDeposit().multiply(settlementStoreSubmitDTO.getSettleWelfareDeposit()));
        settlementManageStore.setPaidCardPasswordDeposit(settlementManageStore.getPaidCardPasswordDeposit().multiply(settlementStoreSubmitDTO.getSettleGetCardPasswordDeposit()));
        settlementManageStore.setMaterialImprestAmount(settlementStoreSubmitDTO.getSettleMaterialImprestAmount());
        settlementManageStoreService.updateById(settlementManageStore);
        // 添加结算金额，给门店余额
        sysStoreService.update(new UpdateWrapper<SysStore>().lambda()
                .setSql("balance = balance + " + settlementManageStore.getSettleSettlementAmount())
                    .eq(SysStore::getId, settlementManageStore.getOrgId()));

        // 保存记录
        SettlementBalanceRecord settlementBalanceRecord = SettlementBalanceRecord.buildSettlementBalanceRecordByStore(settlementManageStore);
        settlementBalanceRecordService.save(settlementBalanceRecord);
        return R.ok();
    }

    /**
     * 工厂确认清算
     */
    @Transactional(rollbackFor = Exception.class)
    @GetMapping("/confirmSettlementByFactory")
    @ApiOperation(value = "工厂确认清算")
    public R confirmSettlementByFactory(@RequestParam("id") Long id) {
        SettlementManageFactory factory = settlementManageFactoryService.getById(id);
        if (factory == null){
            throw new ServiceException("未查询到该工厂结算账单");
        }
        ManageFactory manageFactory = manageFactoryService.getById(factory.getOrgId());
        if (manageFactory == null){
            throw new ServiceException("未查询到该工厂");
        }
        if (SettlementStatusType.YES.getCode().equals(factory.getStatus())){
            throw new ServiceException("该工厂本期已清算，请勿重复操作");
        }
        BigDecimal balance;
        if (manageFactory.getBalance() == null){
            balance = BigDecimal.ZERO;
        }else {
            balance = manageFactory.getBalance();
        }
        balance = balance.add(factory.getMaterialAmount());
        manageFactoryService.update(new UpdateWrapper<ManageFactory>().lambda()
                .eq(ManageFactory::getId, factory.getOrgId())
                    .set(ManageFactory::getBalance, balance));
        factory.setStatus(SettlementStatusType.YES.getCode());
        settlementManageFactoryService.updateById(factory);
        // 保存记录
        SettlementBalanceRecord settlementBalanceRecord = SettlementBalanceRecord.buildSettlementBalanceRecordByFactory(factory);
        settlementBalanceRecordService.save(settlementBalanceRecord);
        return R.ok();
    }
}
