package com.winsun.migration.service.impl;


import com.alibaba.fastjson.JSON;
import com.winsun.bean.HhrUser;
import com.winsun.bean.SysUser;
import com.winsun.bean.activity.HhrActivity;
import com.winsun.bean.activity.HhrActivityRecord;
import com.winsun.item.core.shiro.ShiroKit;
import com.winsun.mapper.HhrUserMapper;
import com.winsun.mapper.SysUserMapper;
import com.winsun.mapper.activity.ActivityMapper;
import com.winsun.mapper.activity.ActivityRecordMapper;
import com.winsun.migration.mapper.db1.NewDatabases;
import com.winsun.migration.mapper.db2.OldDatabases;
import com.winsun.migration.service.IMigrationService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.security.NoSuchAlgorithmException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Slf4j
@Service("migrationService")
public class MigrationServiceImpl implements IMigrationService {

    @Autowired
    private NewDatabases newDatabases;

    @Autowired
    private OldDatabases oldDatabases;

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private HhrUserMapper hhrUserMapper;

    @Autowired
    private ActivityMapper activityMapper;

    @Autowired
    private ActivityRecordMapper activityRecordMapper;
    /**
     * 迁移用户数据
     */
    public void migrationUser() throws NoSuchAlgorithmException {
        //
        List<Map<String, Object>> oldUserList = oldDatabases.getUser();
        log.info(JSON.toJSONString(oldUserList.get(0)));

        SysUser user = null;
        HhrUser hhrUser = null;
        List<String> hhrError = new ArrayList<>();
        List<String> sysError = new ArrayList<>();
        for(Map<String, Object> stringObjectMap : oldUserList) {
            try{
                user = new SysUser();
                user.setId(stringObjectMap.get("id").toString());
                user.setAccount(stringObjectMap.get("account") != null ? stringObjectMap.get("account").toString() : "");
                user.setName(stringObjectMap.get("name") != null ? stringObjectMap.get("name").toString() : "");
                user.setSalt(ShiroKit.getRandomSalt(6));
                user.setPassword(ShiroKit.md5("123456",user.getSalt()));
                user.setSex(stringObjectMap.get("sex") != null ? stringObjectMap.get("sex").toString() : "1");
                user.setPhone(stringObjectMap.get("account") != null ? stringObjectMap.get("account").toString() : "");
                user.setRoleid(stringObjectMap.get("role_id") != null ? stringObjectMap.get("role_id").toString() : "");
                user.setDeptid(stringObjectMap.get("dept_id") != null ? stringObjectMap.get("dept_id").toString() : "");
                user.setStatus(stringObjectMap.get("state") != null ? stringObjectMap.get("state").toString() : "");
                user.setCreatetime(new Date());
                user.setUpdateTime(new Date());
                try{
                    int insert = newDatabases.insert(user);
                    if (insert < 1) {
                        sysError.add(stringObjectMap.get("id").toString());
                    }
                }catch(Exception e) {
                    if(e instanceof DuplicateKeyException){
                        System.out.println("更新记录");
                        sysUserMapper.updateById(user);
                    }else{
                        throw e;
                    }
                }
            }catch(Exception e) {
                    sysError.add(stringObjectMap.get("id").toString());
                    log.info(e.getMessage());
                    this.insertLog("sys_user", user, "error", e.getMessage());
            }
            try {
                hhrUser = new HhrUser();
                hhrUser.setId(stringObjectMap.get("id").toString());
                hhrUser.setIdCard(stringObjectMap.get("id_card") != null ? stringObjectMap.get("id_card").toString() : "");
                hhrUser.setYsm("1");
                hhrUser.setWxHeadImgUrl(stringObjectMap.get("wx_head_img_url") != null ? stringObjectMap.get("wx_head_img_url").toString() : "");
                hhrUser.setWxNickName(stringObjectMap.get("wx_nick_name") != null ? stringObjectMap.get("wx_nick_name").toString() : "");
                hhrUser.setOpenId(stringObjectMap.get("open_id") != null ? stringObjectMap.get("open_id").toString() : "");
                hhrUser.setUploadState(0);
                hhrUser.setGrade(stringObjectMap.get("grade") != null ? stringObjectMap.get("grade").toString() : "");
                hhrUser.setPosition(stringObjectMap.get("position") != null ? stringObjectMap.get("position").toString() : "");
                hhrUser.setParentId(stringObjectMap.get("parent_user_id") != null ? stringObjectMap.get("parent_user_id").toString() : "");
                hhrUser.setParentIds(stringObjectMap.get("parent_ids") != null ? stringObjectMap.get("parent_ids").toString() : "");
                hhrUser.setIsActive(Integer.parseInt(stringObjectMap.get("is_active") != null ? stringObjectMap.get("is_active").toString() : ""));
                try{
                    int i = newDatabases.insertHhr(hhrUser);
                    if (i < 1) {
                        hhrError.add(stringObjectMap.get("id").toString());
                    }
                }catch(Exception e) {
                    if(e instanceof DuplicateKeyException){
                        hhrUserMapper.updateById(hhrUser);
                    }else{
                        throw e;
                    }
                }
            }catch(Exception e) {
                hhrError.add(stringObjectMap.get("id").toString());
                log.error(e.getMessage());
                this.insertLog("hhr_user", hhrUser, "error", e.getMessage());
            }
        }

        insertResult(oldUserList.size(), "sys_user", sysError);
        insertResult(oldUserList.size(), "hhr_user", hhrError);
    }

