package com.crm.manager.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.crm.manager.dao.mapper.UserGoogleEmailMapper;
import com.crm.manager.dao.repository.UserGoogleEmailRepository;
import com.crm.manager.property.GooleUserAdminApiProperty;
import com.crm.manager.service.SysConfigService;
import com.crm.manager.service.UserGoogleEmailService;
import com.crm.rely.backend.core.constant.ConfigConstants;
import com.crm.rely.backend.core.constant.Constants;
import com.crm.rely.backend.core.dto.base.PageDto;
import com.crm.rely.backend.core.dto.base.ResultWithPagerDto;
import com.crm.rely.backend.core.dto.user.google.UserGoogleEmailListDto;
import com.crm.rely.backend.core.entity.base.SingleLongEntity;
import com.crm.rely.backend.core.entity.user.google.UserGoogleEmailAddEntity;
import com.crm.rely.backend.core.entity.user.google.UserGoogleEmailDeleteEntitys;
import com.crm.rely.backend.core.entity.user.google.UserGoogleEmailSearchEntity;
import com.crm.rely.backend.core.entity.user.google.UserGoogleEmailUpdateEntity;
import com.crm.rely.backend.core.pojo.table.SysConfigTable;
import com.crm.rely.backend.core.pojo.table.UserGoogleEmailTable;
import com.crm.rely.backend.exception.ServiceException;
import com.crm.rely.backend.util.GetRandom;
import com.crm.rely.backend.util.GoogleAdminAPIHttp;
import com.google.common.base.Strings;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class UserGoogleEmailServiceImpl implements UserGoogleEmailService {

    @Autowired
    private UserGoogleEmailRepository repository;
    @Autowired
    private UserGoogleEmailMapper mapper;
    @Autowired
    private SysConfigService sysConfigService;

    public SysConfigTable getConfig() throws Exception {
        SysConfigTable gogleConfigTable = sysConfigService.getByCode(ConfigConstants.GOOGLE_USER_ADMIN_API_PROPERTY);
        if (gogleConfigTable == null) {
            throw ServiceException.exception(Constants.SYSTEM_ERROR);
        }
        return gogleConfigTable;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String add(UserGoogleEmailAddEntity entity) throws Exception {
        UserGoogleEmailTable table = new UserGoogleEmailTable();
        BeanUtils.copyProperties(entity, table);

        SysConfigTable gogleConfigTable = getConfig();

        //谷歌账户添加
        GooleUserAdminApiProperty property = JSON.parseObject(gogleConfigTable.getValue(), GooleUserAdminApiProperty.class);
        String accessToken = GoogleAdminAPIHttp.getAccessToken(property.getAdminEmail(), property.getClientEmail(), property.getPrivateKey());

        if (GoogleAdminAPIHttp.getUser(accessToken, table.getGoogleEmail()) != null) {
            throw ServiceException.exception("GoogleEmail is already in use");
        }

        String googlePassword = GetRandom.getRandomPasswordString();
        Integer resposeCode = GoogleAdminAPIHttp.createUser(accessToken, table.getGoogleEmail(), table.getFirstName(), table.getLastName(), googlePassword,
                Strings.isNullOrEmpty(table.getExtraPhone()) ? null : table.getCallingCode() + " " + table.getExtraPhone(), table.getExtraEmail());
        if (Constants.SUCCESS_CODE != resposeCode) {
            throw ServiceException.exception("create GoogleEmail is error");
        }

        String userStr = GoogleAdminAPIHttp.getUser(accessToken, table.getGoogleEmail());
        JSONObject user = JSON.parseObject(userStr);
        table.setGoogleId(user.getString("id"));
        table.setGooglePassword(googlePassword);
        table.setDelFlag(1);
        repository.save(table);

        return table.getGooglePassword();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(UserGoogleEmailDeleteEntitys entity) throws Exception {
        List<UserGoogleEmailTable> tables = repository.findAllByIdIn(entity.getIds());
        if (tables == null) {
            throw ServiceException.exception(Constants.INFO_NOT_FOUND);
        }
        SysConfigTable gogleConfigTable = getConfig();

        //谷歌账户添加
        GooleUserAdminApiProperty property = JSON.parseObject(gogleConfigTable.getValue(), GooleUserAdminApiProperty.class);
        String accessToken = GoogleAdminAPIHttp.getAccessToken(property.getAdminEmail(), property.getClientEmail(), property.getPrivateKey());
        for (UserGoogleEmailTable table : tables) {
            if (GoogleAdminAPIHttp.getUser(accessToken, table.getGoogleEmail()) != null) {
                Integer resposeCode = GoogleAdminAPIHttp.deleteUser(accessToken, table.getGoogleEmail());
                if (204 != resposeCode) {
                    throw ServiceException.exception("delete GoogleEmail is error");
                }
            }
            table.setDelFlag(0);
        }

        repository.save(tables);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(UserGoogleEmailUpdateEntity entity) throws Exception {
        UserGoogleEmailTable table = repository.findFirstById(entity.getId());
        if (table == null) {
            throw ServiceException.exception(Constants.INFO_NOT_FOUND);
        }
        BeanUtils.copyProperties(entity, table);
        SysConfigTable gogleConfigTable = getConfig();

        //谷歌账户添加
        GooleUserAdminApiProperty property = JSON.parseObject(gogleConfigTable.getValue(), GooleUserAdminApiProperty.class);
        String accessToken = GoogleAdminAPIHttp.getAccessToken(property.getAdminEmail(), property.getClientEmail(), property.getPrivateKey());

        if (GoogleAdminAPIHttp.getUser(accessToken, table.getGoogleEmail()) == null) {
            throw ServiceException.exception("GoogleEmail is not used");
        }

        Integer resposeCode = GoogleAdminAPIHttp.updateUser(accessToken, table.getGoogleEmail(), table.getFirstName(), table.getLastName(),
                Strings.isNullOrEmpty(table.getExtraPhone()) ? null : table.getCallingCode() + " " + table.getExtraPhone(), table.getExtraEmail());
        if (Constants.SUCCESS_CODE != resposeCode) {
            throw ServiceException.exception("update GoogleEmail is error");
        }

        repository.save(table);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateRemark(UserGoogleEmailUpdateEntity entity) throws Exception {
        UserGoogleEmailTable table = repository.findFirstById(entity.getId());
        if (table == null) {
            throw ServiceException.exception(Constants.INFO_NOT_FOUND);
        }
        table.setRemark(entity.getRemark());

        repository.save(table);
    }

    @Override
    public ResultWithPagerDto<UserGoogleEmailListDto> searchPageList(UserGoogleEmailSearchEntity entity) throws Exception {
        Integer count = mapper.countList(entity);
        if (count == null || count <= 0) {
            count = this.refresh();
        }
        PageDto pageDto = PageDto.format(entity, count);

        List<UserGoogleEmailTable> tables = mapper.pageList(entity);
        List<UserGoogleEmailListDto> dtos = new ArrayList<>(tables.size());
        for (UserGoogleEmailTable UserGoogleEmailTable : tables) {
            UserGoogleEmailListDto dto = transformSearchListDto(UserGoogleEmailTable);
            dtos.add(dto);
        }

        return ResultWithPagerDto.success(pageDto, dtos);
    }

    @Override
    public UserGoogleEmailListDto searchSingle(SingleLongEntity entity) throws ServiceException {
        UserGoogleEmailTable table = repository.getFirstById(entity.getId());
        if (table == null) {
            throw ServiceException.exception(Constants.INFO_NOT_FOUND);
        }

        return transformSearchListDto(table);
    }

    @Override
    public Integer refresh() throws Exception {
        SysConfigTable gogleConfigTable = getConfig();

        //谷歌账户添加
        GooleUserAdminApiProperty property = JSON.parseObject(gogleConfigTable.getValue(), GooleUserAdminApiProperty.class);
        String accessToken = GoogleAdminAPIHttp.getAccessToken(property.getAdminEmail(), property.getClientEmail(), property.getPrivateKey());

        List<UserGoogleEmailTable> emailTables = repository.findByDelFlag(1);
        Map<String, UserGoogleEmailTable> emailMap = emailTables.stream().collect(Collectors.toMap(UserGoogleEmailTable::getGoogleId, UserGoogleEmailTable -> UserGoogleEmailTable));

        List<UserGoogleEmailTable> emailList = new ArrayList<>();
        List<Map<String, Object>> maps = GoogleAdminAPIHttp.listUsers(accessToken, "");
        for (Map<String, Object> map : maps) {

            UserGoogleEmailTable table = null;
            String googleEmail = map.get("primaryEmail").toString();
            String googleId = map.get("id").toString();
            if(emailMap.containsKey(googleId)){
                table = emailMap.get(googleId);
            }else{
                table = new UserGoogleEmailTable();

            }
            table.setGoogleEmail(googleEmail);
            table.setGoogleId(googleId);
            table.setCreationTime(map.get("creationTime").toString().toString().substring(0, 19).replace("T", " "));
            table.setLastLoginTime(map.get("lastLoginTime").toString().substring(0, 19).replace("T", " "));
            table.setDelFlag(1);

            if(null != map.get("name")){
                Map name = (Map) map.get("name");
                table.setFirstName(name.get("givenName") == null ? null : name.get("givenName").toString());
                table.setLastName(name.get("familyName") == null ? null : name.get("familyName").toString());
            }
            if(null != map.get("emails")){
                List<Map> emails = JSON.parseArray(map.get("emails").toString(),Map.class);
                for (Map email : emails) {
                    String type = email.get("type") == null ? "" : email.get("type").toString();
                    if("work".equals(type)){
                        table.setExtraEmail(email.get("address").toString());
                        break;
                    }
                }
            }
            if(null != map.get("phones")) {
                List<Map> phones = JSON.parseArray(map.get("phones").toString(), Map.class);
                for (Map phone : phones) {
                    String type = phone.get("type") == null ? "" : phone.get("type").toString();
                    if ("work".equals(type)) {
                        String phonenumber = phone.get("value").toString();
                        String[] phonestring = phonenumber.split(" ");
                        if(phonestring.length < 2){
                            table.setExtraPhone(phonenumber);
                        }else{
                            table.setCallingCode(phonestring[0]);
                            table.setExtraPhone(phonestring[1]);
                        }
                        break;
                    }
                }
            }

            emailList.add(table);

            emailMap.remove(googleId);
        }
        if (emailMap.size() > 0) {
            for (String key : emailMap.keySet()) {
                UserGoogleEmailTable table = emailMap.get(key);
                table.setDelFlag(0);
                emailList.add(table);
            }
        }

        repository.save(emailList);

        return maps.size();
    }

    private UserGoogleEmailListDto transformSearchListDto(UserGoogleEmailTable UserGoogleEmailTable) {
        UserGoogleEmailListDto UserGoogleEmailListDto = new UserGoogleEmailListDto();
        BeanUtils.copyProperties(UserGoogleEmailTable, UserGoogleEmailListDto);
        return UserGoogleEmailListDto;
    }


}
