package com.yd.csf.service.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.google.gson.Gson;
import com.yd.auth.core.dto.AuthUserDto;
import com.yd.auth.core.utils.SecurityUtil;
import com.yd.common.constant.CommonConstant;
import com.yd.common.enums.CommonEnum;
import com.yd.common.enums.ResultCode;
import com.yd.common.exception.BusinessException;
import com.yd.common.utils.RandomStringGenerator;

import com.yd.csf.service.dao.FnaMapper;
import com.yd.csf.service.dto.*;
import com.yd.csf.service.enums.FnaStatusEnum;
import com.yd.csf.service.model.Customer;
import com.yd.csf.service.model.Fna;
import com.yd.csf.service.model.FnaForm;
import com.yd.csf.service.service.CustomerService;
import com.yd.csf.service.service.FnaFormService;
import com.yd.csf.service.service.FnaService;
import com.yd.csf.service.vo.FnaVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * fna服务实现
 *
 */
@Service
@Slf4j
public class FnaServiceImpl extends ServiceImpl<FnaMapper, Fna> implements FnaService {

    @Autowired
    private FnaFormService fnaFormService;

    @Resource
    private CustomerService customerService;

    private final static Gson GSON = new Gson();

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> addFna(FnaAddRequest fnaAddRequest) {
        Fna fna = new Fna();
        BeanUtils.copyProperties(fnaAddRequest, fna);

        // 获取Security上下文当前用户的登录信息
        AuthUserDto authUserDto = SecurityUtil.getCurrentLoginUser();
        String userBizId = authUserDto.getUserBizId();

        fna.setUserBizId(userBizId);
        fna.setFnaBizId(RandomStringGenerator.generateBizId16(CommonEnum.UID_TYPE_FNA.getCode()));
        fna.setCreatorId(userBizId);
        fna.setUpdaterId(userBizId);
        fna.setStatus(FnaStatusEnum.UNCOMPLETED.getItemValue());

        Date date = new Date();
        fna.setCreateTime(date);
        fna.setUpdateTime(date);
        // 写入数据库
        boolean result = this.save(fna);
        if (!result) {
            throw new BusinessException(ResultCode.FAIL.getCode(), ResultCode.FAIL.getMessage());
        }
        // 生成fna编号
        String fnaNo = generateFnaNo(fnaAddRequest.getTenantCode(), fna.getId());
        // 更新fna
        baseMapper.updateFnaNoById(fnaNo, fna.getId());

        // 组装返回
        Map<String, Object> map = new HashMap<>();
        map.put("fnaBizId", fna.getFnaBizId());
        return map;
    }

    /**
     * 生成f流程编号
     * 流程编号格式：租户编号-流程类型-创建时间(YY-MM-DD)-id
     *
     * @param tenantCode
     * @param fnaId
     * @return
     */
    private String generateFnaNo(String tenantCode, Long fnaId) {
        String defaultTenantCode = "CSF";
        if (StringUtils.isBlank(tenantCode)) {
            tenantCode = defaultTenantCode;
        }
        // 如果 fnaId 不足 4位，则补足 4位，超过则不变
        String fnaIdstr = String.valueOf(fnaId);
        if (fnaId < 1000L) {
            fnaIdstr = String.format("%04d", fnaId);
        }
        return tenantCode + "-B-" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd")) + "-" + fnaIdstr;
    }

    /**
     * 获取查询条件
     *
     * @param fnaQueryRequest
     * @return
     */
    @Override
    public QueryWrapper<Fna> getQueryWrapper(FnaQueryRequest fnaQueryRequest) {
        QueryWrapper<Fna> queryWrapper = new QueryWrapper<>();
        if (fnaQueryRequest == null) {
            return queryWrapper;
        }
        String customerName = fnaQueryRequest.getCustomerName();
        String appointmentNo = fnaQueryRequest.getAppointmentNo();
        String policyBizId = fnaQueryRequest.getPolicyBizId();
        String policyNo = fnaQueryRequest.getPolicyNo();
        LocalDateTime startTime = fnaQueryRequest.getStartTime();
        LocalDateTime endTime = fnaQueryRequest.getEndTime();
        String fnaNo = fnaQueryRequest.getFnaNo();
        String status = fnaQueryRequest.getStatus();
        String fnaBizId = fnaQueryRequest.getFnaBizId();
        // 流程业务ID
        queryWrapper.eq(StringUtils.isNotBlank(fnaBizId), "fna_biz_id", fnaBizId);
        // 流程编号
        queryWrapper.like(StringUtils.isNotBlank(fnaNo), "fna_no", fnaNo);
        // 状态 'DRAFT'-草稿, 'UNCOMPLETED'-未完成, 'COMPLETED'-已完成，默认查询未完成和已完成
        if (StringUtils.isBlank(status)) {
            queryWrapper.in("status", "UNCOMPLETED", "COMPLETED");
        } else {
            queryWrapper.eq("status", status);
        }
        // 创建时间开始
        queryWrapper.ge(ObjectUtils.isNotEmpty(startTime), "create_time", startTime);
        // 创建时间结束
        queryWrapper.le(ObjectUtils.isNotEmpty(endTime), "create_time", endTime);
        // 客户姓名
        queryWrapper.like(StringUtils.isNotBlank(customerName), "customer_name", customerName);
        // 预约编号
        queryWrapper.like(StringUtils.isNotBlank(appointmentNo), "appointment_no", appointmentNo);
        // 新单编号
        queryWrapper.like(StringUtils.isNotBlank(policyBizId), "policy_biz_id", policyBizId);
        // 保单号
        queryWrapper.like(StringUtils.isNotBlank(policyNo), "policy_no", policyNo);

        String sortField = fnaQueryRequest.getSortField();
        String sortOrder = fnaQueryRequest.getSortOrder();
        queryWrapper.orderBy("createTime".equals(sortField), sortOrder.equals(CommonConstant.SORT_ORDER_ASC),
                "create_time");
        // 默认排序规则
        if (StringUtils.isBlank(sortField)) {
            queryWrapper.orderByDesc("id");
        }
        return queryWrapper;
    }

