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.IMerchantAuthorizationPermissionsAdminService;
import com.liquidnet.client.admin.zhengzai.merchant.service.IMerchantAuthorizationRecordsAdminService;
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.CollectionUtil;
import com.liquidnet.commons.lang.util.IDGenerator;
import com.liquidnet.service.merchant.constant.MerchantPermissionConst;
import com.liquidnet.service.merchant.dto.vo.*;
import com.liquidnet.service.merchant.entity.MerchantAuthorizationPermissions;
import com.liquidnet.service.merchant.entity.MerchantAuthorizationRecords;
import com.liquidnet.service.merchant.mapper.MerchantAuthorizationRecordsMapper;
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.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

@Slf4j
@Service
public class MerchantAuthorizationRecordsAdminServiceImpl extends ServiceImpl<MerchantAuthorizationRecordsMapper, MerchantAuthorizationRecords> implements IMerchantAuthorizationRecordsAdminService {

    @Autowired
    MerchantRedisUtil merchantRedisUtil;

    @Autowired
    MerchantMongoUtil merchantMongoUtil;

    @Autowired
    MongoTemplate mongoTemplate;

    @Autowired
    IMerchantAuthorizationPermissionsAdminService authorizationPermissionsAdminService;

    @Override
    @Transactional
    public void authorizationInit(String performanceId, String cuid, String fieldId, String sponsorId) {
        // 创建者
        this.performanceCreator(performanceId, cuid);

        // 场地方
        this.performanceFielder(performanceId, cuid, fieldId);

        // 主办方
        this.performanceSponsor(performanceId, cuid, sponsorId);
    }

