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) {
        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;
            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();
        }
    }
}