package cn.ezhizao.project.business.invoice.controller;

import java.math.BigDecimal;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;

import cn.ezhizao.project.business.collection.domain.BizCollection;
import cn.ezhizao.project.business.collection.domain.BizCollectionDetail;
import cn.ezhizao.project.business.collection.service.IBizCollectionDetailService;
import cn.ezhizao.project.business.collection.service.IBizCollectionService;
import cn.ezhizao.project.business.invoice.domain.BizCopyInfo;
import cn.ezhizao.project.business.invoice.domain.BizInvoice;
import cn.ezhizao.project.business.invoice.domain.BizInvoiceRecord;
import cn.ezhizao.project.business.invoice.service.IBizCopyInfoService;
import cn.ezhizao.project.business.invoice.service.IBizInvoiceRecordService;
import cn.ezhizao.project.business.invoice.service.IBizInvoiceService;
import cn.ezhizao.project.business.order.service.IBizArchiveInputService;
import cn.ezhizao.project.system.domain.SysFileStorage;
import cn.ezhizao.project.system.service.ISysFileStorageService;
import cn.ezhizao.project.system.service.ISysUserService;
import com.alibaba.nacos.common.utils.CollectionUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import cn.ezhizao.framework.aspectj.lang.annotation.Log;
import cn.ezhizao.framework.aspectj.lang.enums.BusinessType;
import cn.ezhizao.framework.web.controller.BaseController;
import cn.ezhizao.framework.web.domain.AjaxResult;
import cn.ezhizao.common.utils.poi.ExcelUtil;
import cn.ezhizao.framework.web.page.TableDataInfo;

/**
 * 开票管理Controller
 *
 * @author ruoyi
 * @date 2024-08-23
 */
@RestController
@RequestMapping("/business/invoice")
public class BizInvoiceController extends BaseController {
    @Resource
    private IBizInvoiceService bizInvoiceService;
    @Resource
    private IBizInvoiceRecordService bizInvoiceRecordService;
    @Resource
    private IBizCollectionService collectionService;

    @Resource
    private IBizCollectionDetailService collectionDetailService;

    @Resource
    private IBizCopyInfoService bizCopyInfoService;

    @Resource
    private IBizArchiveInputService bizArchiveInputService;

    @Resource
    private ISysUserService userService;

    @Resource
    private ISysFileStorageService fileStorageService;

    /**
     * 查询开票管理列表
     */
    @PreAuthorize("@ss.hasPermi('business:invoice:list')")
    @GetMapping("/list")
    public TableDataInfo list(BizInvoice bizInvoice) throws NoSuchFieldException, IllegalAccessException {
        startPage();
        setTenantId(bizInvoice);
        List<BizInvoice> list = bizInvoiceService.getList(bizInvoice);
        return getDataTable(list);
    }

    /**
     * 导出开票管理列表
     */
    @PreAuthorize("@ss.hasPermi('business:invoice:export')")
    @Log(title = "开票管理导出", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, BizInvoice bizInvoice) throws NoSuchFieldException, IllegalAccessException {
        bizInvoice.setTenantId(getTenantId());
        List<BizInvoice> list = bizInvoiceService.getList(bizInvoice);
        ExcelUtil<BizInvoice> util = new ExcelUtil<BizInvoice>(BizInvoice.class);
        util.exportExcel(response, list, "开票管理数据");
    }

    /**
     * 获取开票管理详细信息
     */
    @PreAuthorize("@ss.hasPermi('business:invoice:query')")
    @GetMapping(value = "/{id}")
    public AjaxResult getInfo(@PathVariable("id") Long id) {
        BizInvoice bizInvoice = bizInvoiceService.getById(id);

        SysFileStorage one = fileStorageService.getOne(new LambdaQueryWrapper<SysFileStorage>().eq(SysFileStorage::getMasterId, bizInvoice.getId()));
        if (one != null) {
            bizInvoice.setEvidenceFile(one.getFileUrl());
        }

        String contractNo = bizArchiveInputService.getById(bizInvoice.getContractId()).getContractNo();
        bizInvoice.setContractNo(contractNo);
        if (bizInvoice.getInvoiceId() != null) {
            String userName2 = userService.selectUserById(bizInvoice.getInvoiceId()).getNickName();
            bizInvoice.setInvoiceName(userName2);
        }

        if (bizInvoice.getApplierId() != null) {
            String userName1 = userService.selectUserById(bizInvoice.getApplierId()).getNickName();
            bizInvoice.setApplierName(userName1);
        }
        return success(bizInvoice);
    }


