package com.fs.his.service.impl;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fs.common.core.domain.R;
import com.fs.common.exception.base.BaseException;
import com.fs.common.utils.DateUtils;
import com.fs.common.utils.IdUtils;
import com.fs.his.domain.FsStoreOrder;
import com.fs.his.enums.FsInquiryOrderStatusEnum;
import com.fs.his.param.BillListParam;
import com.fs.his.param.OrderBillParam;
import com.fs.his.service.IFsStoreOrderItemService;
import com.fs.his.service.IFsStoreOrderService;
import com.fs.his.vo.FsStoreOrderBillLogVo;
import com.fs.his.vo.FsStoreOrderItemListDVO;
import com.fs.huifuPay.sdk.opps.core.utils.StringUtil;
import com.fs.nuonuo.NuonuoUtils;
import com.github.pagehelper.PageInfo;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import com.fs.his.mapper.FsStoreOrderBillLogMapper;
import com.fs.his.domain.FsStoreOrderBillLog;
import com.fs.his.service.IFsStoreOrderBillLogService;
import org.springframework.transaction.annotation.Transactional;

/**
 * 订单开票记录Service业务层处理
 * 
 * @author fs
 * @date 2025-01-07
 */
@Slf4j
@Service
@AllArgsConstructor
public class FsStoreOrderBillLogServiceImpl extends ServiceImpl<FsStoreOrderBillLogMapper, FsStoreOrderBillLog> implements IFsStoreOrderBillLogService{

    private final FsStoreOrderBillLogMapper fsStoreOrderBillLogMapper;
    private final IFsStoreOrderService fsStoreOrderService;
    private final IFsStoreOrderItemService fsStoreOrderItemService;

    /**
     * 查询订单开票记录
     * 
     * @param id 订单开票记录主键
     * @return 订单开票记录
     */
    @Override
    public FsStoreOrderBillLog selectFsStoreOrderBillLogById(Long id)
    {
        return fsStoreOrderBillLogMapper.selectFsStoreOrderBillLogById(id);
    }

    /**
     * 查询订单开票记录列表
     * 
     * @param fsStoreOrderBillLog 订单开票记录
     * @return 订单开票记录
     */
    @Override
    public List<FsStoreOrderBillLog> selectFsStoreOrderBillLogList(FsStoreOrderBillLog fsStoreOrderBillLog)
    {
        return fsStoreOrderBillLogMapper.selectFsStoreOrderBillLogList(fsStoreOrderBillLog);
    }

    /**
     * 新增订单开票记录
     * 
     * @param fsStoreOrderBillLog 订单开票记录
     * @return 结果
     */
    @Override
    public int insertFsStoreOrderBillLog(FsStoreOrderBillLog fsStoreOrderBillLog)
    {
        fsStoreOrderBillLog.setCreateTime(DateUtils.getNowDate());
        return fsStoreOrderBillLogMapper.insertFsStoreOrderBillLog(fsStoreOrderBillLog);
    }

    /**
     * 修改订单开票记录
     * 
     * @param fsStoreOrderBillLog 订单开票记录
     * @return 结果
     */
    @Override
    public int updateFsStoreOrderBillLog(FsStoreOrderBillLog fsStoreOrderBillLog)
    {
        fsStoreOrderBillLog.setUpdateTime(DateUtils.getNowDate());
        return fsStoreOrderBillLogMapper.updateFsStoreOrderBillLog(fsStoreOrderBillLog);
    }

    /**
     * 批量删除订单开票记录
     * 
     * @param ids 需要删除的订单开票记录主键
     * @return 结果
     */
    @Override
    public int deleteFsStoreOrderBillLogByIds(Long[] ids)
    {
        return fsStoreOrderBillLogMapper.deleteFsStoreOrderBillLogByIds(ids);
    }

    /**
     * 删除订单开票记录信息
     * 
     * @param id 订单开票记录主键
     * @return 结果
     */
    @Override
    public int deleteFsStoreOrderBillLogById(Long id){
        return fsStoreOrderBillLogMapper.deleteFsStoreOrderBillLogById(id);
    }

    /**
     * 判断当前时间是否在零点到九点半之间，是否上传接口
     * @return true：上传，false：不上传
     */
    private static boolean time(){
        // 获取当前时间
//        LocalTime now = LocalTime.of(22, 0);
        LocalTime now = LocalTime.now();
        LocalDateTime dateNow = LocalDateTime.now();
//        LocalDateTime dateNow = LocalDateTime.of(2025, 2, 14, 0, 0);

        LocalTime start = LocalTime.of(9, 30);
        LocalTime end = LocalTime.of(22, 0);
        LocalDate noUploadDate = LocalDate.of(2025, 2, 14);

        // 判断是否在允许上传的时间段内
        boolean isUploadTime = !now.isBefore(start) && !now.isAfter(end);
        // 判断是否是禁止上传的日期
        boolean isNoUploadDate = dateNow.toLocalDate().equals(noUploadDate);

        if (!isUploadTime || isNoUploadDate) {
            log.info("当前时间{}不提交开票接口", now);
            return false;
        } else {
            log.info("当前时间{}上传开票", now);
            return true;
        }
    }