    /**
     * 获取fna封装
     *
     * @param fna
     * @return
     */
    @Override
    public FnaVO getFnaVO(Fna fna) {
        // 对象转封装类
        FnaVO fnaVO = FnaVO.objToVo(fna);

        // 1. 关联查询 FNA表单 信息
        String fnaFormBizId = fna.getFnaFormBizId();
        FnaForm fnaForm = null;
        if (StringUtils.isNotBlank(fnaFormBizId)) {
            fnaForm = fnaFormService.getByFnaFormBizId(fnaFormBizId);
            if (fnaForm != null) {
                fnaVO.setFnaFormStatus(fnaForm.getFnaFormStatus());
            }
        }
        return fnaVO;
    }

    /**
     * 分页获取fna封装
     *
     * @param fnaPage
     * @return
     */
    @Override
    public Page<FnaVO> getFnaVOPage(Page<Fna> fnaPage) {
        List<Fna> fnaList = fnaPage.getRecords();
        Page<FnaVO> fnaVOPage = new Page<>(fnaPage.getCurrent(), fnaPage.getSize(), fnaPage.getTotal());
        if (CollUtil.isEmpty(fnaList)) {
            return fnaVOPage;
        }
        // 对象列表 => 封装对象列表
        List<FnaVO> fnaVOList = fnaList.stream().map(FnaVO::objToVo).collect(Collectors.toList());

        // region 可选
        // 1. 关联查询用户信息
//        Set<Long> userIdSet = fnaList.stream().map(Fna::getUserId).collect(Collectors.toSet());
//        Map<Long, List<User>> userIdUserListMap = userService.listByIds(userIdSet).stream()
//                .collect(Collectors.groupingBy(User::getId));

        // 2. 已登录，获取用户点赞、收藏状态
        Map<Long, Boolean> fnaIdHasThumbMap = new HashMap<>();
        Map<Long, Boolean> fnaIdHasFavourMap = new HashMap<>();
//        User loginUser = userService.getLoginUserPermitNull(request);


        // 填充信息
//        fnaVOList.forEach(fnaVO -> {
//            Long userId = fnaVO.getUserId();
//            User user = null;
//            if (userIdUserListMap.containsKey(userId)) {
//                user = userIdUserListMap.get(userId).get(0);
//            }
//            fnaVO.setUser(userService.getUserVO(user));
//            fnaVO.setHasThumb(fnaIdHasThumbMap.getOrDefault(fnaVO.getId(), false));
//            fnaVO.setHasFavour(fnaIdHasFavourMap.getOrDefault(fnaVO.getId(), false));
//        });
        // endregion

        fnaVOPage.setRecords(fnaVOList);
        return fnaVOPage;
    }

    @Override
    public Fna getByBizId(String fnaBizId) {
        QueryWrapper<Fna> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("fna_biz_id", fnaBizId);
        return baseMapper.selectOne(queryWrapper);
    }