    /**
     * 迁移日志
     * @param tableName 迁移表名
     * @param object 迁移对象
     * @param status 迁移状态
     * @param message 迁移信息
     */
    public void insertLog(String tableName, Object object, String status, String message) {
        try {
            newDatabases.insertLog(tableName, JSON.toJSONString(object), status, message);
        }catch(Exception e) {
            log.error("插入日志失败:" + e.getMessage());
        }
    }

    /**
     * 迁移活动
     */
    public void migrationActivity() {
        List<Map<String, Object>> activityList = oldDatabases.getActivity();
        HhrActivity hhrActivity = null;
        log.info(JSON.toJSONString(activityList));
        List<String> list = new ArrayList<>();
        for(Map<String, Object> activity : activityList) {
            try{
                hhrActivity = new HhrActivity();
                hhrActivity.setId(getString(activity.get("id")));
                hhrActivity.setTitle(getString(activity.get("title")));
                hhrActivity.setDesc(getString(activity.get("activityDesc")));
                hhrActivity.setIntegral(Integer.valueOf(getString(activity.get("integral"))));
                hhrActivity.setImageUrl(getString(activity.get("imageUrl")));
                hhrActivity.setActivityType(getString(activity.get("activity_type")));
                hhrActivity.setSubclass(getString(activity.get("subclass")));
                hhrActivity.setRange(getString(activity.get("act_range")));
                hhrActivity.setStatus(getString(activity.get("status")));
                hhrActivity.setSort(activity.get("sort") != null ? Integer.valueOf(getString(activity.get("sort"))) : null);
                hhrActivity.setCreateTime(getDate(activity.get("createDate")));
                hhrActivity.setCreator(getString(activity.get("name")));
                hhrActivity.setDelFlag(activity.get("del_flag") != null ? Integer.valueOf(getString(activity.get("del_flag"))) : 0);
                try{
                    Integer insert = newDatabases.insertActivity(hhrActivity);
                    if (insert < 0) {
                        list.add(activity.get("id").toString());
                    }
                }catch(Exception e) {
                    if(e instanceof DuplicateKeyException){
                        activityMapper.updateById(hhrActivity);
                    }else{
                        throw e;
                    }
                }
            }catch(Exception e) {
                list.add(activity.get("id").toString());
                log.error(e.getMessage());
                this.insertLog("hhr_activity", hhrActivity, "error", e.getMessage());
            }
        }
        insertResult(activityList.size(), "hhr_activity", list);
    }

    /**
     * 迁移活动参与记录
     */
    public void migrationActivityRecord() {

        // 查询出所有记录
        List<Map<String, Object>> activityRecord = oldDatabases.getActivityRecord();
        HhrActivityRecord hhrActivityRecord = null;
        Map<String, Object> count = null;

        List<String> list = new ArrayList<>();

        for(Map<String, Object> map: activityRecord) {
            try{
                hhrActivityRecord = new HhrActivityRecord();
                // 判断是否有重复记录， 根据id  账号   活动id
                Integer id = Integer.valueOf(getString(map.get("id")));
                Integer activityId = Integer.valueOf(getString(map.get("activityId")));
                String account = getString(map.get("account"));
                count = oldDatabases.getActivityRecordCount(id, activityId, account);

                if (Integer.valueOf(getString(count.get("count"))) > 0) {
                    hhrActivityRecord.setIsRepeal(1);
                }else{
                    hhrActivityRecord.setIsRepeal(0);
                }

                hhrActivityRecord.setId(getString(map.get("id")));
                hhrActivityRecord.setActivityId(getString(map.get("activityId")));
                hhrActivityRecord.setCreateId(getString(map.get("create_id")));
                hhrActivityRecord.setCreator(getString(map.get("creator")));
                hhrActivityRecord.setCreateTime(getDate(map.get("createDate")));
                hhrActivityRecord.setImageUrl(getString(map.get("imageUrl_old")));
                hhrActivityRecord.setMessage(getString(map.get("messageInfo")));
                hhrActivityRecord.setRemark(getString(map.get("opinions")));
                hhrActivityRecord.setStatus(getString(map.get("state")));
                hhrActivityRecord.setUpdateTime(getDate(map.get("update_date")));
                hhrActivityRecord.setRecordIntegral(new BigDecimal(getString(map.get("Integral"))).intValue());
                try{
                    Integer insert = newDatabases.insertActivityRecord(hhrActivityRecord);
                    if (insert < 1) {
                        list.add(hhrActivityRecord.getId());
                    }
                }catch(Exception e) {
                    if (e instanceof DuplicateKeyException) {
                        activityRecordMapper.updateById(hhrActivityRecord);
                    }
                    else{
                        throw e;
                    }
                }
            }catch(Exception e) {
                list.add(map.get("id").toString());
                log.error(e.getMessage());
                this.insertLog("hhr_activity_record", hhrActivityRecord, "error", e.getMessage());
            }
        }
        insertResult(activityRecord.size(), "hhr_activity_record", list);
    }

    public Date getDate(Object object)  {
        if (object == null) {
            return null;
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = new Date();
        try {
            date = sdf.parse((String)getString(object));
        } catch (ParseException e) {
            return null;
        }
        return date;
    }

    public String getString(Object object) {
        return object != null ? object.toString() : "";
    }

    /**
     * 插入迁移结果
     * @param total  迁移总数
     * @param tableName  表明
     * @param ids   插入错误id
     */
    public void insertResult(Integer total, String tableName, List<String> ids) {
        this.insertLog(tableName, ids , "result",
                "total:" + total + ", " + tableName +" fail num: " + ids.size());
        log.info("----------------------------------------------------");
        log.info(tableName + "插入失败个数：" + ids.size());
        log.info(JSON.toJSONString(ids));
        log.info("----------------------------------------------------");
    }
}