    @Override
    @Transactional
    public R bill(OrderBillParam param) {
        FsStoreOrder fsStoreOrder = fsStoreOrderService.selectFsStoreOrderByOrderId(param.getOrderId());
        if(fsStoreOrder.getStatus() != FsInquiryOrderStatusEnum.STATUS_4.getValue()){
            return R.error("订单未完成无法开票");
        }
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            Date targetDate = sdf.parse("2025-01-01");
            // 判断当前日期是否小于2025-01-01
            if (fsStoreOrder.getFinishTime().before(targetDate)) {
                return R.error("仅限于2025-01-01以后的订单开票，如需开具之前的发票，请联系客服！");
            }
        } catch (ParseException e) {
            return R.error("日期格式错误");
        }
        if(param.getAmount().add(fsStoreOrder.getBillPrice()).compareTo(fsStoreOrder.getPayPrice()) > 0){
            return R.error("开票金额不能大于订单金额");
        }
        fsStoreOrder.setBillPrice(fsStoreOrder.getBillPrice().add(param.getAmount()));
        fsStoreOrderService.updateFsStoreOrder(fsStoreOrder);
        StringBuilder sb;
        if(StringUtil.isEmpty(param.getMemoStr())){
            sb = new StringBuilder(StringUtil.isEmpty(fsStoreOrder.getUserName()) ? "" : fsStoreOrder.getUserName() + "    ");
            if(param.isMemo()){
                List<FsStoreOrderItemListDVO> items = fsStoreOrderItemService.selectFsStoreOrderItemListDVOByOrderId(param.getOrderId());
                items.forEach(item->{
                    JSONObject json = JSON.parseObject(item.getJsonInfo());
                    sb.append(json.getString("productName")).append("  ").append(json.getString("num")).append("    ");
                });
            }
        }else{
            sb = new StringBuilder(param.getMemoStr());
        }
        FsStoreOrderBillLog log = new FsStoreOrderBillLog();
        String orderNo = IdUtils.getPrimaryKey();
        String no = "";
        if(time()){
            no = NuonuoUtils.requestBilling(orderNo, param.getSaleName(), param.getSaleNo(), param.getAmount(), sb.toString());
            log.setUploadApi(1);
        }
        log.setOrderCode(fsStoreOrder.getOrderCode());
        log.setOrderAmount(param.getAmount());
        log.setPayerName(param.getSaleName());
        log.setPayerTaxNo(param.getSaleNo());
        log.setOrderId(param.getOrderId());
        log.setBillType(param.getBillType());
        log.setOrderNo(orderNo);
        log.setSerialNo(no);
        log.setStatus(20);
        log.setCreateTime(DateUtils.getNowDate());
        log.setCreateBy(param.getUserId().toString());
        log.setUpdateBy(param.getUserId().toString());
        log.setUpdateTime(DateUtils.getNowDate());
        log.setRemark(sb.toString());
        save(log);
        return R.ok();
    }

    @Override
    public PageInfo<FsStoreOrderBillLogVo> billList(BillListParam param) {
        List<FsStoreOrderBillLog> list = list(new QueryWrapper<FsStoreOrderBillLog>().eq(param.getOrderId() != null, "order_id", param.getOrderId()).eq("create_by", param.getUserId()).orderByDesc("create_time"));
        PageInfo<FsStoreOrderBillLog> listPageInfo=new PageInfo<>(list);
        PageInfo<FsStoreOrderBillLogVo> pageInfo = new PageInfo<>();
        BeanUtils.copyProperties(listPageInfo, pageInfo);
        pageInfo.setList(list.stream().map(e -> {
            FsStoreOrderBillLogVo vo = new FsStoreOrderBillLogVo();
            BeanUtils.copyProperties(e, vo);
            return vo;
        }).collect(Collectors.toList()));
        return pageInfo;
    }

    @Override
    public R billBack(Long id) {
        FsStoreOrderBillLog log = getById(id);
        if(log.getStatus() != 2) return R.error("发票无法冲红");
        return R.ok();
    }

    private void back(FsStoreOrderBillLog log){
        String s = NuonuoUtils.saveInvoiceRedConfirm(log.getInvoiceNo(), 2, log.getPayerName());
        log.setRedNo(s);
        log.setRedStatus("01");
        log.setRedReason(2);
        log.setRedTime(LocalDateTime.now());
        updateById(log);
    }

    @Override
    public R billBackByOrderId(Long orderId) {
        List<FsStoreOrderBillLog> list = list(new QueryWrapper<FsStoreOrderBillLog>().eq("order_id", orderId).eq("status", 2));
        list.forEach(this::back);
        return null;
    }

    @Override
    public R reopen(Long id) {
        FsStoreOrderBillLog byId = getById(id);
        if(byId == null) return R.error("ID错误");
        OrderBillParam param = new OrderBillParam();
        param.setOrderId(byId.getOrderId());
        param.setBillType(byId.getBillType());
        param.setSaleName(byId.getPayerName());
        param.setSaleNo(byId.getPayerTaxNo());
        param.setAmount(byId.getOrderAmount());
        param.setMemoStr(byId.getRemark());
        param.setUserId(Long.parseLong(byId.getCreateBy()));
        return this.bill(param);
    }
}