    // 创建者
    private boolean performanceCreator(String performanceId, String cuid) {
        LocalDateTime now = LocalDateTime.now();

        // 查询已有权限
        LambdaQueryWrapper<MerchantAuthorizationRecords> authorizationRecordsLambdaQueryWrapper = Wrappers.lambdaQuery(MerchantAuthorizationRecords.class);
        authorizationRecordsLambdaQueryWrapper.eq(MerchantAuthorizationRecords::getPerformanceId, performanceId);
        authorizationRecordsLambdaQueryWrapper.eq(MerchantAuthorizationRecords::getUidRole, "creator");
        authorizationRecordsLambdaQueryWrapper.eq(MerchantAuthorizationRecords::getDeletedAt, null);
        MerchantAuthorizationRecords authorizationRecords = getOne(authorizationRecordsLambdaQueryWrapper);

        // 是否已存在权限
        if (null != authorizationRecords) {
            if (!authorizationRecords.getUid().equals(cuid)) {
                // 前后 创建方一致 不处理
                return true;
            }
            // 前后 创建方不一致的情况不存在
            throw new LiquidnetServiceException();
        }

        // 添加权限
        ArrayList<MerchantAuthorizationRecords> authorizationRecordsArrayList = new ArrayList<>();
        ArrayList<MerchantAuthorizationPermissions> authorizationPermissionsArrayList = new ArrayList<>();

        // 授权记录
        // todo 用户信息
        MerchantAuthorizationRecords creatorAuthorizationRecords = new MerchantAuthorizationRecords();
        creatorAuthorizationRecords.setAuthorizationRecordId(IDGenerator.nextSnowId());
        creatorAuthorizationRecords.setPerformanceId(performanceId);
        creatorAuthorizationRecords.setUidRole("creator");
        creatorAuthorizationRecords.setUid(cuid);
        creatorAuthorizationRecords.setMobile("");
        creatorAuthorizationRecords.setName("");
        creatorAuthorizationRecords.setCuid(cuid);
        creatorAuthorizationRecords.setCuidRole("creator");
        creatorAuthorizationRecords.setCreatedAt(now);
        authorizationRecordsArrayList.add(creatorAuthorizationRecords);

        // 授权权限
        ArrayList<MerchantAuthorizationPermissionsVo> creatorAuthorizationPermissionsVos = new ArrayList<>();
        String[] fielderPermissionIds = {
                MerchantPermissionConst.PerformancePermission.READ.getId(),
                MerchantPermissionConst.PerformancePermission.EDIT.getId(),
                MerchantPermissionConst.PerformancePermission.ONOFF.getId(),
                MerchantPermissionConst.PerformancePermission.CHECK.getId(),
                MerchantPermissionConst.PerformancePermission.SALES.getId(),
                MerchantPermissionConst.PerformancePermission.ACCREDIT.getId()
        };
        for (String permissionId : fielderPermissionIds) {
            // entity
            MerchantAuthorizationPermissions creatorAuthorizationPermissions = new MerchantAuthorizationPermissions();
            creatorAuthorizationPermissions.setAuthorizationPermissionId(IDGenerator.nextSnowId());
            creatorAuthorizationPermissions.setAuthorizationRecordId(creatorAuthorizationRecords.getAuthorizationRecordId());
            creatorAuthorizationPermissions.setPermissionId(permissionId);
            creatorAuthorizationPermissions.setStartTime(now);
            creatorAuthorizationPermissions.setEndTime(now.plusYears(99));
            creatorAuthorizationPermissions.setCreatedAt(now);
            authorizationPermissionsArrayList.add(creatorAuthorizationPermissions);
            // vo
            MerchantAuthorizationPermissionsVo authorizationPermissionsVo = MerchantAuthorizationPermissionsVo.getNew();
            authorizationPermissionsVo.copy(creatorAuthorizationPermissions);
            creatorAuthorizationPermissionsVos.add(authorizationPermissionsVo);
        }

        // mysql
        boolean success = saveBatch(authorizationRecordsArrayList);
        if (!success) {
            // todo error
            throw new LiquidnetServiceException();
        }
        success = authorizationPermissionsAdminService.saveBatch(authorizationPermissionsArrayList);
        if (!success) {
            // todo error
            throw new LiquidnetServiceException();
        }

        // mongo
        MerchantAuthorizationRecordsVo authorizationRecordsVo = MerchantAuthorizationRecordsVo.getNew();
        authorizationRecordsVo.copy(creatorAuthorizationRecords);
        authorizationRecordsVo.setPermissionsVos(creatorAuthorizationPermissionsVos);
        mongoTemplate.insert(authorizationRecordsVo, MerchantAuthorizationRecordsVo.class.getSimpleName());

        return true;
    }

