package com.yeejoin.equipmanage.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.typroject.tyboot.core.foundation.context.RequestContext;
import org.typroject.tyboot.core.restful.exception.instance.BadRequest;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yeejoin.amos.boot.biz.common.bo.ReginParams;
import com.yeejoin.amos.boot.biz.common.utils.RedisKey;
import com.yeejoin.amos.boot.biz.common.utils.RedisUtils;
import com.yeejoin.amos.component.feign.config.InnerInvokException;
import com.yeejoin.amos.component.feign.model.FeignClientResult;
import com.yeejoin.amos.feign.privilege.Privilege;
import com.yeejoin.amos.feign.privilege.model.AgencyUserModel;
import com.yeejoin.equipmanage.common.entity.Car;
import com.yeejoin.equipmanage.common.entity.CarProperty;
import com.yeejoin.equipmanage.common.entity.Equipment;
import com.yeejoin.equipmanage.common.entity.EquipmentIndex;
import com.yeejoin.equipmanage.common.entity.EquipmentOnCar;
import com.yeejoin.equipmanage.common.entity.EquipmentQrcode;
import com.yeejoin.equipmanage.common.entity.StockDetail;
import com.yeejoin.equipmanage.common.entity.SystemDic;
import com.yeejoin.equipmanage.common.entity.Unit;
import com.yeejoin.equipmanage.common.entity.UploadFile;
import com.yeejoin.equipmanage.common.entity.vo.EquipmentOnCarAppVO;
import com.yeejoin.equipmanage.common.enums.CarStatusEnum;
import com.yeejoin.equipmanage.common.enums.ScanTypeEnum;
import com.yeejoin.equipmanage.common.utils.ParsePropertyUtil;
import com.yeejoin.equipmanage.common.utils.StringUtil;
import com.yeejoin.equipmanage.common.vo.CarStatusChecker;
import com.yeejoin.equipmanage.common.vo.EquPropertyResponse;
import com.yeejoin.equipmanage.common.vo.QRCodeRequest;
import com.yeejoin.equipmanage.common.vo.QREquipResponse;
import com.yeejoin.equipmanage.common.vo.Result;
import com.yeejoin.equipmanage.common.vo.ScanCarBasicInfo;
import com.yeejoin.equipmanage.common.vo.ScanResult;
import com.yeejoin.equipmanage.mapper.CarMapper;
import com.yeejoin.equipmanage.mapper.CarPropertyMapper;
import com.yeejoin.equipmanage.mapper.EquipmentIndexMapper;
import com.yeejoin.equipmanage.mapper.EquipmentMapper;
import com.yeejoin.equipmanage.mapper.EquipmentOnCarMapper;
import com.yeejoin.equipmanage.mapper.EquipmentQrcodeMapper;
import com.yeejoin.equipmanage.mapper.ScrapDetailMapper;
import com.yeejoin.equipmanage.mapper.SystemDicMapper;
import com.yeejoin.equipmanage.mapper.UnitMapper;
import com.yeejoin.equipmanage.mapper.UploadFileMapper;
import com.yeejoin.equipmanage.service.IEquipmentService;
import com.yeejoin.equipmanage.service.IQRCodeService;
import com.yeejoin.equipmanage.service.IStockDetailService;

/**
 * 装备扫码实现类
 **/
@Service("qREquipmentDefServiceImpl")
@Transactional
public class QREquipmentDefServiceImpl implements IQRCodeService<ScanResult<QREquipResponse>> {

    @Autowired
    private EquipmentQrcodeMapper equipmentQrcodeMapper;
    @Autowired
    private CarMapper carMapper;
    @Autowired
    private UnitMapper unitMapper;
    @Autowired
    private CarPropertyMapper carPropertyMapper;
    @Autowired
    private RedisUtils redisUtils;
    @Autowired
    private ScrapDetailMapper scrapDetailMapper;
    @Autowired
    private EquipmentOnCarMapper equipmentOnCarMapper;
    @Autowired
    private EquipmentMapper equipmentMapper;
    @Autowired
    protected HttpServletRequest request;
    @Autowired
    private SystemDicMapper systemDicMapper;
    @Autowired
    private EquipmentIndexMapper equipmentIndexMapper;
    @Autowired
    private IStockDetailService stockDetailService;
    @Autowired
    private UploadFileMapper uploadFileMapper;
    @Value("${fileserver_domain}")
    private String fileUrl;
    @Autowired
    IEquipmentService iEquipmentService;