    @GetMapping(value = "/getInfoByName/{name}")
    public AjaxResult getInfoByName(@PathVariable String name) {
        BizCopyInfo one = bizCopyInfoService.getOne(new LambdaQueryWrapper<BizCopyInfo>().eq(BizCopyInfo::getName, name));
        return success(one);
    }

    /**
     * 新增开票管理
     */
    @PreAuthorize("@ss.hasPermi('business:invoice:add')")
    @Log(title = "开票管理", businessType = BusinessType.INSERT)
    @PostMapping
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult add(@RequestBody BizInvoice bizInvoice) throws NoSuchFieldException, IllegalAccessException {
        if(null == bizInvoice.getContractId()){
            return error("请选择合同");
        }
        BizCopyInfo info1 = new BizCopyInfo();
        BizCopyInfo info2 = new BizCopyInfo();
        //开票户
        Long tenantId = getTenantId();
        BizCopyInfo one = bizCopyInfoService.getOne(new LambdaQueryWrapper<BizCopyInfo>().eq(BizCopyInfo::getTenantId, tenantId));
        if (one != null) {
            info1.setId(one.getId());
        }
        info1.setName(bizInvoice.getInvoiceMy());
        info1.setAddress(bizInvoice.getMyAddress());
        info1.setAccount(bizInvoice.getMyAccount());
        info1.setCode(bizInvoice.getMyCreditSocietyCode());
        info1.setTenantId(tenantId);
        bizCopyInfoService.saveOrUpdate(info1);
        //收票户
        String invoiceOther = bizInvoice.getInvoiceOther();
        BizCopyInfo one1 = bizCopyInfoService.getOne(new LambdaQueryWrapper<BizCopyInfo>().eq(BizCopyInfo::getName, invoiceOther));
        if (one1 != null) {
            info2.setId(one1.getId());
        }
        info2.setName(invoiceOther);
        info2.setAddress(bizInvoice.getOtherAddress());
        info2.setAccount(bizInvoice.getOtherAccount());
        info2.setCode(bizInvoice.getOtherCreditSocietyCode());
        bizCopyInfoService.saveOrUpdate(info2);
        bizInvoice.setApplierId(getUserId());
        bizInvoice.setApplierTime(new Date());
        bizInvoice.setTenantId(  getTenantId());
        return toAjax(bizInvoiceService.save(bizInvoice) && editRecord(bizInvoice));
    }

    /**
     * 修改开票管理
     */
    @PreAuthorize("@ss.hasPermi('business:invoice:edit')")
    @Log(title = "开票管理", businessType = BusinessType.UPDATE)
    @PutMapping
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult edit(@RequestBody BizInvoice bizInvoice) throws NoSuchFieldException, IllegalAccessException {
        Long tenantId = getTenantId();
        if(null == bizInvoice.getContractId()){
            return error("请选择合同");
        }
        BizCopyInfo info1 = new BizCopyInfo();
        BizCopyInfo info2 = new BizCopyInfo();
        BizCopyInfo one = bizCopyInfoService.getOne(new LambdaQueryWrapper<BizCopyInfo>().eq(BizCopyInfo::getTenantId, tenantId));
        if (one != null) {
            info1.setId(one.getId());
        }
        info1.setName(bizInvoice.getInvoiceMy());
        info1.setAddress(bizInvoice.getMyAddress());
        info1.setAccount(bizInvoice.getMyAccount());
        info1.setCode(bizInvoice.getMyCreditSocietyCode());
        bizCopyInfoService.saveOrUpdate(info1);
        //收票户
        String invoiceOther = bizInvoice.getInvoiceOther();
        BizCopyInfo one1 = bizCopyInfoService.getOne(new LambdaQueryWrapper<BizCopyInfo>().eq(BizCopyInfo::getName, invoiceOther));
        if (one1 != null) {
            info2.setId(one1.getId());
        }
        info2.setName(invoiceOther);
        info2.setAddress(bizInvoice.getOtherAddress());
        info2.setAccount(bizInvoice.getOtherAccount());
        info2.setCode(bizInvoice.getOtherCreditSocietyCode());
        bizCopyInfoService.saveOrUpdate(info2);
        if (bizInvoice.getStatus().equals(3)) {
            Long userId = getUserId();
            bizInvoice.setInvoiceId(userId);
            SysFileStorage sysFileStorage = new SysFileStorage();
            sysFileStorage.setMasterId(bizInvoice.getId());
            sysFileStorage.setMasterTableName("biz_invoice");
            sysFileStorage.setFileUrl(bizInvoice.getEvidenceFile());
            sysFileStorage.setFileName(bizInvoice.getFileName());
            sysFileStorage.setOriginalFileName(bizInvoice.getOriginalFileName());
            SysFileStorage fileStorage = fileStorageService.getOne(new LambdaQueryWrapper<SysFileStorage>().eq(SysFileStorage::getMasterId, bizInvoice.getId()));
           if (fileStorage != null ){
               fileStorageService.physicalDelete(fileStorage);
           }
            fileStorageService.save(sysFileStorage);
        }
        editRecord(bizInvoice);
        return toAjax(bizInvoiceService.updateById(bizInvoice));
    }

