package com.wisedu.mooc.app.log.dao;

import com.wisedu.coeus.core.dao.BaseDao;
import com.wisedu.coeus.core.db.PageMaker;
import com.wisedu.coeus.util.Strings;
import com.wisedu.mooc.app.log.bo.LogUserVisit;
import com.wisedu.mooc.app.log.bo.LogUserVisitPos;
import org.springframework.stereotype.Repository;
import org.springframework.util.CollectionUtils;

import java.util.*;

@Repository("logUserVisitDao")
public class LogUserVisitDao extends BaseDao {

    public void insertLog(LogUserVisit logUserVisit, LogUserVisitPos logUserVisitPos) {
        String sql = "select * from log_user_visit where visit_session=:visitSession and visit_key=:visitKey and coeus_user_id=:userId order by visit_time desc";
        Map<String, Object> map = new HashMap<String, Object>();

        map.put("visitSession", logUserVisit.getVisitSession());
        map.put("visitKey", logUserVisit.getVisitKey());
        map.put("userId", logUserVisit.getCoeusUserId());

        List<LogUserVisit> list = this.queryForBeanList(LogUserVisit.class, sql, map, 1, 1);

        String posId = Strings.getUUID();

        if (CollectionUtils.isEmpty(list)) {
            //插入新的访问记录
            String logId = Strings.getUUID();
            logUserVisit.setLogId(logId);
            logUserVisit.setVisitPosCount(1);
            logUserVisit.setLastPosId(posId);
            logUserVisit.setRefererUrl(logUserVisitPos.getVisitUrl());
            logUserVisit.setVisitUrl(logUserVisitPos.getVisitUrl());
            this.insert(logUserVisit);

            logUserVisitPos.setPosId(posId);
            logUserVisitPos.setLogId(logId);
            this.insert(logUserVisitPos);
        } else {
            Long diff = 0L;
            LogUserVisit exitsUserVisit = list.get(0);

            // 获取上次访问点
            LogUserVisitPos lastUserVisitPos = load(LogUserVisitPos.class, exitsUserVisit.getLastPosId());
            if (lastUserVisitPos != null) {
                // 更新上次访问点的持续时间
                diff = logUserVisitPos.getVisitTime() - lastUserVisitPos.getVisitTime();
                lastUserVisitPos.setVisitDuration(diff.intValue());
                try {
                    this.merge(lastUserVisitPos);
                } catch (Exception e) {
                    LOGGER.error(e.getMessage(), e);
                }
            }

            // 保存本次访问点
            logUserVisitPos.setPosId(posId);
            logUserVisitPos.setLogId(exitsUserVisit.getLogId());
            this.insert(logUserVisitPos);

            // 更新已存在日志记录
            diff = logUserVisit.getVisitTime() - exitsUserVisit.getVisitTime();
            exitsUserVisit.setVisitUrl(logUserVisitPos.getVisitUrl());
            exitsUserVisit.setVisitPosCount(exitsUserVisit.getVisitPosCount() + 1);
            exitsUserVisit.setVisitDuration(diff.intValue());
            exitsUserVisit.setLastPosId(posId);

            try {
                this.merge(exitsUserVisit);
            } catch (Exception e) {
                LOGGER.error(e.getMessage(), e);
            }
        }

    }

