package trackertest;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.UUID;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

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

import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.DynamicTest;
import org.junit.jupiter.api.TestFactory;

import entity.TransRecord;
import entity.TransportId;
import entity.config;
import tracker.Tracker;

public class TrackerTest {
    private static EntityManagerFactory emf;
    private static EntityManager em;
    private static List<String> userIds;
    private static Map<String, Long> originalUploads;
    private static Tracker tracker;

    @BeforeAll
    static void setup() throws Exception {
        // 强制加载 MySQL 驱动，否则无法建立连接
        Class.forName("com.mysql.cj.jdbc.Driver");
        config cfg = new config();
        Map<String,Object> props = new HashMap<>();
        // 添加时区和 SSL 参数
        String jdbcUrl = String.format(
            "jdbc:mysql://%s/%s?useSSL=false&serverTimezone=UTC",
            cfg.SqlURL, cfg.TestDatabase);
        props.put("javax.persistence.jdbc.url", jdbcUrl);
        props.put("javax.persistence.jdbc.user", cfg.SqlUsername);
        props.put("javax.persistence.jdbc.password", cfg.SqlPassword);
        props.put("javax.persistence.jdbc.driver", "com.mysql.cj.jdbc.Driver");
        emf = Persistence.createEntityManagerFactory("myPersistenceUnit", props);
        em = emf.createEntityManager();
        // 使用简单实体名而非带包名前缀
        userIds = em.createQuery(
            "select u.userid from UserPT u", String.class
        ).getResultList();

        // 保存初始 upload 值
        originalUploads = new HashMap<>();
        for (String uid : userIds) {
            Long up = em.createQuery(
                "select u.upload from UserPT u where u.userid = :uid", Long.class
            ).setParameter("uid", uid)
             .getSingleResult();
            originalUploads.put(uid, up != null ? up : 0L);
        }
        tracker = new Tracker(emf);
    }

    @AfterAll
    static void teardown() {
        if (em != null && em.isOpen()) em.close();
        if (emf != null && emf.isOpen()) emf.close();
    }

    @TestFactory
    Collection<DynamicTest> testAddUpLoad() {
        Random rnd = new Random();
        return userIds.stream()
            .map(uid -> DynamicTest.dynamicTest("AddUpLoad for user " + uid, () -> {
                int delta = rnd.nextInt(1000) + 1; // Ensure non-zero value
                long before = originalUploads.get(uid);
                
                // AddUpLoad 前打印
                System.out.println("Running AddUpLoad assert for user=" + uid + ", delta=" + delta);
                Assertions.assertFalse(tracker.AddUpLoad(uid, delta), 
                    "AddUpLoad should return false on successful operation");
                System.out.println("AddUpLoad assert passed for user=" + uid);

                // Clear the persistence context to ensure fresh data is fetched
                em.clear();
                
                // Fetch updated value
                Long after = em.createQuery(
                    "select u.upload from UserPT u where u.userid = :uid", Long.class
                ).setParameter("uid", uid)
                 .getSingleResult();

                // upload 值断言前打印
                System.out.println("Running upload-value assert for user=" + uid);
                Assertions.assertEquals(before + delta, after, 
                    "Upload value should be increased by " + delta);
                System.out.println("Upload-value assert passed for user=" + uid);
                
                // ReduceUpLoad 前打印
                System.out.println("Running ReduceUpLoad assert for user=" + uid + ", delta=" + delta);
                Assertions.assertFalse(tracker.ReduceUpLoad(uid, delta),
                    "ReduceUpLoad should return false on successful operation");
                System.out.println("ReduceUpLoad assert passed for user=" + uid);
            }))
            .collect(Collectors.toList());
    }