    @Override
    public boolean updateByBizId(Fna fna) {
        UpdateWrapper<Fna> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("fna_biz_id", fna.getFnaBizId());
        return baseMapper.update(fna, updateWrapper) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteFna(DeleteFnaRequest deleteRequest) {
        String fnaBizId = deleteRequest.getFnaBizId();
        // 判断是否存在
        Fna oldFna = this.getByBizId(fnaBizId);
        if (oldFna == null) {
            throw new BusinessException(ResultCode.NULL_ERROR.getCode(), ResultCode.NULL_ERROR.getMessage());
        }
        // 操作数据库
        boolean result = this.removeById(oldFna.getId());
        if (!result) {
            throw new BusinessException(ResultCode.FAIL.getCode(), ResultCode.FAIL.getMessage());
        }
        return result;
    }

    /**
     * 查询单个对象
     * @param fnaBizId
     * @return
     */
    @Override
    public Fna queryOne(String fnaBizId) {
        return this.getOne(new LambdaQueryWrapper<Fna>().eq(Fna::getFnaBizId,fnaBizId));
    }

    @Override
    public Boolean updateFna(FnaUpdateRequest fnaUpdateRequest, String appointmentNo) {
        // 判断是否存在
        String fnaBizId = fnaUpdateRequest.getFnaBizId();
        Fna fna = this.getByBizId(fnaBizId);
        if (fna == null) {
            throw new BusinessException(ResultCode.NULL_ERROR.getCode(), ResultCode.NULL_ERROR.getMessage());
        }

        BeanUtils.copyProperties(fnaUpdateRequest, fna,"fnaBizId");

        if (StringUtils.isNotBlank(fnaUpdateRequest.getCustomerBizId())) {
            Customer customer = customerService.getByCustomerBizId(fnaUpdateRequest.getCustomerBizId());
            fna.setCustomerName(customer.getFirstNamePinyin());
        }
        // 设置 状态
        String customerBizId = fnaUpdateRequest.getCustomerBizId();
        String fnaFormBizId = fnaUpdateRequest.getFnaFormBizId();

        if (StringUtils.isNotBlank(customerBizId) || StringUtils.isNotBlank(fnaFormBizId) || StringUtils.isBlank(appointmentNo) ) {
            fna.setStatus(FnaStatusEnum.UNCOMPLETED.getItemValue());
        }

        if (StringUtils.isNotBlank(customerBizId) && StringUtils.isNotBlank(fnaFormBizId) && StringUtils.isBlank(appointmentNo)) {
            fna.setStatus(FnaStatusEnum.COMPLETED.getItemValue());
        }

        // 操作数据库
        fna.setAppointmentNo(appointmentNo);
        return this.updateById(fna);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> copyFna(FnaCopyRequest fnaCopyRequest) {
        String fnaBizId = fnaCopyRequest.getFnaBizId();
        Fna oldFna = this.getByBizId(fnaBizId);
        if (oldFna == null) {
            throw new BusinessException(ResultCode.NULL_ERROR.getCode(), ResultCode.NULL_ERROR.getMessage());
        }
        // 获取Security上下文当前用户的登录信息
        AuthUserDto authUserDto = SecurityUtil.getCurrentLoginUser();
        String userBizId = authUserDto.getUserBizId();

        // 新建流程
        Fna newFna = new Fna();
        // 租户编码
        newFna.setTenantCode(oldFna.getTenantCode());
        // 复制 客户信息
        newFna.setCustomerName(oldFna.getCustomerName());
        newFna.setCustomerBizId(oldFna.getCustomerBizId());
        newFna.setUserBizId(userBizId);
        newFna.setFnaBizId(RandomStringGenerator.generateBizId16(CommonEnum.UID_TYPE_FNA.getCode()));
        newFna.setCreatorId(userBizId);
        newFna.setUpdaterId(userBizId);
        newFna.setStatus(FnaStatusEnum.UNCOMPLETED.getItemValue());

        Date date = new Date();
        newFna.setCreateTime(date);
        newFna.setUpdateTime(date);
        // 保存 fna
        boolean result = this.save(newFna);
        if (!result) {
            throw new BusinessException(ResultCode.FAIL.getCode(), ResultCode.FAIL.getMessage());
        }

        // 生成fna编号
        String fnaNo = generateFnaNo(oldFna.getTenantCode(), newFna.getId());
        // 复制 FnaForm
        String newFnaFormBizId = copyFnaForm(oldFna.getFnaFormBizId(), userBizId);
        // 更新 fna
        Fna updateFna = new Fna();
        updateFna.setId(newFna.getId());
        updateFna.setFnaNo(fnaNo);
        updateFna.setFnaFormBizId(newFnaFormBizId);
        this.updateById(updateFna);

        return Collections.singletonMap("fnaBizId", newFna.getFnaBizId());
    }

    @Override
    public int updateCustomerNameByCustomerBizId(String firstNamePinyin, String customerBizId) {
        return baseMapper.updateCustomerNameByCustomerBizId(firstNamePinyin, customerBizId);
    }

    private String copyFnaForm(String oldFnaFormBizId, String userBizId) {
        FnaForm fnaForm = fnaFormService.getByFnaFormBizId(oldFnaFormBizId);
        if (fnaForm == null) {
            return null;
        }
        // 处理个人资料
        PersonalData personalData = fnaFormService.getPersonalDataObj(fnaForm.getPersonalData());
        personalData.setAccountName(null);
        personalData.setRegistrationNumber(null);
        personalData.setNumber(null);

        FnaForm newFnaForm = new FnaForm();
        BeanUtils.copyProperties(fnaForm, newFnaForm, "id", "fnaFormBizId", "userBizId", "personalData");
        newFnaForm.setFnaFormBizId(RandomStringGenerator.generateBizId16(CommonEnum.UID_TYPE_FNA_FORM.getCode()));
        newFnaForm.setFnaFormStatus("0");
        newFnaForm.setUserBizId(userBizId);
        newFnaForm.setCreatorId(userBizId);
        newFnaForm.setUpdaterId(userBizId);
        newFnaForm.setPersonalData(GSON.toJson(personalData));

        Date date = new Date();
        newFnaForm.setCreateTime(date);
        newFnaForm.setUpdateTime(date);
        fnaFormService.save(newFnaForm);

        return newFnaForm.getFnaFormBizId();
    }

}
