package tracker;

import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.HashMap;
import java.util.Map;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import com.querydsl.jpa.impl.JPAUpdateClause;
import entity.QUserPT;
import entity.Seed;
import entity.SeedDownload;
import entity.TransRecord;
import entity.config;
import entity.TTorent;
import java.time.LocalDateTime;

public class Tracker implements TrackerInterface {
    private final EntityManagerFactory emf;

    // 默认构造：产线数据库
    public Tracker() {
        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 Tracker(EntityManagerFactory emf) {
        this.emf = emf;
    }

    @Override
    public boolean AddUpLoad(String userid, int upload) {
        EntityManager em = emf.createEntityManager();
        EntityTransaction tx = em.getTransaction();
        try {
            tx.begin();
            QUserPT q = QUserPT.userPT;
            long updated = new JPAUpdateClause(em, q)
                .where(q.userid.eq(userid))
                .set(q.upload, q.upload.add(upload))
                .execute();
            tx.commit();
            // 成功时 updated>0 返回 false，失败时返回 true
            return updated <= 0;
        } catch(Exception e) {
            if (tx.isActive()) tx.rollback();
            return true;
        } finally {
            em.close();
        }
    }

    @Override
    public boolean ReduceUpLoad(String userid, int upload){
        EntityManager em = emf.createEntityManager();
        EntityTransaction tx = em.getTransaction();
        try {
            tx.begin();
            QUserPT q = QUserPT.userPT;
            long updated = new JPAUpdateClause(em, q)
                .where(q.userid.eq(userid))
                .set(q.upload, q.upload.subtract(upload))
                .execute();
            tx.commit();
            // 成功时 updated>0 返回 false，失败时返回 true
            return updated <= 0;
        } catch(Exception e) {
            if (tx.isActive()) tx.rollback();
            return true;
        } finally {
            em.close();
        }
    }

    @Override
    public boolean AddDownload(String userid, int download) {
        EntityManager em = emf.createEntityManager();
        EntityTransaction tx = em.getTransaction();
        try {
            tx.begin();
            QUserPT q = QUserPT.userPT;
            long updated = new JPAUpdateClause(em, q)
                .where(q.userid.eq(userid))
                .set(q.download, q.download.add(download))
                .execute();
            tx.commit();
            return updated <= 0;
        } catch(Exception e) {
            if (tx.isActive()) tx.rollback();
            return true;
        } finally {
            em.close();
        }
    }

    @Override
    public boolean ReduceDownload(String userid, int download) {
        EntityManager em = emf.createEntityManager();
        EntityTransaction tx = em.getTransaction();
        try {
            tx.begin();
            QUserPT q = QUserPT.userPT;
            long updated = new JPAUpdateClause(em, q)
                .where(q.userid.eq(userid))
                .set(q.download, q.download.subtract(download))
                .execute();
            tx.commit();
            return updated <= 0;
        } catch(Exception e) {
            if (tx.isActive()) tx.rollback();
            return true;
        } finally {
            em.close();
        }
    }

    @Override
    public boolean AddMagic(String userid, int magic) {
        EntityManager em = emf.createEntityManager();
        EntityTransaction tx = em.getTransaction();
        try {
            tx.begin();
            QUserPT q = QUserPT.userPT;
            long updated = new JPAUpdateClause(em, q)
                .where(q.userid.eq(userid))
                .set(q.magic, q.magic.add(magic))
                .execute();
            tx.commit();
            return updated <= 0;
        } catch(Exception e) {
            if (tx.isActive()) tx.rollback();
            return true;
        } finally {
            em.close();
        }
    }

    @Override
    public boolean ReduceMagic(String userid, int magic) {
        EntityManager em = emf.createEntityManager();
        EntityTransaction tx = em.getTransaction();
        try {
            tx.begin();
            QUserPT q = QUserPT.userPT;
            long updated = new JPAUpdateClause(em, q)
                .where(q.userid.eq(userid))
                .set(q.magic, q.magic.subtract(magic))
                .execute();
            tx.commit();
            return updated <= 0;
        } catch(Exception e) {
            if (tx.isActive()) tx.rollback();
            return true;
        } finally {
            em.close();
        }
    }

    @Override
    public int SaveTorrent(String seedid, File TTorent){
        try {
            Path storageDir = Paths.get(config.TORRENT_STORAGE_DIR);
            if (!Files.exists(storageDir)) {
                Files.createDirectories(storageDir);
            }
            String filename = TTorent.getName();
            Path target = storageDir.resolve(seedid + "_" + filename);
            Files.copy(TTorent.toPath(), target, StandardCopyOption.REPLACE_EXISTING);

            EntityManager em = emf.createEntityManager();
            EntityTransaction tx = em.getTransaction();
            try {
                tx.begin();
                Seed seed = em.find(Seed.class, seedid);
                seed.url = target.toString();
                em.merge(seed);
                tx.commit();
                return 0;
            } catch (Exception e) {
                if (tx.isActive()) tx.rollback();
                return 1;
            } finally {
                em.close();
            }
        } catch (Exception e) {
            return 1;
        }
    }

    @Override
    public File GetTTorent(String seedid, String userid, String ip) {
        EntityManager em = emf.createEntityManager();
        EntityTransaction tx = em.getTransaction();
        File file = null;
        try {
            Seed seed = em.find(Seed.class, seedid);
            if (seed == null || seed.url == null) {
                return null;
            }
            file = new File(seed.url);
            if (!file.exists()) {
                return null;
            }
            tx.begin();
            SeedDownload sd = new SeedDownload();
            sd.seedId = seedid;
            sd.userId = userid;
            sd.clientIp = ip;
            LocalDateTime now = LocalDateTime.now();
            sd.downloadStart = now;
            sd.downloadEnd = now;
            em.persist(sd);
            tx.commit();
        } catch (Exception e) {
            if (tx.isActive()) tx.rollback();
            // ignore persistence errors and still return the file
        } finally {
            em.close();
        }
        return file;
    }

    @Override
    public int AddRecord(TransRecord rd){
        EntityManager em = emf.createEntityManager();
        EntityTransaction tx = em.getTransaction();
        try {
            tx.begin();
            em.persist(rd);
            tx.commit();
            // 持久化成功，返回1表示插入成功
            return 1;
        } catch (Exception e) {
            if (tx.isActive()) tx.rollback();
            return -1;
        } finally {
            em.close();
        }
    }
}