    @TestFactory
    Collection<DynamicTest> testReduceUpLoad() {
        Random rnd = new Random();
        return userIds.stream()
            .map(uid -> DynamicTest.dynamicTest("ReduceUpLoad for user " + uid, () -> {
                long before = originalUploads.get(uid);
                int max = (int)Math.min(before, 1000);
                int delta = max > 0 ? rnd.nextInt(max) + 1 : 0;
                if (delta == 0) return;  // 无可减量时跳过

                // ReduceUpLoad 前打印
                System.out.println("Running ReduceUpLoad assert for user=" + uid + ", delta=" + delta);
                Assertions.assertFalse(tracker.ReduceUpLoad(uid, delta));
                System.out.println("ReduceUpLoad assert passed for user=" + uid);

                Long after = em.createQuery(
                    "select u.upload from UserPT u where u.userid = :uid", Long.class
                ).setParameter("uid", uid)
                 .getSingleResult();

                // 减少后值断言前打印
                System.out.println("Running post-reduce-value assert for user=" + uid);
                Assertions.assertEquals(before - delta, after);
                System.out.println("Post-reduce-value assert passed for user=" + uid);

                // 回滚 AddUpLoad 前打印
                System.out.println("Running rollback AddUpLoad assert for user=" + uid + ", delta=" + delta);
                Assertions.assertFalse(tracker.AddUpLoad(uid, delta));
                System.out.println("Rollback AddUpLoad assert passed for user=" + uid);
            }))
            .collect(Collectors.toList());
    }

    @TestFactory
    Collection<DynamicTest> testAddDownload() {
        Random rnd = new Random();
        return userIds.stream()
            .map(uid -> DynamicTest.dynamicTest("AddDownload for user " + uid, () -> {
                int delta = rnd.nextInt(1000) + 1;
                Long before = em.createQuery(
                    "select u.download from UserPT u where u.userid = :uid", Long.class
                ).setParameter("uid", uid).getSingleResult();
                before = before != null ? before : 0L;

                System.out.println("Running AddDownload assert for user=" + uid + ", delta=" + delta);
                Assertions.assertFalse(tracker.AddDownload(uid, delta),
                    "AddDownload should return false on successful operation");
                em.clear();

                Long after = em.createQuery(
                    "select u.download from UserPT u where u.userid = :uid", Long.class
                ).setParameter("uid", uid).getSingleResult();
                System.out.println("Running download-value assert for user=" + uid);
                Assertions.assertEquals(before + delta, after,
                    "Download value should be increased by " + delta);

                System.out.println("Running rollback ReduceDownload assert for user=" + uid + ", delta=" + delta);
                Assertions.assertFalse(tracker.ReduceDownload(uid, delta),
                    "Rollback ReduceDownload should return false");
            }))
            .collect(Collectors.toList());
    }

    @TestFactory
    Collection<DynamicTest> testReduceDownload() {
        Random rnd = new Random();
        return userIds.stream()
            .map(uid -> DynamicTest.dynamicTest("ReduceDownload for user " + uid, () -> {
                Long before = em.createQuery(
                    "select u.download from UserPT u where u.userid = :uid", Long.class
                ).setParameter("uid", uid).getSingleResult();
                before = before != null ? before : 0L;
                int max = before.intValue();
                int delta = max > 0 ? rnd.nextInt(max) + 1 : 0;
                if (delta == 0) return;

                System.out.println("Running ReduceDownload assert for user=" + uid + ", delta=" + delta);
                Assertions.assertFalse(tracker.ReduceDownload(uid, delta));
                Long after = em.createQuery(
                    "select u.download from UserPT u where u.userid = :uid", Long.class
                ).setParameter("uid", uid).getSingleResult();
                System.out.println("Running post-reduce-download-value assert for user=" + uid);
                Assertions.assertEquals(before - delta, after);

                System.out.println("Running rollback AddDownload assert for user=" + uid + ", delta=" + delta);
                Assertions.assertFalse(tracker.AddDownload(uid, delta));
            }))
            .collect(Collectors.toList());
    }

