package com.reyun.service.impl;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import com.reyun.dic.AppTypeEnum;
import com.reyun.dic.ReportEnumType;
import com.reyun.dic.RoleEnumType;
import com.reyun.model.*;
import com.reyun.repository.*;
import com.reyun.service.AppService;
import com.reyun.service.AuthService;
import com.reyun.service.ConfigParamService;
import com.reyun.service.IAppTagService;
import com.reyun.service.IDicService;
import com.reyun.util.CipherUtil;
import com.reyun.util.Constant;
import com.reyun.util.DateUtil;
import com.reyun.util.HttpClientUtil;
import com.reyun.util.ShortUrlGenerator;
import com.reyun.util.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class AppServiceImpl implements AppService {

	private static final Logger logger = LoggerFactory.getLogger(AppServiceImpl.class);

	@Autowired
	AppRepository appRepository;
	
	@Autowired
	CategoryRepository categoryRepository;
	
	@Autowired
	AccountRepository accountRepository;

	@Autowired
	AuthRepository authRepository;

	@Autowired
	AuthService authService;

    @Autowired
    ConfigParamService configParamService;

	@Autowired
	private IDicService iDicService;

	@Autowired
	private IAppTagService iAppTagService;


    @Override
    public List<App> listAuthAppByAccount(Account account, Long subAccountId) {

        Account subAccount = accountRepository.findOne(subAccountId);

        if (subAccount.getIsChannelPerson()) {

            //查询母账号下面所有授权的数据
            return appRepository.findAuthAppByRootParent(subAccountId, account.getRootParent());

        } else {

            return appRepository.findAuthApp(subAccountId);
        }
    }

    @Override
	public App delete(final Long id,final Long account) {
		App app = appRepository.findOne(id);
		app.setModifyAccount(account+"");
		app.setModifyTime(new Date());
		app.setDelFlag(true);
		appRepository.save(app);

		return app;
	}
	
	@Override
	public List<App> listAppByAccount(Long accountId) {

        List<App> appList = new ArrayList<>();
        Account oneAccount = accountRepository.findOne(accountId);


        if (oneAccount.getIsSuperUser() || oneAccount.getRoleCategory().equals(RoleEnumType.MANAGER.getKey())) {
			//母账号,或者管理员创建的APP
			accountId = oneAccount.getIsSuperUser() ? accountId : oneAccount.getParent();
			appList = appRepository.listAppByRootAccount(accountId);

		} else {

            //自定义角色,自定义权限
            List<Long> appIdList = authService.findAuthAppListByAccount(oneAccount.getId());

            if (!CollectionUtils.isEmpty(appIdList)) {
                appList = appRepository.findByIds(appIdList);
            }
        }
        for(App app:appList){
        	String appGenreName=appRepository.findAppGenreNameByAppID(app.getId());
        	app.setAppGenreName(appGenreName);
		}
        return appList;
	}

    @Override
	public App findById(Long id) {

    	App one = appRepository.findOne(id);
		one.setAppTagList(iAppTagService.findByApp(id));
		return one;
	}

	@Override
	public App create(App resource,Long accountId)
    {
		Account account = accountRepository.findOne(accountId);
		
		resource.setAccount(account.getId());
 		resource.setCreateAccount(account.getId()+"");
		resource.setCreateTime(new Date());
		resource.setModifyAccount(account.getId()+"");
		resource.setModifyTime(new Date());
		resource.setDelFlag(false);
		
		String dateStr = DateUtil.getCurrentDateStr(DateUtil.C_TIME_PATTON_DEFAULT);
		String key = ShortUrlGenerator.md5(account.getEmail() + resource.getName() + resource.getPlatform() + dateStr);
		resource.setAppkey(ShortUrlGenerator.md5(key));
		resource.setToken(CipherUtil.generatePassword("reged_"+ShortUrlGenerator.md5(key)));
        resource.setRegedbutton(false);
//        resource.setSyncDdb(false);
		
		App app =  appRepository.save(resource);

        /*//同步DDB,同步APP的测试模式状态
        this.syncAppDebugStatus(app);*/

		if (app.getAppTagList() != null && app.getAppTagList().size() > 0) {
			List<String> tagIdsList = app.getAppTagList().stream().map(AppTag::getTagId).collect(Collectors.toList());
			final List<SyDicItem> subNodeList = iDicService.find(tagIdsList);

			List<String> parentTagIdsList = subNodeList.stream().map(SyDicItem::getItemPid).collect(Collectors.toList());
			final List<SyDicItem> parentNodeList = iDicService.find(parentTagIdsList);

			Map<String, SyDicItem> dicMap = Maps.uniqueIndex(subNodeList, SyDicItem::getItemCode);
			Map<String, SyDicItem> dicParentMap = Maps.uniqueIndex(parentNodeList, SyDicItem::getItemCode);

			app.getAppTagList().forEach(appTag -> {
				SyDicItem syDicItem = dicMap.get(appTag.getTagId());
				if (syDicItem != null) {
					appTag.setTagName(syDicItem.getItemValue());
					appTag.setParentTagId(syDicItem.getItemPid());

					if (dicParentMap.containsKey(syDicItem.getItemPid())) {
						appTag.setParentTagName(dicParentMap.get(syDicItem.getItemPid()).getItemValue());
					}
				}
			});
			this.iAppTagService.saveOrUpdate(app.getId(), app.getAppTagList());
		}

		if (AppTypeEnum.APP.getCode().equals(app.getTagType()) || AppTypeEnum.GAME.getCode().equals(app.getTagType())) {
			boolean flag = doInvokeOfficeAudit(app.getId());
			logger.info("调试完成, 分配任务至运营人员. app:{}, httpstatus: {}", app.getId(), flag);
		}

        return app;
	}


    @Override
	public App update(App resource,Long account) {
		App app = appRepository.findOne(resource.getId());
		
		app.setModifyAccount(account+"");
		app.setModifyTime(new Date());
		app.setName(resource.getName());
		app.setBundleid(resource.getBundleid());
		app.setUrl(resource.getUrl());
		app.setAppTagList(resource.getAppTagList());
		app.setTagType(resource.getTagType());

		final List<AppTag> appTagList = resource.getAppTagList();
		if (appTagList != null && appTagList.size() > 0) {
			List<String> tagIdsList = appTagList.stream().map(AppTag::getTagId).collect(Collectors.toList());
			Map<String,SyDicItem> dicMap = Maps.uniqueIndex(iDicService.find(tagIdsList), SyDicItem::getItemCode);

			appTagList.forEach(appTag -> {
				SyDicItem syDicItem = dicMap.get(appTag.getTagId());
				if (syDicItem != null) {
					appTag.setTagName(syDicItem.getItemValue());
					appTag.setParentTagId(syDicItem.getItemPid());
				}
			});
			this.iAppTagService.saveOrUpdate(resource.getId(), appTagList);
		}

		return appRepository.save(app);
	}



	@Override
	public App enable(Long id,Long account) {
		App app = appRepository.findOne(id);
		app.setModifyAccount(account+"");
		app.setModifyTime(new Date());
		app.setRegedbutton(true);
		return appRepository.save(app);
		
	}

	@Override
	public App forbidden(Long id,Long account) {
		App app = appRepository.findOne(id);
		app.setModifyAccount(account+"");
		app.setModifyTime(new Date());
		app.setRegedbutton(false);
		return appRepository.save(app);
		
	}

	@Override
	public Boolean validName(String name) {
		
		return null;
	}

	@Override
	public Boolean validAppleId(Long account,String appleId) {
		boolean flag = true;
		App app = appRepository.findByBundleidInNotDel(account,appleId);
		if(app == null){
			flag = false;
		}
		return flag;
	}
	
	@Override
	public Boolean validName(Long account,String name) {
		boolean flag = true;
		App app = appRepository.findByNameNotDel(account, name);
		if(app == null){
			flag = false;
		}
		return flag;
	}

	@Override
	public List<Category> listCategory() {
		
		return categoryRepository.findAll();
	}

	private boolean doInvokeOfficeAudit(Long app){
		String url = Constant.adminUrl + "/api/ioapp/tag/task/distribute?app=" + app;
		String result = HttpClientUtil.doHttpGetRequest(url, "");

		Map resObj;
		try {
			resObj = new ObjectMapper().readValue(result, Map.class);
		} catch (IOException e) {
			logger.error("doInvokeOfficeAudit occur failed. app:{}", app);
			return false;
		}
		return "200".equals(resObj.get("code"));
	}

}
