package com.liquidnet.client.admin.zhengzai.merchant.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.liquidnet.client.admin.zhengzai.merchant.service.IMerchantCompaniesAdminService;
import com.liquidnet.client.admin.zhengzai.merchant.service.IMerchantFieldAppliesAdminService;
import com.liquidnet.client.admin.zhengzai.merchant.service.IMerchantFieldsAdminService;
import com.liquidnet.client.admin.zhengzai.merchant.utils.MerchantMongoUtil;
import com.liquidnet.client.admin.zhengzai.merchant.utils.MerchantRedisUtil;
import com.liquidnet.common.exception.LiquidnetServiceException;
import com.liquidnet.commons.lang.util.IDGenerator;
import com.liquidnet.service.merchant.dto.vo.MerchantCompaniesVo;
import com.liquidnet.service.merchant.dto.vo.MerchantFieldAppliesVo;
import com.liquidnet.service.merchant.dto.vo.MerchantFieldsVo;
import com.liquidnet.service.merchant.entity.MerchantCompanies;
import com.liquidnet.service.merchant.entity.MerchantFieldApplies;
import com.liquidnet.service.merchant.entity.MerchantFields;
import com.liquidnet.service.merchant.mapper.MerchantFieldAppliesMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.IntStream;

@Slf4j
@Service
public class MerchantFieldAppliesAdminServiceImpl extends ServiceImpl<MerchantFieldAppliesMapper, MerchantFieldApplies> implements IMerchantFieldAppliesAdminService {

    @Autowired
    MerchantRedisUtil merchantRedisUtil;

    @Autowired
    MerchantMongoUtil merchantMongoUtil;

    @Autowired
    MongoTemplate mongoTemplate;


    @Autowired
    IMerchantFieldsAdminService merchantFieldsAdminService;

    @Autowired
    IMerchantCompaniesAdminService merchantCompaniesAdminService;


