package cheat;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.EntityTransaction;

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 {

    private EntityManagerFactory emf;

    public Cheat() {
        config cfg = new config();
        Map<String, Object> props = new HashMap<>();
        props.put("javax.persistence.jdbc.url",
                "jdbc:mysql://" + cfg.SqlURL + "/" + cfg.Database);
        props.put("javax.persistence.jdbc.user", cfg.SqlUsername);
        props.put("javax.persistence.jdbc.password", cfg.SqlPassword);
        this.emf = Persistence.createEntityManagerFactory("myPersistenceUnit", props);
    }

    // 测试时注入
    public Cheat(EntityManagerFactory emf) {
        this.emf = emf;
    }

    private EntityManager getEntityManager() {
        return emf.createEntityManager();
    }

    @Override
    public boolean AddAppeal(Appeal appeal) {
        EntityManager em = getEntityManager();
        EntityTransaction tx = em.getTransaction();
        try {
            tx.begin();
            em.persist(appeal);
            tx.commit();
        } catch (Exception e) {
            if (tx.isActive()) {
                tx.rollback();
            }
            e.printStackTrace();
            return false;
        } finally {
            em.close();
        }
        return true;
    }

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

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

    @Override
    public boolean HandleAppeal(String appealid, Integer status) {
        EntityManager em = getEntityManager();
        EntityTransaction tx = em.getTransaction();
        try {
            tx.begin();
            Appeal appeal = em.find(Appeal.class, appealid);
            if (appeal != null) {
                appeal.status = status;
                em.merge(appeal);
                User user = em.find(User.class, appeal.appealuserid);
                if (user != null && user.accountstate != false) {
                    if (status == 1) {
                        user.accountstate = false;
                    }
                    em.merge(user);
                }
                tx.commit();
                return true;
            }
            return false;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        } finally {
            if (tx.isActive()) {
                tx.rollback();
            }
            em.close();
        }
    }

    @Override
    public Pair<String, String>[] GetFakeSeed() {
        List<Pair<String, String>> fakeSeeds = new ArrayList<>();
        EntityManager em = getEntityManager();
        try {
            JPAQueryFactory queryFactory = new JPAQueryFactory(em);
            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;
        } finally {
            em.close();
        }
        return fakeSeeds.toArray(new Pair[0]);
    }

    @Override
    public String[] GetPunishedUserList() {
        List<String> punishedUsers = new ArrayList<>();
        EntityManager em = getEntityManager();
        try {
            JPAQueryFactory queryFactory = new JPAQueryFactory(em);
            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;
        } finally {
            em.close();
        }
        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() {
        EntityManager em = getEntityManager();
        EntityTransaction tx = em.getTransaction();
        try {
            tx.begin();
            JPAQueryFactory queryFactory = new JPAQueryFactory(em);
            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;
                em.merge(user);
            }
            tx.commit();
        } catch (Exception e) {
            if (tx.isActive()) tx.rollback();
        } finally {
            em.close();
        }
    }
}