    private boolean editRecord(BizInvoice bizInvoice) {
        BizInvoiceRecord bizInvoiceRecord = new BizInvoiceRecord();
        bizInvoiceRecord.setInvoiceId(bizInvoice.getId());
        bizInvoiceRecord.setContractId(bizInvoice.getContractId());
        bizInvoiceRecord.setUserId(getUserId());
        bizInvoiceRecord.setTenantId(bizInvoice.getTenantId());
        switch (bizInvoice.getStatus()) {
            case 0:
                //待提交（页面上的保存）
                bizInvoiceRecord.setInvoiceStatus(0);
                break;
            case 1:
                //页面上的提交 ，状态叫待开票
                bizInvoiceRecord.setInvoiceStatus(1);
                break;
            case 2:
                //页面 拒绝
                bizInvoiceRecord.setInvoiceStatus(2);
                bizInvoiceRecord.setRemark(bizInvoice.getRefuseReason());
                break;
            case 3:
                //审核通过, 状态时已开票
                bizInvoiceRecord.setInvoiceStatus(3);
                break;
            case 4:
                //退回
                bizInvoiceRecord.setInvoiceStatus(4);
                bizInvoiceRecord.setRemark(bizInvoice.getReturnReason());
                break;
            case 5:
                //反审核
                bizInvoiceRecord.setInvoiceStatus(5);
                bizInvoiceRecord.setRemark(bizInvoice.getUauditReason());
                //需要把状态设置为1，页面得是待开票
                bizInvoice.setStatus(1);
                break;
            default:
                break;
        }
        return bizInvoiceRecordService.save(bizInvoiceRecord);
    }

    /**
     * 删除开票管理
     */
    @PreAuthorize("@ss.hasPermi('business:invoice:remove')")
    @Log(title = "开票管理", businessType = BusinessType.DELETE)
    @DeleteMapping("/{ids}")
    public AjaxResult remove(@PathVariable List<Long> ids) {
        return toAjax(bizInvoiceService.removeBatchByIds(ids));
    }

    @GetMapping(value = "/getCollectionToAmount/{id}")
    public AjaxResult getCollectionToAmount(@PathVariable String id) {
        List<BizCollection> list = collectionService.list(new LambdaQueryWrapper<BizCollection>()
                .eq(BizCollection::getContractId, id)
                .eq(BizCollection::getStatus, 1)
                .eq(BizCollection::getArriveStatus, 1)
                .eq(BizCollection::getDeleted, 0));
        List<Long> ids = list.stream().map(v -> v.getId()).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(ids)) {
            return success(0);
        }
        List<BizCollectionDetail> details = collectionDetailService.list(
                new LambdaQueryWrapper<BizCollectionDetail>()
                        .in(BizCollectionDetail::getCollectionId, ids)
                        .eq(BizCollectionDetail::getDeleted, 0)
        );
        //所有审核通过的合同
        BigDecimal amount = details.stream().map(BizCollectionDetail::getArriveAmount).reduce(BigDecimal.ZERO, BigDecimal::add);

        //已开票 或待审核的开票
        LambdaQueryWrapper<BizInvoice> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(BizInvoice::getContractId, id);
        wrapper.eq(BizInvoice::getDeleted, 0);
        wrapper.and(item -> item.eq(BizInvoice::getStatus, 3).or().eq(BizInvoice::getStatus, 1));
        List<BizInvoice> invoices = bizInvoiceService.list(wrapper);
        if (!CollectionUtils.isEmpty(invoices)) {
            BigDecimal haveAmount = invoices.stream().map(v -> v.getAllowInvoiceAmount()).reduce(BigDecimal.ZERO, BigDecimal::add);
            amount = amount.subtract(haveAmount);
            if (amount.compareTo(BigDecimal.ZERO)<0){
                amount = BigDecimal.ZERO;
            }
        }

        return success(amount);

    }
}