    @Override
    @Transactional
    public boolean applyApprove(String uid, String fieldApplyId, String auditUid, String auditName) {
        List<MerchantFieldAppliesVo> fieldAppliesVos = merchantRedisUtil.getFieldAppliesVosByUid(uid);
        if (CollectionUtils.isEmpty(fieldAppliesVos)) {
            // todo error
            throw new LiquidnetServiceException();
        }
        int idx = IntStream.range(0, fieldAppliesVos.size())
                .filter(i -> fieldAppliesVos.get(i).getFieldApplyId().equals(fieldApplyId))
                .findFirst()
                .orElse(-1);
        if (idx < 0) {
            // todo error
            throw new LiquidnetServiceException();
        }
        MerchantFieldAppliesVo fieldAppliesVo = fieldAppliesVos.get(idx);
        if (0 != fieldAppliesVo.getApplyStatus()) {
            // todo error
            throw new LiquidnetServiceException();
        }

        LocalDateTime now = LocalDateTime.now();

        if (fieldAppliesVo.getApplyType().equals("claim")) {
            // 认领逻辑

            // 公司 entity mysql
            MerchantCompanies companiesEntity = new MerchantCompanies();
            companiesEntity.setCompanyId(IDGenerator.nextSnowId());
            companiesEntity.setName(fieldAppliesVo.getCompanyName());
            companiesEntity.setLicenseCode(fieldAppliesVo.getLicenseCode());
            companiesEntity.setLicenseImg(fieldAppliesVo.getLicenseImg());
            companiesEntity.setLegalName(fieldAppliesVo.getLegalName());
            companiesEntity.setLegalIdentity(fieldAppliesVo.getLegalIdentity());
            companiesEntity.setLegalIdentityObverse(fieldAppliesVo.getLegalIdentityObverse());
            companiesEntity.setLegalIdentityReverse(fieldAppliesVo.getLegalIdentityReverse());
            companiesEntity.setCreatedAt(now);
            boolean success = merchantCompaniesAdminService.save(companiesEntity);
            if (!success) {
                // todo error
                throw new LiquidnetServiceException();
            }
            // 公司 vo
            MerchantCompaniesVo companiesVo = MerchantCompaniesVo.getNew();
            companiesVo.copy(companiesEntity);

            // 场地 entity mysql
            LambdaQueryWrapper<MerchantFields> fieldsLambdaQueryWrapper = Wrappers.lambdaQuery(MerchantFields.class);
            fieldsLambdaQueryWrapper.eq(MerchantFields::getFieldId, fieldAppliesVo.getFieldId());
            MerchantFields fieldsEntity = merchantFieldsAdminService.getOne(fieldsLambdaQueryWrapper);
            if (null == fieldsEntity) {
                // todo error
                throw new LiquidnetServiceException();
            }
            if (2 != fieldsEntity.getClaimStatus() || !fieldsEntity.getUid().equals(uid)) {
                // todo error
                throw new LiquidnetServiceException();
            }
            fieldsEntity.setIsOnline(1);
            fieldsEntity.setClaimStatus(1);
            fieldsEntity.setUid(uid);
            fieldsEntity.setIsCheck(0);
            fieldsEntity.setName(fieldAppliesVo.getName());
            fieldsEntity.setLogo(fieldAppliesVo.getLogo());
            fieldsEntity.setBackground(fieldAppliesVo.getBackground());
            fieldsEntity.setDescription(fieldAppliesVo.getDescription());
            fieldsEntity.setBuiltDate(LocalDate.parse(fieldAppliesVo.getBuiltDate()));
            fieldsEntity.setProvinceId(fieldAppliesVo.getProvinceId());
            fieldsEntity.setProvinceName(fieldAppliesVo.getProvinceName());
            fieldsEntity.setCityId(fieldAppliesVo.getCityId());
            fieldsEntity.setCityName(fieldAppliesVo.getCityName());
            fieldsEntity.setDistrictId(fieldAppliesVo.getDistrictId());
            fieldsEntity.setDistrictName(fieldAppliesVo.getDistrictName());
            fieldsEntity.setAddress(fieldAppliesVo.getAddress());
            fieldsEntity.setLongitude(fieldAppliesVo.getLongitude());
            fieldsEntity.setLatitude(fieldAppliesVo.getLatitude());
            fieldsEntity.setContactName(fieldAppliesVo.getContactName());
            fieldsEntity.setContactEmail(fieldAppliesVo.getContactEmail());
            fieldsEntity.setCompanyId(companiesVo.getCompanyId());
            fieldsEntity.setUpdatedAt(now);
            LambdaUpdateWrapper<MerchantFields> fieldsLambdaUpdateWrapper = Wrappers.lambdaUpdate(MerchantFields.class);
            fieldsLambdaUpdateWrapper.eq(MerchantFields::getFieldId, fieldsEntity.getFieldId());
            success = merchantFieldsAdminService.update(fieldsEntity, fieldsLambdaUpdateWrapper);
            if (!success) {
                // todo error
                throw new LiquidnetServiceException();
            }
            // 场地 vo
            MerchantFieldsVo fieldsVo = MerchantFieldsVo.getNew();
            fieldsVo.copy(fieldsEntity);
            fieldsVo.setCompaniesVo(companiesVo);

            // 场地申请 vo
            fieldAppliesVo.setApplyStatus(1);
            fieldAppliesVo.setReject("");
            fieldAppliesVo.setAuditUid(auditUid);
            fieldAppliesVo.setAuditName(auditName);
            fieldAppliesVo.setAuditedAt(now);
            fieldAppliesVo.setUpdatedAt(now);

            // 场地申请 mysql
            LambdaUpdateWrapper<MerchantFieldApplies> fieldAppliesLambdaUpdateWrapper = Wrappers.lambdaUpdate(MerchantFieldApplies.class);
            fieldAppliesLambdaUpdateWrapper.eq(MerchantFieldApplies::getFieldApplyId, fieldAppliesVo.getFieldApplyId());
            fieldAppliesLambdaUpdateWrapper.set(MerchantFieldApplies::getApplyStatus, fieldAppliesVo.getApplyStatus());
            fieldAppliesLambdaUpdateWrapper.set(MerchantFieldApplies::getReject, fieldAppliesVo.getReject());
            fieldAppliesLambdaUpdateWrapper.set(MerchantFieldApplies::getAuditUid, fieldAppliesVo.getAuditUid());
            fieldAppliesLambdaUpdateWrapper.set(MerchantFieldApplies::getAuditName, fieldAppliesVo.getAuditName());
            fieldAppliesLambdaUpdateWrapper.set(MerchantFieldApplies::getAuditedAt, fieldAppliesVo.getAuditedAt());
            fieldAppliesLambdaUpdateWrapper.set(MerchantFieldApplies::getUpdatedAt, fieldAppliesVo.getUpdatedAt());
            success = update(fieldAppliesLambdaUpdateWrapper);
            if (!success) {
                // todo error
                throw new LiquidnetServiceException();
            }

            // 场地 sync mongo
            merchantMongoUtil.setFieldsVoByFieldId(fieldsVo.getFieldId(), fieldsVo);

            // 场地 sync redis
            merchantRedisUtil.setFieldsVoByFieldId(fieldsVo.getFieldId(), fieldsVo);

            // 场地申请 redis
            merchantRedisUtil.setFieldAppliesVosByUid(uid, fieldAppliesVos);

        } else {
            // 创建逻辑

            // 公司 entity mysql
            MerchantCompanies companiesEntity = new MerchantCompanies();
            companiesEntity.setCompanyId(IDGenerator.nextSnowId());
            companiesEntity.setName(fieldAppliesVo.getCompanyName());
            companiesEntity.setLicenseCode(fieldAppliesVo.getLicenseCode());
            companiesEntity.setLicenseImg(fieldAppliesVo.getLicenseImg());
            companiesEntity.setLegalName(fieldAppliesVo.getLegalName());
            companiesEntity.setLegalIdentity(fieldAppliesVo.getLegalIdentity());
            companiesEntity.setLegalIdentityObverse(fieldAppliesVo.getLegalIdentityObverse());
            companiesEntity.setLegalIdentityReverse(fieldAppliesVo.getLegalIdentityReverse());
            companiesEntity.setCreatedAt(now);
            boolean success = merchantCompaniesAdminService.save(companiesEntity);
            if (!success) {
                // todo error
                throw new LiquidnetServiceException();
            }
            // 公司 vo
            MerchantCompaniesVo companiesVo = MerchantCompaniesVo.getNew();
            companiesVo.copy(companiesEntity);

            // 场地 entity mysql
            MerchantFields fieldsEntity = new MerchantFields();
            fieldsEntity.setFieldId(IDGenerator.nextSnowId());
            fieldsEntity.setIsOnline(1);
            fieldsEntity.setClaimStatus(1);
            fieldsEntity.setUid(uid);
            fieldsEntity.setIsCheck(0);
            fieldsEntity.setName(fieldAppliesVo.getName());
            fieldsEntity.setLogo(fieldAppliesVo.getLogo());
            fieldsEntity.setBackground(fieldAppliesVo.getBackground());
            fieldsEntity.setDescription(fieldAppliesVo.getDescription());
            fieldsEntity.setBuiltDate(LocalDate.parse(fieldAppliesVo.getBuiltDate()));
            fieldsEntity.setProvinceId(fieldAppliesVo.getProvinceId());
            fieldsEntity.setProvinceName(fieldAppliesVo.getProvinceName());
            fieldsEntity.setCityId(fieldAppliesVo.getCityId());
            fieldsEntity.setCityName(fieldAppliesVo.getCityName());
            fieldsEntity.setDistrictId(fieldAppliesVo.getDistrictId());
            fieldsEntity.setDistrictName(fieldAppliesVo.getDistrictName());
            fieldsEntity.setAddress(fieldAppliesVo.getAddress());
            fieldsEntity.setLongitude(fieldAppliesVo.getLongitude());
            fieldsEntity.setLatitude(fieldAppliesVo.getLatitude());
            fieldsEntity.setContactName(fieldAppliesVo.getContactName());
            fieldsEntity.setContactEmail(fieldAppliesVo.getContactEmail());
            fieldsEntity.setCompanyId(companiesVo.getCompanyId());
            fieldsEntity.setCreatedAt(now);
            success = merchantFieldsAdminService.save(fieldsEntity);
            if (!success) {
                // todo error
                throw new LiquidnetServiceException();
            }
            // 场地 vo
            MerchantFieldsVo fieldsVo = MerchantFieldsVo.getNew();
            fieldsVo.copy(fieldsEntity);
            fieldsVo.setCompaniesVo(companiesVo);

            // 场地申请 vo
            fieldAppliesVo.setApplyStatus(1);
            fieldAppliesVo.setReject("");
            fieldAppliesVo.setAuditUid(auditUid);
            fieldAppliesVo.setAuditName(auditName);
            fieldAppliesVo.setAuditedAt(now);
            fieldAppliesVo.setUpdatedAt(now);
            fieldAppliesVo.setFieldId(fieldsVo.getFieldId());

            // 场地申请 mysql
            LambdaUpdateWrapper<MerchantFieldApplies> fieldAppliesLambdaUpdateWrapper = Wrappers.lambdaUpdate(MerchantFieldApplies.class);
            fieldAppliesLambdaUpdateWrapper.eq(MerchantFieldApplies::getFieldApplyId, fieldAppliesVo.getFieldApplyId());
            fieldAppliesLambdaUpdateWrapper.set(MerchantFieldApplies::getApplyStatus, fieldAppliesVo.getApplyStatus());
            fieldAppliesLambdaUpdateWrapper.set(MerchantFieldApplies::getReject, fieldAppliesVo.getReject());
            fieldAppliesLambdaUpdateWrapper.set(MerchantFieldApplies::getAuditUid, fieldAppliesVo.getAuditUid());
            fieldAppliesLambdaUpdateWrapper.set(MerchantFieldApplies::getAuditName, fieldAppliesVo.getAuditName());
            fieldAppliesLambdaUpdateWrapper.set(MerchantFieldApplies::getAuditedAt, fieldAppliesVo.getAuditedAt());
            fieldAppliesLambdaUpdateWrapper.set(MerchantFieldApplies::getUpdatedAt, fieldAppliesVo.getUpdatedAt());
            fieldAppliesLambdaUpdateWrapper.set(MerchantFieldApplies::getFieldId, fieldAppliesVo.getFieldId());
            success = update(fieldAppliesLambdaUpdateWrapper);
            if (!success) {
                // todo error
                throw new LiquidnetServiceException();
            }

            // 场地 sync mongo
            merchantMongoUtil.setFieldsVoByFieldId(fieldsVo.getFieldId(), fieldsVo);

            // 场地 sync redis
            merchantRedisUtil.setFieldsVoByFieldId(fieldsVo.getFieldId(), fieldsVo);

            // 场地申请 sync redis
            merchantRedisUtil.setFieldAppliesVosByUid(uid, fieldAppliesVos);
        }

        return true;
    }

