package cheat;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.transaction.Transactional;

import org.apache.commons.lang3.tuple.Pair;

import com.querydsl.jpa.impl.JPAQueryFactory;

import entity.Appeal;
import entity.QAppeal;
import entity.QSeed;
import entity.User;
import entity.config;

public class Cheat implements CheatInterfnterface {

    @PersistenceContext
    private EntityManager entityManager;

    @Override
    @Transactional
    public boolean AddAppeal(Appeal appeal) {
        try {
            entityManager.persist(appeal);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    @Override
    public Appeal GetAppeal(String appealid) {
        try {
            JPAQueryFactory queryFactory = new JPAQueryFactory(entityManager);
            QAppeal qAppeal = QAppeal.appeal;
            Appeal appeal = queryFactory
                .selectFrom(qAppeal)
                .where(qAppeal.appealid.eq(appealid))
                .fetchOne();
            return appeal;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    @Override
    public Appeal[] GetAppealList() {
        try {
            JPAQueryFactory queryFactory = new JPAQueryFactory(entityManager);
            QAppeal qAppeal = QAppeal.appeal;
            List<Appeal> appeals = queryFactory
                .selectFrom(qAppeal)
                .fetch();
            return appeals.toArray(new Appeal[0]);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    @Override
    public boolean HandleAppeal(String appealid, Integer status) {
        try {
            Appeal appeal = GetAppeal(appealid);
            if (appeal != null) {
                appeal.status = status;
                entityManager.merge(appeal);
                User user = entityManager.find(User.class, appeal.appealuserid);
                if (user != null && user.accountstate != false) {
                    if (status == 1) {
                        user.accountstate = false;
                    }
                    entityManager.merge(user);
                }
                return true;
            }
            return false;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    @Override
    public Pair<String, String>[] GetFakeSeed() {
        List<Pair<String, String>> fakeSeeds = new ArrayList<>();
        try {
            JPAQueryFactory queryFactory = new JPAQueryFactory(entityManager);
            QSeed qSeed = QSeed.seed;
            List<com.querydsl.core.Tuple> results = queryFactory
                .select(qSeed.seedid, qSeed.seeduserid)
                .from(qSeed)
                .where(qSeed.faketime.gt(new config().FakeTime))
                .fetch();
            for (com.querydsl.core.Tuple result : results) {
                String seedid = result.get(qSeed.seedid);
                String userid = result.get(qSeed.seeduserid);
                fakeSeeds.add(Pair.of(seedid, userid));
            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        return fakeSeeds.toArray(new Pair[0]);
    }

    @Override
    public String[] GetPunishedUserList() {
        List<String> punishedUsers = new ArrayList<>();
        try {
            JPAQueryFactory queryFactory = new JPAQueryFactory(entityManager);
            entity.QUser qUser = entity.QUser.user;
            List<String> results = queryFactory
                .select(qUser.userid)
                .from(qUser)
                .where(qUser.accountstate.isTrue())
                .fetch();
            for (String userid : results) {
                punishedUsers.add(userid);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        return punishedUsers.toArray(new String[0]);
    }

    @Override
    public void DetectTrans() {
        // JPAQueryFactory queryFactory = new JPAQueryFactory(entityManager);
        // QSeed qSeed = QSeed.seed;
        // List<Seed> seeds = queryFactory
        //     .selectFrom(qSeed)
        //     .fetch();
        // for (Seed seed : seeds) {
        //     QTransRecord qTransRecord = QTransRecord.transRecord;
        //     List<TransRecord> tasks = queryFactory
        //         .selectFrom(qTransRecord)
        //         .where(qTransRecord.seedid.eq(seed.seedid))
        //         .fetch();

        //     int n = tasks.size();
        //     if (n == 0) continue;

        //     double[] xArr = new double[n];
        //     for (int i = 0; i < n; i++) {
        //         TransRecord t = tasks.get(i);
        //         xArr[i] = Math.max(0, t.upload - t.download);
        //     }

        //     double sum = 0;
        //     for (double x : xArr) sum += x;
        //     double mu = sum / n;

        //     double sqSum = 0;
        //     for (double x : xArr) sqSum += (x - mu) * (x - mu);
        //     double sigma = Math.sqrt(sqSum / n);

        //     for (int i = 0; i < n; i++) {
        //         if (Math.abs(xArr[i] - mu) > 3 * sigma) {
        //             User user = entityManager.find(User.class, tasks.get(i).downloaduserid);
        //             if (user != null) {
        //                 user.detectedCount++;
        //                 user.lastDetectedTime = new java.util.Date();
        //                 entityManager.merge(user);
        //             }
        //         }
        //     }
        // }
    }

    @Override
    public void DetectFakeSeed(){
    }

    @Override
    public boolean DetectFakeSeed(String seedid){
        return false;
    }

    @Override
    public void PunishUser(){
        JPAQueryFactory queryFactory = new JPAQueryFactory(entityManager);
        entity.QUser qUser = entity.QUser.user;
        List<User> users = queryFactory
            .selectFrom(qUser)
            .where(qUser.detectedCount.gt(new entity.config().CheatTime) 
                .or(qUser.fakeDetectedCount.gt(new entity.config().FakeTime)))
            .fetch();

        for (User user : users) {
            user.accountstate = true;
            entityManager.merge(user);
        }
    }
}