    @Override
    public ScanResult<QREquipResponse> scan(QRCodeRequest request) {
        Optional<String> qrcode = Optional.ofNullable(request.getQrCode().split("#")[1]);
        String qrCode = StringUtil.splitQRCode(request)[1];
        QREquipResponse response = new QREquipResponse();
        response.setType(CAR_TYPE);
        ScanTypeEnum type = ScanTypeEnum.getEnum(request.getType());
        switch (type) {
            case CAR_LOAD:
                checkLoadEquipCar(qrCode);
                break;
            case CAR_UNINSTALL:
                break;
            case CAR_FILLING:
                checkLoadEquipCar(qrCode);
                break;
            case CAR_MAINTENANCE:
                checkMaintenanceCar(qrCode);
                break;
            case CAR_REPAIR:
                checkRepairCar(qrCode);
                break;
            case CAR_REPAIRCOMPLETE:
                checkRepairComplatedCar(qrCode);
                break;
            case CAR_SCRAP:
                checkScrapCar(qrCode);
                break;
            case CAR_INFORMATION:
                break;
            default:
                break;
        }

        response.setCar(generateBasicInfo(qrcode.get()));

        return response;
    }

    private void checkMaintenanceCar(String qrCode) {
        Car car = findUseableCar(qrCode);
        if (car == null) {
            throw new IllegalArgumentException("本单位无此车!");
        }
    }

    /**
     * 查找本单位下在位的车辆
     *
     * @param qrCode
     * @return
     */
    public Car findUseableCar(String qrCode) {
        Map<String, Object> columnMap = new HashMap<String, Object>();
        // columnMap.put("type",SystemDicTypeEum.carState.getType());
        // columnMap.put("code",CarStatusEnum.ZW.getCode());
        // Long stateId =systemDicMapper.selectByMap(columnMap).get(0).getId();
        //
        // columnMap.clear();
        columnMap.put("qr_code", qrCode);
        columnMap.put("org_code", getSelectedOrgInfo().getCompany().getOrgCode());
        columnMap.put("car_state", CarStatusEnum.ZW.getCode());

        List<Car> cars = carMapper.selectByMap(columnMap);
        if (cars.isEmpty()) {
            return null;
        }
        return cars.get(0);
    }

    /**
     * 查找到本单位下非归还状态的车辆 由于车辆是单件的，所以一个状态只能找到一个 若没有查到即car==null，则说明此单位下无此车辆，抛出运行时异常
     *
     * @param qrCode
     * @return
     */
    private Car findCar(String qrCode) {
        QueryWrapper<Car> carQueryWrapper = new QueryWrapper<>();
        carQueryWrapper.eq("qr_code", qrCode);
        carQueryWrapper.eq("org_code", getSelectedOrgInfo().getCompany().getOrgCode());
        Car car = carMapper.selectOne(carQueryWrapper);
        Assert.notNull(car, "本单位下无此车辆");
        return car;
    }

    private void checkLoadEquipCar(String qrCode) {
        Car car = findCar(qrCode);

        // Map<String, Object> columnMap = new HashMap<String, Object>();
        // columnMap.put("type", SystemDicTypeEum.carState.getType());
        // columnMap.put("code",CarStatusEnum.ZW.getCode());
        // Long stateId =systemDicMapper.selectByMap(columnMap).get(0).getId();
        //
        // SystemDic state = systemDicMapper.selectById(car.getCarStateId());
        Result result = CarStatusChecker.isLoadable(CarStatusEnum.getEnum(car.getCarState().toString()));
        if (!result.isOk()) {
            throw new IllegalArgumentException(result.toString());
        }
    }

    private void checkRepairCar(String qrCode) throws IllegalArgumentException {
        Car car = findCar(qrCode);
        List<EquipmentOnCarAppVO> equipmentOnCarAppVOS = carMapper.selectEquipmentOnCarAppList(car.getId());
        if (equipmentOnCarAppVOS.size() >0){
            throw new BadRequest("请先卸载装备后再进行维修");
        }

        CarStatusEnum status = CarStatusEnum.getEnum(String.valueOf(car.getCarState()));
        Result result = CarStatusChecker.isRepairable(status);
        if (!result.isOk()) {
            throw new IllegalArgumentException(result.toString());
        }
    }

    private void checkRepairComplatedCar(String qrCode) throws IllegalArgumentException {
        Car car = findCar(qrCode);
        Result result = CarStatusChecker.isRepairCompleteable(CarStatusEnum.getEnum(car.getCarState().toString()));
        if (!result.isOk()) {
            throw new IllegalArgumentException(result.toString());
        }
    }

    /**
     * 判断此车是否有车载装备
     *
     * @param carId 车辆id
     * @return true有，false无
     */
    private boolean isEquipOnCar(Long carId) {

        Map<String, Object> columnMap = new HashMap<String, Object>();
        columnMap.put("car_id", carId);

        List<EquipmentOnCar> equipments = equipmentOnCarMapper.selectByMap(columnMap);
        if (equipments != null && equipments.size() > 0) {
            return true;
        }
        return false;

    }

