package com.njzscloud.supervisory.biz.service;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.njzscloud.common.core.ex.Exceptions;
import com.njzscloud.common.mp.support.PageParam;
import com.njzscloud.common.mp.support.PageResult;
import com.njzscloud.common.security.support.UserDetail;
import com.njzscloud.common.security.util.SecurityUtil;
import com.njzscloud.supervisory.biz.constant.AuditStatus;
import com.njzscloud.supervisory.biz.constant.BizObj;
import com.njzscloud.supervisory.biz.mapper.BizTruckMapper;
import com.njzscloud.supervisory.biz.pojo.entity.BizTruckEntity;
import com.njzscloud.supervisory.biz.pojo.param.ModifyBizTruckParam;
import com.njzscloud.supervisory.biz.pojo.param.SearchTruckParam;
import com.njzscloud.supervisory.biz.pojo.result.SearchCompanyResult;
import com.njzscloud.supervisory.biz.pojo.result.SearchTruckResult;
import com.njzscloud.supervisory.biz.pojo.result.TruckCantDelResult;
import com.njzscloud.supervisory.device.pojo.entity.DeviceLocalizerEntity;
import com.njzscloud.supervisory.device.service.DeviceLocalizerService;
import com.njzscloud.supervisory.sys.auth.pojo.result.MyResult;
import com.njzscloud.supervisory.sys.dict.pojo.DictItemEntity;
import com.njzscloud.supervisory.sys.dict.service.DictItemService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

