package cn.com.qmth.stmms.biz.school.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import cn.com.qmth.stmms.biz.basic.service.PrivilegeService;
import cn.com.qmth.stmms.biz.common.BaseQueryService;
import cn.com.qmth.stmms.biz.config.model.SystemAuth;
import cn.com.qmth.stmms.biz.config.service.SystemAuthService;
import cn.com.qmth.stmms.biz.school.dao.SchoolDao;
import cn.com.qmth.stmms.biz.school.model.School;
import cn.com.qmth.stmms.biz.school.query.SchoolSearchQuery;
import cn.com.qmth.stmms.biz.school.service.SchoolService;
import cn.com.qmth.stmms.biz.utils.SolarHttpUtil;
import cn.com.qmth.stmms.common.utils.AesUtils;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

@Service("schoolService")
public class SchoolServiceImpl extends BaseQueryService<School> implements SchoolService {

    @Autowired
    public SchoolDao schoolDao;

    @Autowired
    private SystemAuthService authService;

    @Autowired
    private PrivilegeService privilegeService;

    @Value("${qmth.solar.host}")
    private String host;

    @Value("${qmth.solar.org.uri}")
    private String uri;

    @Override
    public School findById(Integer id) {
        return schoolDao.findOne(id);
    }

    @Override
    public School findByAccessKey(String accessKey) {
        return schoolDao.findFirstByAccessKey(accessKey);
    }

    public SchoolSearchQuery findByQuery(final SchoolSearchQuery query) {
        checkQuery(query);
        Page<School> result = schoolDao.findAll(new Specification<School>() {

            @Override
            public Predicate toPredicate(Root<School> root, CriteriaQuery<?> cQuery, CriteriaBuilder cb) {
                List<Predicate> predicates = new LinkedList<Predicate>();
                if (StringUtils.isNotBlank(query.getName())) {
                    predicates.add(cb.like(root.get("name").as(String.class), "%" + query.getName() + "%"));
                }
                if (StringUtils.isNotBlank(query.getProvince())) {
                    predicates.add(cb.equal(root.get("province"), query.getProvince()));
                }
                if (StringUtils.isNotBlank(query.getCity())) {
                    predicates.add(cb.equal(root.get("city"), query.getCity()));
                }
                return predicates.isEmpty() ? cb.conjunction() : cb.and(predicates.toArray(new Predicate[predicates
                        .size()]));
            }

        }, query);
        fillResult(result, query);
        return query;
    }

    @Transactional
    public School save(School school) {
        boolean isCreate = false;
        if (school.getId() != null && school.getId() > 0) {
            school.setUpdateTime(new Date());
        } else {
            isCreate = true;
            school.setCreateTime(new Date());
        }
        School s = schoolDao.save(school);
        if (isCreate) {
            privilegeService.initRoleAndPrivilege(school.getId());
        }
        return s;
    }

    @Transactional
    public void deleteById(Integer id) {
        schoolDao.delete(id);
    }

    @Transactional
    public void delete(School school) {
        schoolDao.delete(school);
    }

    @Transactional
    public School resetAccessKeyAndSecret(School school) {
        while (true) {
            school.resetAccessKeyAndSecret();
            if (schoolDao.findFirstByAccessKey(school.getAccessKey()) == null) {
                return schoolDao.save(school);
            }
        }
    }

    @Transactional
    @Override
    public void updateOrg() {
        SystemAuth systemAuth = authService.findOne();
        String accessKey = AesUtils.decrypt(systemAuth.getAccessKey());
        String accessSecret = AesUtils.decrypt(systemAuth.getAccessSecret());
        SolarHttpUtil orgUtil = new SolarHttpUtil(accessKey, accessSecret, host, uri);
        List<School> list = orgUtil.getOrgs();
        this.updateOrg(list);
    }

    @Override
    public void updateOrg(List<School> list) {
        for (School s : list) {
            boolean isCreate = false;
            School school = schoolDao.findByCode(s.getCode());
            if (school == null) {
                school = schoolDao.findFirstByAccessKey(s.getAccessKey());
                if (school != null) {
                    continue;
                }
                school = new School();
                school.setCreateTime(new Date());
                school.setProvince("");
                school.setCity("");
                school.setCode(s.getCode());
                school.setEnable(true);
                school.setGroupDeleteCheck(true);
                school.setDoubleTrack(false);
                isCreate = true;
            }
            school.setName(s.getName());
            school.setAccessKey(s.getAccessKey());
            school.setAccessSecret(s.getAccessSecret());
            // school.setLogoUrl(s.getLogoUrl());
            school.setUpdateTime(new Date());
            schoolDao.save(school);
            if (isCreate) {
                privilegeService.initRoleAndPrivilege(school.getId());
            }
        }
    }

    @Override
    public List<School> parseJson(String json) {
        List<School> schools = new ArrayList<School>();
        JSONArray orgArray = JSONArray.fromObject(json);
        for (int i = 0; i < orgArray.size(); i++) {
            JSONObject org = orgArray.getJSONObject(i);
            School school = new School();
            school.setAccessKey(org.getString("accessKey"));
            school.setAccessSecret(org.getString("accessSecret"));
            school.setCode(org.getString("code"));
            school.setName(org.getString("name"));
            school.setLogoUrl(org.getString("logo"));
            school.setEnable(true);
            school.setGroupDeleteCheck(false);
            school.setDoubleTrack(false);
            schools.add(school);
        }
        return schools;
    }

    @Override
    public School findByParentIdAndSubCode(Integer schoolId, String subCode) {
        School school = schoolDao.findByParentIdAndSubCode(schoolId, subCode);
        return school;
    }
}
