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.security.MessageDigest;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import javax.persistence.*;
import com.dampcake.bencode.Bencode;
import com.dampcake.bencode.Type;
import com.querydsl.jpa.impl.JPAUpdateClause;
import entity.*;
import entity.config;

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, String infoHash) {
        long newTotal = upload;  // convert to long
        EntityManager em = emf.createEntityManager();
        EntityTransaction tx = em.getTransaction();
        tx.begin();
        try {
            // 1) find the seedId by infoHash
            String seedId = em.createQuery(
                "SELECT s.seedId FROM SeedHash s WHERE s.infoHash = :ih", String.class)
                .setParameter("ih", infoHash)
                .getSingleResult();
            // 2) sum existing uploads for this user+seed
            Long sumSoFar = em.createQuery(
                "SELECT COALESCE(SUM(t.upload),0) FROM TransRecord t WHERE t.uploaduserid = :uid AND t.seedid = :sid",
                Long.class)
                .setParameter("uid", userid)
                .setParameter("sid", seedId)
                .getSingleResult();
            long delta = newTotal - sumSoFar;
            if (delta < 0L) {
                tx.rollback();
                return true;   // error: newTotal less than already recorded
            }
            if (delta == 0L) {
                tx.rollback();
                return false;  // nothing to do
            }
            // 3) persist a new TransRecord with only the delta
            TransRecord rd = new TransRecord();
            rd.taskid       = UUID.randomUUID().toString();
            rd.uploaduserid = userid;
            rd.seedid       = seedId;
            rd.upload       = delta;
            rd.maxupload    = newTotal;
            em.persist(rd);

            // 4) 重新计算用户的总上传，确保与 TransRecord 完全一致
            Long totalUpload = em.createQuery(
                "SELECT COALESCE(SUM(t.upload),0) FROM TransRecord t WHERE t.uploaduserid = :uid",
                Long.class
            )
            .setParameter("uid", userid)
            .getSingleResult();
            UserPT user = em.find(UserPT.class, userid);
            user.upload = totalUpload;
            em.merge(user);
            tx.commit();
            return false;      // success
        } catch (RuntimeException ex) {
            if (tx.isActive()) tx.rollback();
            throw ex;
        } finally {
            em.close();
        }
    }
    
    @Override
    public boolean ReduceUpLoad(String userid, int upload){
        long uploadLong = upload;  // convert to long
        EntityManager em = emf.createEntityManager();
        EntityTransaction tx = em.getTransaction();
        tx.begin();
        try {
            // 1) fetch user and ensure enough upload to reduce
            UserPT user = em.find(UserPT.class, userid);
            long before = user.upload;
            if (uploadLong > before) {
                tx.rollback();
                return true;   // error: cannot reduce more than current total
            }
            // 2) subtract
            user.upload = before - uploadLong;
            em.merge(user);
            // (optional) record a negative TransRecord so sums stay in sync
            TransRecord rd = new TransRecord();
            rd.taskid       = UUID.randomUUID().toString();
            rd.uploaduserid = userid;
            rd.seedid       = null;
            rd.upload       = -uploadLong;
            rd.maxupload    = user.upload;
            em.persist(rd);
            tx.commit();
            return false;      // success
        } catch (RuntimeException ex) {
            if (tx.isActive()) tx.rollback();
            throw ex;
        } finally {
            em.close();
        }
    }
    @Override
    public boolean AddDownload(String userid, int download, String infoHash) {
        long newTotal = download;  // convert to long
        EntityManager em = emf.createEntityManager();
        EntityTransaction tx = em.getTransaction();
        try {
            // 1. 查 SeedHash
            TypedQuery<SeedHash> qsh = em.createQuery(
                "SELECT s FROM SeedHash s WHERE s.infoHash = :h", SeedHash.class);
            qsh.setParameter("h", infoHash);
            List<SeedHash> shl = qsh.getResultList();
            if (shl.isEmpty()) {
                System.out.println("seed没有被记录");
                return true;
            }
            String seedid = shl.get(0).seedId;

            // 2. 统计该用户在该种子上的已有 download
            TypedQuery<Long> qsum = em.createQuery(
                "SELECT COALESCE(SUM(t.download),0) FROM TransRecord t " +
                "WHERE t.seedid = :sid AND t.downloaduserid = :uid", Long.class);
            qsum.setParameter("sid", seedid);
            qsum.setParameter("uid", userid);
            long oldSeedSum = qsum.getSingleResult();

            long diff = newTotal - oldSeedSum;
            if (diff <= 0) return false;
            
            System.out.println("AddDownload: 该种子原有总量=" + oldSeedSum + ", 新总量=" + newTotal + ", 增量=" + diff);

            try {
                tx.begin();
                // 1. persist 增量记录
                TransRecord tr = new TransRecord();
                tr.taskid         = UUID.randomUUID().toString();
                tr.downloaduserid = userid;
                tr.seedid         = seedid;
                tr.download       = diff;
                tr.maxdownload    = newTotal;
                em.persist(tr);

                // 2. 全表重新累计该用户所有种子的 download，并更新 UserPT.download
                TypedQuery<Long> qTotal = em.createQuery(
                    "SELECT COALESCE(SUM(t.download),0) FROM TransRecord t WHERE t.downloaduserid = :uid",
                    Long.class
                )
                .setParameter("uid", userid);
                long userTotalDownload = qTotal.getSingleResult();
                QUserPT quser = QUserPT.userPT;
                new JPAUpdateClause(em, quser)
                    .where(quser.userid.eq(userid))
                    .set(quser.download, userTotalDownload)
                    .execute();

                tx.commit();
                return false;
            } catch (Exception e) {
                if (tx.isActive()) tx.rollback();
                return true;
            } finally {
                em.close();
            }
        } catch (Exception e) {
            return true;
        }
    }
    @Override
    public boolean ReduceDownload(String userid, int download) {
        long downloadLong = download;  // convert to long
        EntityManager em = emf.createEntityManager();
        try {
            // 1. 预检查当前值
            TypedQuery<Long> qcurr = em.createQuery(
                "SELECT u.download FROM UserPT u WHERE u.userid = :uid", Long.class);
            qcurr.setParameter("uid", userid);
            long current = qcurr.getSingleResult();
            if (downloadLong > current) {
                em.close();
                return true;
            }
            // 2. 执行减法更新
            EntityTransaction tx = em.getTransaction();
            tx.begin();
            QUserPT q = QUserPT.userPT;
            new JPAUpdateClause(em, q)
                .where(q.userid.eq(userid))
                .set(q.download, q.download.subtract(downloadLong))
                .execute();
            tx.commit();
            return false;
        } catch(Exception e) {
            return true;
        } finally {
            if (em.isOpen()) 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);

            // attempt to parse infoHash, but don’t fail if parsing fails
            String infoHash = null;
            try {
                byte[] torrentData = Files.readAllBytes(target);
                Bencode bencode = new Bencode();
                @SuppressWarnings("unchecked")
                Map<String,Object> meta = (Map<String,Object>) bencode.decode(torrentData, Type.DICTIONARY);
                byte[] infoBytes = bencode.encode((Map<String,Object>) meta.get("info"));
                MessageDigest sha1 = MessageDigest.getInstance("SHA-1");
                byte[] digest = sha1.digest(infoBytes);
                StringBuilder sb = new StringBuilder();
                for (byte b1 : digest) {
                    sb.append(String.format("%02x", b1));
                }
                infoHash = sb.toString();
            } catch (Exception e) {
                System.err.println("Warning: could not parse torrent infoHash: " + e.getMessage());
            }

            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);

                // upsert SeedHash only if we have a valid infoHash
                if (infoHash != null) {
                    SeedHash sh = new SeedHash();
                    sh.seedId = seedid;
                    sh.infoHash = infoHash;
                    em.merge(sh);
                }
                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();
        }
    }
}