    // 授权场地方
    private boolean performanceFielder(String performanceId, String cuid,  String fieldId) {
        LocalDateTime now = LocalDateTime.now();

        // 查询已有权限
        LambdaQueryWrapper<MerchantAuthorizationRecords> authorizationRecordsLambdaQueryWrapper = Wrappers.lambdaQuery(MerchantAuthorizationRecords.class);
        authorizationRecordsLambdaQueryWrapper.eq(MerchantAuthorizationRecords::getPerformanceId, performanceId);
        authorizationRecordsLambdaQueryWrapper.eq(MerchantAuthorizationRecords::getUidRole, "fielder");
        authorizationRecordsLambdaQueryWrapper.eq(MerchantAuthorizationRecords::getDeletedAt, null);
        MerchantAuthorizationRecords authorizationRecords = getOne(authorizationRecordsLambdaQueryWrapper);

        // 查询场地方
        MerchantFieldsVo fieldsVo = merchantRedisUtil.getFieldsVoByFieldId(fieldId);

        // 是否已存在权限
        if (null != authorizationRecords) {
            if (authorizationRecords.getUid().equals(fieldsVo.getUid())) {
                // 前后 场地方一致 不处理
                return true;
            }

            // 前后 场地方不一致 删除旧权限 及 我的授权
            authorizationRecords.setUpdatedAt(now);
            authorizationRecords.setDeletedAt(now);

            // mysql
            LambdaUpdateWrapper<MerchantAuthorizationRecords> authorizationRecordsLambdaUpdateWrapper = Wrappers.lambdaUpdate(MerchantAuthorizationRecords.class);
            authorizationRecordsLambdaUpdateWrapper
                    .eq(MerchantAuthorizationRecords::getPerformanceId, performanceId)
                    .eq(MerchantAuthorizationRecords::getDeletedAt, null);
            authorizationRecordsLambdaUpdateWrapper.and(wrapper -> wrapper
                    .eq(MerchantAuthorizationRecords::getAuthorizationRecordId, authorizationRecords.getAuthorizationRecordId())
                    .or(wrapper1 -> wrapper1
                            .eq(MerchantAuthorizationRecords::getCuid, authorizationRecords.getUid())
                            .eq(MerchantAuthorizationRecords::getCuidRole, "fielder"))
            );
            authorizationRecordsLambdaUpdateWrapper.set(MerchantAuthorizationRecords::getUpdatedAt, authorizationRecords.getUpdatedAt());
            authorizationRecordsLambdaUpdateWrapper.set(MerchantAuthorizationRecords::getDeletedAt, authorizationRecords.getDeletedAt());
            boolean success = update(authorizationRecordsLambdaUpdateWrapper);
            if (!success) {
                // todo error
                throw new LiquidnetServiceException();
            }

            // mongo
            Criteria criteria = Criteria.where("performanceId").is(performanceId).and("deletedAt").is(null);
            criteria.orOperator(
                    Criteria.where("authorizationRecordId").is(authorizationRecords.getAuthorizationRecordId()),
                    Criteria.where("cuid").is(authorizationRecords.getUid()).and("cuidRole").is("fielder")
            );
            Query query = Query.query(criteria);
            mongoTemplate.remove(query, MerchantAuthorizationRecordsVo.class, MerchantAuthorizationRecordsVo.class.getSimpleName());
        }

        // 是否添加权限
        if (1 == fieldsVo.getClaimStatus()) {
            ArrayList<MerchantAuthorizationRecords> authorizationRecordsArrayList = new ArrayList<>();
            ArrayList<MerchantAuthorizationPermissions> authorizationPermissionsArrayList = new ArrayList<>();

            ArrayList<MerchantAuthorizationRecordsVo> authorizationRecordsVoArrayList = new ArrayList<>();

            // 授权记录 entity
            // todo 用户信息
            MerchantAuthorizationRecords fielderAuthorizationRecords = new MerchantAuthorizationRecords();
            fielderAuthorizationRecords.setAuthorizationRecordId(IDGenerator.nextSnowId());
            fielderAuthorizationRecords.setPerformanceId(performanceId);
            fielderAuthorizationRecords.setUidRole("fielder");
            fielderAuthorizationRecords.setUid(fieldsVo.getUid());
            fielderAuthorizationRecords.setMobile("");
            fielderAuthorizationRecords.setName("");
            fielderAuthorizationRecords.setCuid(cuid);
            fielderAuthorizationRecords.setCuidRole("creator");
            fielderAuthorizationRecords.setCreatedAt(now);
            authorizationRecordsArrayList.add(fielderAuthorizationRecords);
            // 授权权限 entity vo
            ArrayList<MerchantAuthorizationPermissionsVo> fielderAuthorizationPermissionsVos = new ArrayList<>();
            String[] fielderPermissionIds = {
                    MerchantPermissionConst.PerformancePermission.READ.getId(),
                    MerchantPermissionConst.PerformancePermission.CHECK.getId(),
                    MerchantPermissionConst.PerformancePermission.ACCREDIT.getId()
            };
            for (String permissionId : fielderPermissionIds) {
                MerchantAuthorizationPermissions fielderAuthorizationPermissions = new MerchantAuthorizationPermissions();
                fielderAuthorizationPermissions.setAuthorizationPermissionId(IDGenerator.nextSnowId());
                fielderAuthorizationPermissions.setAuthorizationRecordId(fielderAuthorizationRecords.getAuthorizationRecordId());
                fielderAuthorizationPermissions.setPermissionId(permissionId);
                fielderAuthorizationPermissions.setStartTime(now);
                fielderAuthorizationPermissions.setEndTime(now.plusYears(99));
                fielderAuthorizationPermissions.setCreatedAt(now);
                authorizationPermissionsArrayList.add(fielderAuthorizationPermissions);

                MerchantAuthorizationPermissionsVo fielderAuthorizationPermissionsVo = MerchantAuthorizationPermissionsVo.getNew();
                fielderAuthorizationPermissionsVo.copy(fielderAuthorizationPermissions);
                fielderAuthorizationPermissionsVos.add(fielderAuthorizationPermissionsVo);
            }
            // 授权记录 vo
            MerchantAuthorizationRecordsVo fielderAuthorizationRecordsVo = MerchantAuthorizationRecordsVo.getNew();
            fielderAuthorizationRecordsVo.copy(fielderAuthorizationRecords);
            fielderAuthorizationRecordsVo.setPermissionsVos(fielderAuthorizationPermissionsVos);
            authorizationRecordsVoArrayList.add(fielderAuthorizationRecordsVo);

            // 查询默认验票员
            List<MerchantFieldCheckersVo> fieldCheckersVos = merchantRedisUtil.getFieldCheckersVosByFieldId(fieldId);
            if (!CollectionUtil.isEmpty(fieldCheckersVos)) {
                // 验票员 授权权限
                String[] checkerPermissionIds = {
                        MerchantPermissionConst.PerformancePermission.CHECK.getId()
                };

                for (MerchantFieldCheckersVo fieldCheckersVo: fieldCheckersVos) {
                    // 验票员 授权记录 entity
                    MerchantAuthorizationRecords checkerAuthorizationRecords = new MerchantAuthorizationRecords();
                    checkerAuthorizationRecords.setAuthorizationRecordId(IDGenerator.nextSnowId());
                    checkerAuthorizationRecords.setPerformanceId(performanceId);
                    checkerAuthorizationRecords.setUidRole("checker");
                    checkerAuthorizationRecords.setUid(fieldCheckersVo.getUid());
                    checkerAuthorizationRecords.setMobile(fieldCheckersVo.getMobile());
                    checkerAuthorizationRecords.setName(fieldCheckersVo.getName());
                    checkerAuthorizationRecords.setCuid(fieldsVo.getUid());
                    checkerAuthorizationRecords.setCuidRole("fielder");
                    checkerAuthorizationRecords.setCreatedAt(now);
                    authorizationRecordsArrayList.add(checkerAuthorizationRecords);

                    // 验票员 授权权限 entity vo
                    ArrayList<MerchantAuthorizationPermissionsVo> checkerAuthorizationPermissionsVos = new ArrayList<>();
                    for (String permissionId : checkerPermissionIds) {
                        MerchantAuthorizationPermissions checkerAuthorizationPermissions = new MerchantAuthorizationPermissions();
                        checkerAuthorizationPermissions.setAuthorizationPermissionId(IDGenerator.nextSnowId());
                        checkerAuthorizationPermissions.setAuthorizationRecordId(checkerAuthorizationRecords.getAuthorizationRecordId());
                        checkerAuthorizationPermissions.setPermissionId(permissionId);
                        checkerAuthorizationPermissions.setStartTime(now);
                        checkerAuthorizationPermissions.setEndTime(now.plusYears(99));
                        checkerAuthorizationPermissions.setCreatedAt(now);
                        authorizationPermissionsArrayList.add(checkerAuthorizationPermissions);

                        MerchantAuthorizationPermissionsVo checkerAuthorizationPermissionsVo = MerchantAuthorizationPermissionsVo.getNew();
                        checkerAuthorizationPermissionsVo.copy(checkerAuthorizationPermissions);
                        checkerAuthorizationPermissionsVos.add(checkerAuthorizationPermissionsVo);
                    }

                    // 验票员 授权记录 vo
                    MerchantAuthorizationRecordsVo checkerAuthorizationRecordsVo = MerchantAuthorizationRecordsVo.getNew();
                    checkerAuthorizationRecordsVo.copy(checkerAuthorizationRecords);
                    checkerAuthorizationRecordsVo.setPermissionsVos(checkerAuthorizationPermissionsVos);
                    authorizationRecordsVoArrayList.add(checkerAuthorizationRecordsVo);
                }
            }

            // mysql
            boolean success = saveBatch(authorizationRecordsArrayList);
            if (!success) {
                // todo error
                throw new LiquidnetServiceException();
            }
            success = authorizationPermissionsAdminService.saveBatch(authorizationPermissionsArrayList);
            if (!success) {
                // todo error
                throw new LiquidnetServiceException();
            }

            // mongo
            mongoTemplate.insert(authorizationRecordsVoArrayList, MerchantAuthorizationRecordsVo.class.getSimpleName());
        }

        return true;
    }