    private ScanCarBasicInfo generateBasicInfo(String qrCode) throws RuntimeException {
        ScanCarBasicInfo info = new ScanCarBasicInfo();

        QueryWrapper<Car> wrapper = new QueryWrapper();
        wrapper.lambda().eq(Car::getQrCode,qrCode);
        Car car = carMapper.selectOne(wrapper);

        if (car == null) {
            throw new IllegalArgumentException("该二维码不是车辆二维码！");
        }

        QueryWrapper<UploadFile> uploadFileQueryWrapper = new QueryWrapper<>();
        uploadFileQueryWrapper.eq("file_type", "image");
        uploadFileQueryWrapper.eq("object_type", "car");
        uploadFileQueryWrapper.eq("object_id", car.getId());
//        List<UploadFile> imgs = uploadFileMapper.selectList(uploadFileQueryWrapper);
//        car.setImg(imgs);
        String img = iEquipmentService.getById(car.getEquipmentId()).getImg();

        if (car == null) {
            throw new IllegalArgumentException(String.format("该二维码【%s】的车辆，不存在！", qrCode));
        }
        // 根据车辆获取装备信息
        Equipment equipment = equipmentMapper.selectById(car.getEquipmentId());

        ParsePropertyUtil.setting(info::setCarId, car::getId);
        ParsePropertyUtil.setting(info::setCarNum, car::getCarNum);
        ParsePropertyUtil.setting(info::setEquipmentId, car::getEquipmentId);
        ParsePropertyUtil.setting(info::setEquipName, equipment::getName);
        info.setImg(fileUrl+img);
//        ParsePropertyUtil.setting(info::setImg, () -> {
//            if(car.getImg().size()>0){
//                if (StringUtil.isNotEmpty(car.getImg().get(0).getUrl())) {
//                    return fileUrl+car.getImg().get(0).getUrl();
//                } else if (StringUtil.isNotEmpty(equipment.getImg())) {
//                    return equipment.getImg();
//                } else {
//                    return null;
//                }
//            }else{
//                return null;
//            }
//        });
        //位置信息
        QueryWrapper<StockDetail> stockDetailQueryWrapper = new QueryWrapper<>();
        stockDetailQueryWrapper.eq("qr_code", qrCode);
        StockDetail stockDetail = stockDetailService.getOne(stockDetailQueryWrapper);
        if (stockDetail != null && StringUtil.isNotEmpty(stockDetail.getDescription())) {
            info.setDescription(stockDetail.getDescription());
        }

        // 获取
        Unit unit = unitMapper.selectById(equipment.getUnitId());
        ParsePropertyUtil.setting(info::setQrCode, () -> qrCode);
        ParsePropertyUtil.setting(info::setUnit, unit::getName);

        List<Car> cars = findAllSameTypeOfCars(car.getEquipmentId(), car.getOrgCode());
        info.setAmount(doubleTrans(1.0d));
        info.setTotal(doubleTrans(cars.size()));
        ParsePropertyUtil.setting(info::setEquProperties, () -> {
            return parseCarPerformance(findCarProperties(car));
        });
        return info;
    }

    public String doubleTrans(double num) {
        if(num % 1.0 == 0) {
            return String.valueOf((long)num);
        }
        return String.valueOf(num);
    }


    /**
     * 解析性能指标
     *
     * @param
     * @param
     */
    public List<EquPropertyResponse> parseCarPerformance(List<CarProperty> carProperties) {
        List<EquPropertyResponse> list = new ArrayList<>();

        for (CarProperty ep : carProperties) {
            if (ep == null || !StringUtil.isNotEmpty(ep.getValue())) {
                continue;
            }
            // 获取性能参数
//			PerfQuotaDefinition perfQuotaDefinition = perfQuotaDefinitionMapper
//					.selectById(ep.getPerfQuotaDefinitionId());
            EquipmentIndex equipmentIndex = equipmentIndexMapper.selectById(ep.getEquipmentIndexId());
            EquPropertyResponse epr = new EquPropertyResponse();
			ParsePropertyUtil.setting(epr::setName, () -> equipmentIndex.getPerfQuotaName());
            ParsePropertyUtil.setting(epr::setUnit, () -> equipmentIndex.getUnitName());
            ParsePropertyUtil.setting(epr::setIsImportentParameter, () -> true);
			ParsePropertyUtil.setting(epr::setTextLine, () -> {
			    if(StringUtil.isNotEmpty(equipmentIndex.getUnitName())){
                    return  equipmentIndex.getPerfQuotaName() + ":" + ep.getValue()+"("+equipmentIndex.getUnitName()+")";
                }else{
                    return  equipmentIndex.getPerfQuotaName() + ":" + ep.getValue();
                }
			});
            epr.setValue(ep.getValue());
            list.add(epr);
        }
        return list;
    }