    @Override
    public boolean applyReject(String uid, String fieldApplyId, String auditUid, String auditName, String reject) {
        List<MerchantFieldAppliesVo> fieldAppliesVos = merchantRedisUtil.getFieldAppliesVosByUid(uid);
        if (CollectionUtils.isEmpty(fieldAppliesVos)) {
            // todo error
            throw new LiquidnetServiceException();
        }
        int idx = IntStream.range(0, fieldAppliesVos.size())
                .filter(i -> fieldAppliesVos.get(i).getFieldApplyId().equals(fieldApplyId))
                .findFirst()
                .orElse(-1);
        if (idx < 0) {
            // todo error
            throw new LiquidnetServiceException();
        }
        MerchantFieldAppliesVo fieldAppliesVo = fieldAppliesVos.get(idx);
        if (0 != fieldAppliesVo.getApplyStatus()) {
            // todo error
            throw new LiquidnetServiceException();
        }

        LocalDateTime now = LocalDateTime.now();

        if (fieldAppliesVo.getApplyType().equals("claim")) {
            // 驳回认领逻辑

            // 场地 vo
            MerchantFieldsVo fieldsVo = merchantRedisUtil.getFieldsVoByFieldId(fieldAppliesVo.getFieldId());
            if (null == fieldsVo) {
                // todo error
                throw new LiquidnetServiceException();
            }
            if (2 != fieldsVo.getClaimStatus() || !fieldsVo.getUid().equals(uid)) {
                // todo error
                throw new LiquidnetServiceException();
            }
            fieldsVo.setClaimStatus(0);
            fieldsVo.setUid("");
            fieldsVo.setUpdatedAt(now);

            // 场地 mysql
            LambdaUpdateWrapper<MerchantFields> fieldsLambdaUpdateWrapper = Wrappers.lambdaUpdate(MerchantFields.class);
            fieldsLambdaUpdateWrapper.eq(MerchantFields::getFieldId, fieldsVo.getFieldId());
            fieldsLambdaUpdateWrapper.set(MerchantFields::getClaimStatus, fieldsVo.getClaimStatus());
            fieldsLambdaUpdateWrapper.set(MerchantFields::getUid, fieldsVo.getUid());
            fieldsLambdaUpdateWrapper.set(MerchantFields::getUpdatedAt, fieldsVo.getUpdatedAt());
            boolean success = merchantFieldsAdminService.update(fieldsLambdaUpdateWrapper);
            if (!success) {
                // todo error
                throw new LiquidnetServiceException();
            }

            // 场地申请 vo
            fieldAppliesVo.setApplyStatus(2);
            fieldAppliesVo.setReject(reject);
            fieldAppliesVo.setAuditUid(auditUid);
            fieldAppliesVo.setAuditName(auditName);
            fieldAppliesVo.setAuditedAt(now);
            fieldAppliesVo.setUpdatedAt(now);

            // 场地申请 mysql
            LambdaUpdateWrapper<MerchantFieldApplies> fieldAppliesLambdaUpdateWrapper = Wrappers.lambdaUpdate(MerchantFieldApplies.class);
            fieldAppliesLambdaUpdateWrapper.eq(MerchantFieldApplies::getFieldApplyId, fieldAppliesVo.getFieldApplyId());
            fieldAppliesLambdaUpdateWrapper.set(MerchantFieldApplies::getApplyStatus, fieldAppliesVo.getApplyStatus());
            fieldAppliesLambdaUpdateWrapper.set(MerchantFieldApplies::getReject, fieldAppliesVo.getReject());
            fieldAppliesLambdaUpdateWrapper.set(MerchantFieldApplies::getAuditUid, fieldAppliesVo.getAuditUid());
            fieldAppliesLambdaUpdateWrapper.set(MerchantFieldApplies::getAuditName, fieldAppliesVo.getAuditName());
            fieldAppliesLambdaUpdateWrapper.set(MerchantFieldApplies::getAuditedAt, fieldAppliesVo.getAuditedAt());
            fieldAppliesLambdaUpdateWrapper.set(MerchantFieldApplies::getUpdatedAt, fieldAppliesVo.getUpdatedAt());
            success = update(fieldAppliesLambdaUpdateWrapper);
            if (!success) {
                // todo error
                throw new LiquidnetServiceException();
            }

            // 场地 sync mongo
            Query query = Query.query(Criteria.where("fieldId").is(fieldsVo.getFieldId()));
            Update update = Update.update("claimStatus", fieldsVo.getClaimStatus()).set("uid", fieldsVo.getUid()).set("updatedAt", fieldsVo.getUpdatedAt());
            mongoTemplate.updateFirst(query, update, MerchantFieldsVo.class, MerchantFieldsVo.class.getSimpleName());

            // 场地 sync redis
            merchantRedisUtil.setFieldsVoByFieldId(fieldsVo.getFieldId(), fieldsVo);

            // 场地申请 sync redis
            merchantRedisUtil.setFieldAppliesVosByUid(uid, fieldAppliesVos);

        } else {
            // 驳回创建逻辑

            // 场地申请 vo
            fieldAppliesVo.setApplyStatus(2);
            fieldAppliesVo.setReject(reject);
            fieldAppliesVo.setAuditUid(auditUid);
            fieldAppliesVo.setAuditName(auditName);
            fieldAppliesVo.setAuditedAt(now);
            fieldAppliesVo.setUpdatedAt(now);

            // 场地申请 mysql
            LambdaUpdateWrapper<MerchantFieldApplies> fieldAppliesLambdaUpdateWrapper = Wrappers.lambdaUpdate(MerchantFieldApplies.class);
            fieldAppliesLambdaUpdateWrapper.eq(MerchantFieldApplies::getFieldApplyId, fieldAppliesVo.getFieldApplyId());
            fieldAppliesLambdaUpdateWrapper.set(MerchantFieldApplies::getApplyStatus, fieldAppliesVo.getApplyStatus());
            fieldAppliesLambdaUpdateWrapper.set(MerchantFieldApplies::getReject, fieldAppliesVo.getReject());
            fieldAppliesLambdaUpdateWrapper.set(MerchantFieldApplies::getAuditUid, fieldAppliesVo.getAuditUid());
            fieldAppliesLambdaUpdateWrapper.set(MerchantFieldApplies::getAuditName, fieldAppliesVo.getAuditName());
            fieldAppliesLambdaUpdateWrapper.set(MerchantFieldApplies::getAuditedAt, fieldAppliesVo.getAuditedAt());
            fieldAppliesLambdaUpdateWrapper.set(MerchantFieldApplies::getUpdatedAt, fieldAppliesVo.getUpdatedAt());
            boolean success = update(fieldAppliesLambdaUpdateWrapper);
            if (!success) {
                // todo error
                throw new LiquidnetServiceException();
            }

            // 场地申请 sync redis
            merchantRedisUtil.setFieldAppliesVosByUid(uid, fieldAppliesVos);
        }

        return true;
    }


}