/**
 * 车辆信息
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class BizTruckService extends ServiceImpl<BizTruckMapper, BizTruckEntity> implements IService<BizTruckEntity> {
    private final DeviceLocalizerService deviceLocalizerService;
    private final DictItemService dictItemService;

    /**
     * 新增
     *
     * @param bizTruckEntity 数据
     */
    @Transactional(rollbackFor = Exception.class)
    public void add(BizTruckEntity bizTruckEntity) {
        bizTruckEntity.setAuditStatus(AuditStatus.DaiShenHe);
        String licensePlate = bizTruckEntity.getLicensePlate();
        boolean exists = this.exists(Wrappers.lambdaQuery(BizTruckEntity.class).eq(BizTruckEntity::getLicensePlate, licensePlate));
        if (exists) {
            throw Exceptions.exception("车牌号已存在：{}", licensePlate);
        }
        String gps = bizTruckEntity.getGps();
        if (StrUtil.isNotBlank(gps)) {
            long count = deviceLocalizerService.count(Wrappers.<DeviceLocalizerEntity>query().eq("terminal_id", gps));
            if (count == 0) {
                throw Exceptions.exception("设备不存在：{}", gps);
            }
        }
        this.save(bizTruckEntity);
    }

    /**
     * 修改
     *
     * @param modifyBizTruckParam 数据
     */
    @Transactional(rollbackFor = Exception.class)
    public void modify(ModifyBizTruckParam modifyBizTruckParam) {
        Long id = modifyBizTruckParam.getId();
        BizTruckEntity oldData = this.getById(id);
        Assert.notNull(oldData, () -> Exceptions.exception("车辆不存在"));
        String licensePlate = modifyBizTruckParam.getLicensePlate();
        boolean exists = this.exists(Wrappers.lambdaQuery(BizTruckEntity.class)
                .eq(BizTruckEntity::getLicensePlate, licensePlate)
                .ne(BizTruckEntity::getId, id));
        if (exists) {
            throw Exceptions.exception("车牌号已存在：{}", licensePlate);
        }
        String gps = modifyBizTruckParam.getGps();
        if (StrUtil.isNotBlank(gps)) {
            long count = deviceLocalizerService.count(Wrappers.<DeviceLocalizerEntity>query().eq("terminal_id", gps));
            if (count == 0) {
                throw Exceptions.exception("设备不存在：{}", gps);
            }
        }
        this.updateById(BeanUtil.copyProperties(modifyBizTruckParam, BizTruckEntity.class));
    }

    /**
     * 删除
     *
     * @param ids Ids
     */
    @Transactional(rollbackFor = Exception.class)
    public void del(List<Long> ids) {
        Assert.notEmpty(ids, () -> Exceptions.clierr("未指定要删除的数据"));
        long count = this.count(Wrappers.<BizTruckEntity>query().in("id", ids));
        Assert.isTrue(count == ids.size(), () -> Exceptions.clierr("未找到要删除的数据"));
        List<TruckCantDelResult> idList = baseMapper.truckCantDel(Wrappers.query()
                .eq("a.deleted", 0)
                .in("b.id", ids));
        Assert.isTrue(idList.isEmpty(), () -> Exceptions.clierr(MapUtil.builder()
                .put("reason", "存在已关联的订单")
                .put("details", idList)
                .build()));
        this.removeBatchByIds(ids);
    }

    /**
     * 详情
     *
     * @param id Id
     * @return BizTruckEntity 结果
     */
    public SearchTruckResult detail(Long id) {
        SearchTruckResult result = baseMapper.selectDetailById(id);
        List<DictItemEntity> list = dictItemService.list(Wrappers.<DictItemEntity>lambdaQuery()
                .eq(DictItemEntity::getDictKey, "vehicle_type"));
        if (null != list && list.size() > 0) {
            List<DictItemEntity> entityList = list.stream().filter(t -> t.getVal().equals(result.getTruckCategory()))
                    .collect(Collectors.toList());
            if (entityList.size() > 0) {
                result.setTruckCategory(entityList.get(0).getTxt());
            }
        }
        return result;
    }

    /**
     * 分页查询
     *
     * @param searchTruckParam 筛选条件
     * @param pageParam        分页参数
     * @return PageResult&lt;SearchTruckResult&gt; 分页结果
     */
    public PageResult<SearchTruckResult> paging(PageParam pageParam, SearchTruckParam searchTruckParam) {
        String companyName = searchTruckParam.getCompanyName();
        String licensePlate = searchTruckParam.getLicensePlate();
        AuditStatus auditStatus = searchTruckParam.getAuditStatus();
        String aStatus = "";
        if (null != auditStatus) {
            aStatus = auditStatus.getVal();
        }
        QueryWrapper<SearchTruckResult> ew = Wrappers.<SearchTruckResult>query()
                .eq("a.deleted", 0)
                .eq(StrUtil.isNotBlank(aStatus), "a.audit_status", aStatus)
                .like(StrUtil.isNotBlank(companyName), "b.company_name", companyName)
                .like(StrUtil.isNotBlank(licensePlate), "a.license_plate", licensePlate);
        MyResult userDetail = SecurityUtil.loginUser();
        BizObj bizObj = userDetail.getBizObj();
        if (bizObj == BizObj.QiYe
                || bizObj == BizObj.GeTi
        ) {
            ew.eq("b.user_id", userDetail.getUserId());
        }
        IPage<SearchTruckResult> page = baseMapper.paging(pageParam.toPage(), ew);
        List<DictItemEntity> list = dictItemService.list(Wrappers.<DictItemEntity>lambdaQuery()
                .eq(DictItemEntity::getDictKey, "vehicle_type"));
        if (null != list && list.size() > 0) {
            for (SearchTruckResult result : page.getRecords()) {
                List<DictItemEntity> entityList = list.stream().filter(t -> t.getVal().equals(result.getTruckCategory()))
                        .collect(Collectors.toList());
                if (entityList.size() > 0) {
                    result.setTruckCategory(entityList.get(0).getTxt());
                }
            }
        }
        return PageResult.of(page);
    }

    @Transactional(rollbackFor = Exception.class)
    public void busy(List<Long> id, Boolean busy) {
    }

    public PageResult<BizTruckEntity> dispensabilityList(PageParam pageParam, String keywords) {
        UserDetail userDetail = SecurityUtil.loginUser();
        SearchCompanyResult searchCompanyResult = baseMapper.selectCompanyByUserId(userDetail.getUserId());
        Assert.notNull(searchCompanyResult, () -> Exceptions.exception("未查询到公司信息"));
        return PageResult.of(this.page(pageParam.toPage(), Wrappers.<BizTruckEntity>lambdaQuery()
                // .eq(BizTruckEntity::getBusy, false)
                .eq(BizTruckEntity::getAuditStatus, AuditStatus.TongGuo)
                .eq(BizTruckEntity::getCompanyId, searchCompanyResult.getId())
                .and(StrUtil.isNotBlank(keywords), it ->
                        it.like(BizTruckEntity::getLicensePlate, keywords)
                                .or().like(BizTruckEntity::getVnCode, keywords))

        ));
    }

    @Transactional(rollbackFor = Exception.class)
    public void audit(Long id, AuditStatus auditStatus, String auditMemo, List<String> certificationDate) {
        Assert.isTrue(auditStatus == AuditStatus.TongGuo || auditStatus == AuditStatus.BoHui, "错误的审核状态");
        BizTruckEntity oldData = getById(id);
        if (oldData == null) {
            throw Exceptions.exception("未找到要审核的数据");
        }
        if (oldData.getAuditStatus() != AuditStatus.DaiShenHe) {
            throw Exceptions.exception("当前状态不能审核");
        }
        boolean updated = update(Wrappers.<BizTruckEntity>lambdaUpdate()
                .set(BizTruckEntity::getAuditStatus, auditStatus)
                .set(BizTruckEntity::getAuditMemo, auditStatus == AuditStatus.TongGuo ? "" : auditMemo)
                .eq(BizTruckEntity::getId, id)
                .eq(BizTruckEntity::getAuditStatus, AuditStatus.DaiShenHe));
        if (!updated) {
            throw Exceptions.exception("数据状态已改变，无法审核");
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public void cancel(Long id) {
        BizTruckEntity oldData = getById(id);
        if (oldData == null) {
            throw Exceptions.exception("未找到要撤销的数据");
        }
        update(Wrappers.<BizTruckEntity>lambdaUpdate()
                .set(BizTruckEntity::getAuditStatus, AuditStatus.YiCheXiao)
                .eq(BizTruckEntity::getId, id)
        );
    }

    public void changeCompany(Long id, Long companyId) {
        this.updateById(new BizTruckEntity()
                .setId(id)
                .setCompanyId(companyId)
        );
    }
}