    /**
     * 根据二维码查询车辆信息
     *
     * @param qrCode
     * @return
     */
    private EquipmentQrcode findEquipmentQRCode(String qrCode) {

        Map<String, Object> columnMap = new HashMap<String, Object>();
        columnMap.put("q_r_code", qrCode);
        List<EquipmentQrcode> result = equipmentQrcodeMapper.selectByMap(columnMap);
        if (result.isEmpty()) {
            return null;
        }

        return result.get(0);
    }

    /**
     * 该组织下相同类型的车辆
     *
     * @param equipmentId
     * @param orgCode
     * @return
     */
    private List<Car> findAllSameTypeOfCars(Long equipmentId, String orgCode) {
        Map<String, Object> columnMap = new HashMap<String, Object>();
        columnMap.put("equipment_id", equipmentId);
        columnMap.put("org_code", orgCode);

        return carMapper.selectByMap(columnMap);
    }

    /**
     * 查询该车辆下性能指标
     *
     * @param car
     * @return
     */
    private List<CarProperty> findCarProperties(Car car) {
        Map<String, Object> columnMap = new HashMap<String, Object>();
        columnMap.put("car_id", car.getId());
        List<CarProperty> list = carPropertyMapper.selectByMap(columnMap);
        return list;
    }

    /**
     * 获取车辆信息
     *
     * @param qrCode
     * @return
     */
    private Car getCar(String qrCode) throws IllegalArgumentException {
        EquipmentQrcode equipmentQRCode = findEquipmentQRCode(qrCode);
        if (null == equipmentQRCode) {
            throw new IllegalArgumentException("未查询到对应的车辆！");
        }

        Car car = carMapper.selectById(equipmentQRCode.getCarId());
        if (null == car) {
            throw new IllegalArgumentException("车辆不存在！");
        }

        return car;
    }

    private void checkScrapCar(String qrCode) throws IllegalArgumentException {
        Car car = findCar(qrCode);
        List<EquipmentOnCarAppVO> equipmentOnCarAppVOS = carMapper.selectEquipmentOnCarAppList(car.getId());
        if (equipmentOnCarAppVOS.size() >0){
            throw new BadRequest("有车载装备的车辆不能报废，请先卸载装备！");
        }
        SystemDic state = systemDicMapper.selectById(car.getCarState());
        CarStatusEnum status = CarStatusEnum.getEnum(car.getCarState().toString());

        Map<String, Object> columnMap = new HashMap<String, Object>();
        columnMap.put("car_id", car.getId());

//        List<EquipmentOnCar> equipmentOnCars = equipmentOnCarMapper.selectByMap(columnMap);
//
//        if (!equipmentOnCars.isEmpty()) {
//            throw new IllegalArgumentException("有车载装备的车辆不能报废，请先卸载装备！");
//        }
    }

    /**
     * 当前登录用户信息
     */
    /**
     * 当前登录用户信息
     */
    protected ReginParams getSelectedOrgInfo() {
        return JSONObject.parseObject(redisUtils.get(buildKey(getUserId(), getToken())).toString(), ReginParams.class);
    }

    protected String getToken() {
        String authToken = request.getHeader("token");
        if (authToken == null) {
            authToken = request.getHeader("X-Access-Token");
        }
        return authToken;
    }

    protected String getProduct() {
        String authToken = request.getHeader("product");
        if (authToken == null) {
            authToken = request.getParameter("product");
        }
        return authToken;
    }

    protected String getAppKey() {
        String authToken = request.getHeader("appKey");
        if (authToken == null) {
            authToken = request.getParameter("appKey");
        }
        return authToken;
    }

    protected String getChannelType() {
        String channelType = request.getHeader("channelType");
        if (channelType == null) {
            channelType = request.getParameter("channelType");
        }
        return channelType;
    }

    /**
     * 当前登录用户信息
     */
    protected AgencyUserModel getUserInfo() {
        AgencyUserModel userModel = null;
        if (getToken() != null) {
            RequestContext.setToken(getToken());
            RequestContext.setProduct(getProduct());
            RequestContext.setAppKey(getAppKey());
            FeignClientResult<?> feignClientResult;
            try {
                feignClientResult = Privilege.agencyUserClient.getme();
                userModel = (AgencyUserModel) feignClientResult.getResult();

            } catch (InnerInvokException e) {
                throw new RuntimeException(e.getMessage());
            }

        }
        return userModel;

    }

    protected String getUserId() {
        String userId = null;
        if (getUserInfo() != null) {
            userId = getUserInfo().getUserId();
        }
        return userId;
    }

    // redi缓存选择的用户信息
    private String buildKey(String userId, String token) {
    	 return RedisKey.buildReginKey(userId, token);

    }
}