    public PageMaker queryLogUserVisit(Long userId, String searchKey, Integer periodType, Integer orderType, int pageIndex, int pageSize) {
        String sql = "select * from log_user_visit t where t.coeus_user_id=:userId ";

        Map<String, Object> params = new HashMap<String, Object>();
        params.put("userId", userId);

        if (Strings.isNotEmpty(searchKey)) {
            sql = sql + " and (t.province like :key or t.city like :key or t.ip_address like :key or t.referer_url like :key " + sqlHelper.supportLike() + ")";
            params.put("key", this.sqlHelper.toLikeValue(searchKey));
        }

        sql = this.sqlPeriodProcess(sql, params, periodType);

        if (orderType == 1) {
            //按照访问时间降序
            sql = sql + " order by t.visit_date desc";
        } else if (orderType == 2) {
            //按照访问时间升序
            sql = sql + " order by t.visit_date asc";
        } else if (orderType == 3) {
            //按照访问页数降序
            sql = sql + " order by t.visit_pos_count desc";
        } else if (orderType == 4) {
            //按照访问页数升序
            sql = sql + " order by t.visit_pos_count asc";
        } else if (orderType == 5) {
            //按照停留总时长降序
            sql = sql + " order by t.visit_duration desc";
        } else if (orderType == 6) {
            //按照停留总时长升序
            sql = sql + " order by t.visit_duration asc";
        }

        return this.query(LogUserVisit.class, sql, params, pageIndex, pageSize);
    }

    public Long countVisitPages(Long userId, String searchKey, Integer periodType) {
        String sql = "select sum(t.visit_pos_count) from log_user_visit t where t.coeus_user_id=:userId ";
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("userId", userId);

        if (Strings.isNotEmpty(searchKey)) {
            sql = sql + " and (t.province like :key or t.city like :key or t.ip_address like :key or t.referer_url like :key " + sqlHelper.supportLike() + ")";
            params.put("key", this.sqlHelper.toLikeValue(searchKey));
        }

        sql = this.sqlPeriodProcess(sql, params, periodType);
        return this.queryForLong(sql, params);
    }

    public Long sumVisitTimes(Long userId, String searchKey, Integer periodType) {
        String sql = "select sum(t.visit_duration) from log_user_visit t where t.coeus_user_id=:userId ";
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("userId", userId);

        if (Strings.isNotEmpty(searchKey)) {
            sql = sql + " and (t.province like :key or t.city like :key or t.ip_address like :key or t.referer_url like :key " + sqlHelper.supportLike() + ")";
            params.put("key", this.sqlHelper.toLikeValue(searchKey));
        }

        sql = this.sqlPeriodProcess(sql, params, periodType);
        return this.queryForLong(sql, params);
    }

    private String sqlPeriodProcess(String sql, Map<String, Object> params, Integer periodType) {
        //1昨天 2最近7天 3最近30天 4所有历史纪录
        Calendar calendar = Calendar.getInstance();
        if (periodType == 1) {
            //昨天
            calendar.set(Calendar.HOUR, 0);
            calendar.set(Calendar.MINUTE, 0);
            calendar.set(Calendar.SECOND, 0);
            calendar.set(Calendar.MILLISECOND, 0);

            Date end = calendar.getTime();

            calendar.add(Calendar.DAY_OF_YEAR, -1);
            Date start = calendar.getTime();

            params.put("start", start);
            params.put("end", end);

            sql = sql + " and (t.visit_date between :start and :end)";

        } else if (periodType == 2) {
            //最近7天
            Date end = calendar.getTime();

            calendar.add(Calendar.DAY_OF_YEAR, -7);
            Date start = calendar.getTime();

            params.put("start", start);
            params.put("end", end);

            sql = sql + " and (t.visit_date between :start and :end)";
        } else if (periodType == 3) {
            //最近30天
            Date end = calendar.getTime();

            calendar.add(Calendar.DAY_OF_YEAR, -30);
            Date start = calendar.getTime();

            params.put("start", start);
            params.put("end", end);

            sql = sql + " and (t.visit_date between :start and :end)";
        }

        return sql;
    }

    public List<LogUserVisitPos> queryUserVisitPoss(String logId) {
        String sql = "select * from log_user_visit_pos t where t.log_id=:logId ";
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("logId", logId);
        return this.queryForEntityList(LogUserVisitPos.class, sql, params, -1, -1);
    }

    public LogUserVisit queryUserVisit(String logId) {
        return this.load(LogUserVisit.class, logId);
    }
}