    // 授权主办方
    private boolean performanceSponsor(String performanceId, String cuid, String sponsorId) {
        LocalDateTime now = LocalDateTime.now();

        // 查询已有权限
        LambdaQueryWrapper<MerchantAuthorizationRecords> authorizationRecordsLambdaQueryWrapper = Wrappers.lambdaQuery(MerchantAuthorizationRecords.class);
        authorizationRecordsLambdaQueryWrapper.eq(MerchantAuthorizationRecords::getPerformanceId, performanceId);
        authorizationRecordsLambdaQueryWrapper.eq(MerchantAuthorizationRecords::getUidRole, "sponsor");
        authorizationRecordsLambdaQueryWrapper.eq(MerchantAuthorizationRecords::getDeletedAt, null);
        MerchantAuthorizationRecords authorizationRecords = getOne(authorizationRecordsLambdaQueryWrapper);

        // 查询主办方
        MerchantSponsorsVo sponsorsVo = merchantRedisUtil.getSponsorsVoBySponsorId(sponsorId);

        // 是否已存在权限
        if (null != authorizationRecords) {
            if (authorizationRecords.getUid().equals(sponsorsVo.getUid())) {
                // 前后 主办方一致 不处理
                return true;
            }

            // 前后 主办方不一致 删除旧权限 及 我的授权
            authorizationRecords.setUpdatedAt(now);
            authorizationRecords.setDeletedAt(now);

            // mysql
            LambdaUpdateWrapper<MerchantAuthorizationRecords> authorizationRecordsLambdaUpdateWrapper = Wrappers.lambdaUpdate(MerchantAuthorizationRecords.class);
            authorizationRecordsLambdaUpdateWrapper
                    .eq(MerchantAuthorizationRecords::getPerformanceId, performanceId)
                    .eq(MerchantAuthorizationRecords::getDeletedAt, null);
            authorizationRecordsLambdaUpdateWrapper.and(wrapper -> wrapper
                    .eq(MerchantAuthorizationRecords::getAuthorizationRecordId, authorizationRecords.getAuthorizationRecordId())
                    .or(wrapper1 -> wrapper1
                            .eq(MerchantAuthorizationRecords::getCuid, authorizationRecords.getUid())
                            .eq(MerchantAuthorizationRecords::getCuidRole, "sponsor"))
            );
            authorizationRecordsLambdaUpdateWrapper.set(MerchantAuthorizationRecords::getUpdatedAt, authorizationRecords.getUpdatedAt());
            authorizationRecordsLambdaUpdateWrapper.set(MerchantAuthorizationRecords::getDeletedAt, authorizationRecords.getDeletedAt());
            boolean success = update(authorizationRecordsLambdaUpdateWrapper);
            if (!success) {
                // todo error
                throw new LiquidnetServiceException();
            }

            // mongo
            Criteria criteria = Criteria.where("performanceId").is(performanceId).and("deletedAt").is(null);
            criteria.orOperator(
                    Criteria.where("authorizationRecordId").is(authorizationRecords.getAuthorizationRecordId()),
                    Criteria.where("cuid").is(authorizationRecords.getUid()).and("cuidRole").is("sponsor")
            );
            Query query = Query.query(criteria);
            mongoTemplate.remove(query, MerchantAuthorizationRecordsVo.class, MerchantAuthorizationRecordsVo.class.getSimpleName());
        }

        // 是否添加权限
        if (!sponsorsVo.getUid().isEmpty()) {
            ArrayList<MerchantAuthorizationRecords> authorizationRecordsArrayList = new ArrayList<>();
            ArrayList<MerchantAuthorizationPermissions> authorizationPermissionsArrayList = new ArrayList<>();

            // 授权记录 entity
            // todo 用户信息
            MerchantAuthorizationRecords sponsorAuthorizationRecords = new MerchantAuthorizationRecords();
            sponsorAuthorizationRecords.setAuthorizationRecordId(IDGenerator.nextSnowId());
            sponsorAuthorizationRecords.setPerformanceId(performanceId);
            sponsorAuthorizationRecords.setUidRole("sponsor");
            sponsorAuthorizationRecords.setUid(sponsorsVo.getUid());
            sponsorAuthorizationRecords.setMobile("");
            sponsorAuthorizationRecords.setName("");
            sponsorAuthorizationRecords.setCuid(cuid);
            sponsorAuthorizationRecords.setCuidRole("creator");
            sponsorAuthorizationRecords.setCreatedAt(now);
            authorizationRecordsArrayList.add(sponsorAuthorizationRecords);
            // 授权权限 entity vo
            ArrayList<MerchantAuthorizationPermissionsVo> sponsorAuthorizationPermissionsVos = new ArrayList<>();
            String[] fielderPermissionIds = {
                    MerchantPermissionConst.PerformancePermission.READ.getId(),
                    MerchantPermissionConst.PerformancePermission.CHECK.getId(),
                    MerchantPermissionConst.PerformancePermission.SALES.getId(),
                    MerchantPermissionConst.PerformancePermission.ACCREDIT.getId()
            };
            for (String permissionId : fielderPermissionIds) {
                MerchantAuthorizationPermissions sponsorAuthorizationPermissions = new MerchantAuthorizationPermissions();
                sponsorAuthorizationPermissions.setAuthorizationPermissionId(IDGenerator.nextSnowId());
                sponsorAuthorizationPermissions.setAuthorizationRecordId(sponsorAuthorizationRecords.getAuthorizationRecordId());
                sponsorAuthorizationPermissions.setPermissionId(permissionId);
                sponsorAuthorizationPermissions.setStartTime(now);
                sponsorAuthorizationPermissions.setEndTime(now.plusYears(99));
                sponsorAuthorizationPermissions.setCreatedAt(now);
                authorizationPermissionsArrayList.add(sponsorAuthorizationPermissions);

                MerchantAuthorizationPermissionsVo sponsorAuthorizationPermissionsVo = MerchantAuthorizationPermissionsVo.getNew();
                sponsorAuthorizationPermissionsVo.copy(sponsorAuthorizationPermissions);
                sponsorAuthorizationPermissionsVos.add(sponsorAuthorizationPermissionsVo);
            }
            // 授权记录 vo
            MerchantAuthorizationRecordsVo sponsorAuthorizationRecordsVo = MerchantAuthorizationRecordsVo.getNew();
            sponsorAuthorizationRecordsVo.copy(sponsorAuthorizationRecords);
            sponsorAuthorizationRecordsVo.setPermissionsVos(sponsorAuthorizationPermissionsVos);

            // mysql
            boolean success = saveBatch(authorizationRecordsArrayList);
            if (!success) {
                // todo error
                throw new LiquidnetServiceException();
            }
            success = authorizationPermissionsAdminService.saveBatch(authorizationPermissionsArrayList);
            if (!success) {
                // todo error
                throw new LiquidnetServiceException();
            }

            // mongo
            mongoTemplate.insert(sponsorAuthorizationRecordsVo, MerchantAuthorizationRecordsVo.class.getSimpleName());
        }

        return true;
    }
}