    @TestFactory
    Collection<DynamicTest> testAddMagic() {
        Random rnd = new Random();
        return userIds.stream()
            .map(uid -> DynamicTest.dynamicTest("AddMagic for user " + uid, () -> {
                int delta = rnd.nextInt(1000) + 1;
                Integer before = em.createQuery(
                    "select u.magic from UserPT u where u.userid = :uid", Integer.class
                ).setParameter("uid", uid).getSingleResult();
                before = before != null ? before : 0;

                System.out.println("Running AddMagic assert for user=" + uid + ", delta=" + delta);
                Assertions.assertFalse(tracker.AddMagic(uid, delta));
                em.clear();

                Integer after = em.createQuery(
                    "select u.magic from UserPT u where u.userid = :uid", Integer.class
                ).setParameter("uid", uid).getSingleResult();
                System.out.println("Running magic-value assert for user=" + uid);
                Assertions.assertEquals(before + delta, after.intValue());

                System.out.println("Running rollback ReduceMagic assert for user=" + uid + ", delta=" + delta);
                Assertions.assertFalse(tracker.ReduceMagic(uid, delta));
            }))
            .collect(Collectors.toList());
    }

    @TestFactory
    Collection<DynamicTest> testReduceMagic() {
        Random rnd = new Random();
        return userIds.stream()
            .map(uid -> DynamicTest.dynamicTest("ReduceMagic for user " + uid, () -> {
                Integer before = em.createQuery(
                    "select u.magic from UserPT u where u.userid = :uid", Integer.class
                ).setParameter("uid", uid).getSingleResult();
                before = before != null ? before : 0;
                int max = before.intValue();
                int delta = max > 0 ? rnd.nextInt(max) + 1 : 0;
                if (delta == 0) return;

                System.out.println("Running ReduceMagic assert for user=" + uid + ", delta=" + delta);
                Assertions.assertFalse(tracker.ReduceMagic(uid, delta));
                Integer after = em.createQuery(
                    "select u.magic from UserPT u where u.userid = :uid", Integer.class
                ).setParameter("uid", uid).getSingleResult();
                System.out.println("Running post-reduce-magic-value assert for user=" + uid);
                Assertions.assertEquals(before - delta, after.intValue());

                System.out.println("Running rollback AddMagic assert for user=" + uid + ", delta=" + delta);
                Assertions.assertFalse(tracker.AddMagic(uid, delta));
            }))
            .collect(Collectors.toList());
    }

    @TestFactory
    Collection<DynamicTest> testAddRecord() {
        Random rnd = new Random();
        // 取所有 seed_id 用于外键测试
        List<String> seedIds = em.createQuery(
            "select s.seedid from Seed s", String.class
        ).getResultList();
        // 若无可用 seedId 则跳过此组测试，避免 rnd.nextInt(0) 抛错
        // if (seedIds.isEmpty()) {
        //     return Collections.emptyList();
        // }
        return IntStream.range(0, 10)
            .mapToObj(i -> DynamicTest.dynamicTest("AddRecord test #" + i, () -> {
                // 随机构造 TransRecord
                String uploaderId = userIds.get(rnd.nextInt(userIds.size()));
                String downloaderId = userIds.get(rnd.nextInt(userIds.size()));
                String seedId = seedIds.get(rnd.nextInt(seedIds.size()));
                String taskId = UUID.randomUUID().toString();

                TransRecord rd = new TransRecord();
                rd.taskid = taskId;
                rd.uploaduserid = uploaderId;
                rd.downloaduserid = downloaderId;
                rd.seedid = seedId;
                rd.upload = rnd.nextInt(10000);
                rd.download = rnd.nextInt(10000);
                rd.maxupload = rd.upload + rnd.nextInt(10000);
                rd.maxdownload = rd.download + rnd.nextInt(10000);

                // 调用待测方法
                int ret = tracker.AddRecord(rd);
                Assertions.assertTrue(ret > 0, "返回值应为新记录主键");

                // 验证已插入
                TransportId pk = new TransportId(taskId, uploaderId, downloaderId);
                TransRecord fetched = em.find(TransRecord.class, pk);
                Assertions.assertNotNull(fetched, "应查询到新增的 TransRecord");

                // 清理：删除测试记录
                EntityTransaction tx = em.getTransaction();
                tx.begin();
                em.remove(fetched);
                tx.commit();
            }))
            .collect(Collectors.toList());
    }
}
