package com.gxwebsoft.glt.service;

import com.gxwebsoft.glt.AutoReleaseTestApplication;
import com.gxwebsoft.glt.entity.GltUserTicket;
import com.gxwebsoft.glt.entity.GltUserTicketLog;
import com.gxwebsoft.glt.entity.GltUserTicketRelease;
import com.gxwebsoft.glt.mapper.GltUserTicketLogMapper;
import com.gxwebsoft.glt.mapper.GltUserTicketMapper;
import com.gxwebsoft.glt.mapper.GltUserTicketReleaseMapper;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.jdbc.core.JdbcTemplate;

import java.time.LocalDateTime;
import java.util.List;

import static org.junit.jupiter.api.Assertions.*;

@SpringBootTest(
    classes = AutoReleaseTestApplication.class,
    properties = {
        "spring.datasource.url=jdbc:h2:mem:auto_release;MODE=MySQL;DB_CLOSE_DELAY=-1;DATABASE_TO_LOWER=TRUE",
        "spring.datasource.driver-class-name=org.h2.Driver",
        "spring.datasource.username=sa",
        "spring.datasource.password=",
        "spring.sql.init.mode=always",
        "spring.sql.init.schema-locations=classpath:schema-auto-release-h2.sql",
        "mybatis-plus.configuration.map-underscore-to-camel-case=true",
        "mybatis-plus.global-config.db-config.logic-delete-value=1",
        "mybatis-plus.global-config.db-config.logic-not-delete-value=0"
    }
)
class GltUserTicketAutoReleaseServiceTest {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Autowired
    private GltUserTicketMapper userTicketMapper;

    @Autowired
    private GltUserTicketReleaseMapper releaseMapper;

    @Autowired
    private GltUserTicketLogMapper logMapper;

    @Autowired
    private GltUserTicketAutoReleaseService autoReleaseService;

    @BeforeEach
    void clean() {
        jdbcTemplate.execute("DELETE FROM glt_user_ticket_log");
        jdbcTemplate.execute("DELETE FROM glt_user_ticket_release");
        jdbcTemplate.execute("DELETE FROM glt_user_ticket");
    }

    @Test
    void releaseDue_success_updatesTicketReleaseAndWritesLog() {
        LocalDateTime now = LocalDateTime.of(2026, 2, 6, 12, 0, 0);

        GltUserTicket ticket = new GltUserTicket();
        ticket.setTemplateId(1);
        ticket.setGoodsId(1);
        ticket.setOrderId(1);
        ticket.setOrderNo("T-001");
        ticket.setOrderGoodsId(1);
        ticket.setTotalQty(10);
        ticket.setAvailableQty(0);
        ticket.setFrozenQty(10);
        ticket.setUsedQty(0);
        ticket.setReleasedQty(0);
        ticket.setUserId(100);
        ticket.setSortNumber(0);
        ticket.setComments("test");
        ticket.setStatus(0);
        ticket.setDeleted(0);
        ticket.setTenantId(10584);
        ticket.setCreateTime(now);
        ticket.setUpdateTime(now);
        assertEquals(1, userTicketMapper.insert(ticket));
        assertNotNull(ticket.getId());

        GltUserTicketRelease rel = new GltUserTicketRelease();
        rel.setUserTicketId(ticket.getId().longValue());
        rel.setUserId(100);
        rel.setPeriodNo(1);
        rel.setReleaseQty(3);
        rel.setReleaseTime(now.minusSeconds(1));
        rel.setStatus(0);
        rel.setDeleted(0);
        rel.setTenantId(10584);
        rel.setCreateTime(now);
        rel.setUpdateTime(now);
        assertEquals(1, releaseMapper.insert(rel));
        assertNotNull(rel.getId());

        int releasedCount = autoReleaseService.releaseDue(now, 100);
        assertEquals(1, releasedCount);

        GltUserTicket after = userTicketMapper.selectById(ticket.getId());
        assertNotNull(after);
        assertEquals(3, after.getAvailableQty());
        assertEquals(7, after.getFrozenQty());
        assertEquals(3, after.getReleasedQty());

        GltUserTicketRelease relAfter = releaseMapper.selectById(rel.getId());
        assertNotNull(relAfter);
        assertEquals(1, relAfter.getStatus());

        List<GltUserTicketLog> logs = logMapper.selectList(null);
        assertEquals(1, logs.size());
        assertEquals(ticket.getId(), logs.get(0).getUserTicketId());
        assertEquals(3, logs.get(0).getChangeAvailable());
        assertEquals(-3, logs.get(0).getChangeFrozen());
    }

    @Test
    void releaseDue_notDue_noop() {
        LocalDateTime now = LocalDateTime.of(2026, 2, 6, 12, 0, 0);

        GltUserTicket ticket = new GltUserTicket();
        ticket.setTotalQty(10);
        ticket.setAvailableQty(0);
        ticket.setFrozenQty(10);
        ticket.setUsedQty(0);
        ticket.setReleasedQty(0);
        ticket.setUserId(100);
        ticket.setStatus(0);
        ticket.setDeleted(0);
        ticket.setTenantId(10584);
        ticket.setCreateTime(now);
        ticket.setUpdateTime(now);
        userTicketMapper.insert(ticket);

        GltUserTicketRelease rel = new GltUserTicketRelease();
        rel.setUserTicketId(ticket.getId().longValue());
        rel.setUserId(100);
        rel.setPeriodNo(1);
        rel.setReleaseQty(3);
        rel.setReleaseTime(now.plusDays(1));
        rel.setStatus(0);
        rel.setDeleted(0);
        rel.setTenantId(10584);
        rel.setCreateTime(now);
        rel.setUpdateTime(now);
        releaseMapper.insert(rel);

        int releasedCount = autoReleaseService.releaseDue(now, 100);
        assertEquals(0, releasedCount);

        GltUserTicket after = userTicketMapper.selectById(ticket.getId());
        assertNotNull(after);
        assertEquals(0, after.getAvailableQty());
        assertEquals(10, after.getFrozenQty());

        GltUserTicketRelease relAfter = releaseMapper.selectById(rel.getId());
        assertNotNull(relAfter);
        assertEquals(0, relAfter.getStatus());
        assertEquals(0, logMapper.selectCount(null));
    }

    @Test
    void releaseDue_frozenInsufficient_marksFailed() {
        LocalDateTime now = LocalDateTime.of(2026, 2, 6, 12, 0, 0);

        GltUserTicket ticket = new GltUserTicket();
        ticket.setTotalQty(2);
        ticket.setAvailableQty(0);
        ticket.setFrozenQty(2);
        ticket.setUsedQty(0);
        ticket.setReleasedQty(0);
        ticket.setUserId(100);
        ticket.setStatus(0);
        ticket.setDeleted(0);
        ticket.setTenantId(10584);
        ticket.setCreateTime(now);
        ticket.setUpdateTime(now);
        userTicketMapper.insert(ticket);

        GltUserTicketRelease rel = new GltUserTicketRelease();
        rel.setUserTicketId(ticket.getId().longValue());
        rel.setUserId(100);
        rel.setPeriodNo(1);
        rel.setReleaseQty(3);
        rel.setReleaseTime(now.minusSeconds(1));
        rel.setStatus(0);
        rel.setDeleted(0);
        rel.setTenantId(10584);
        rel.setCreateTime(now);
        rel.setUpdateTime(now);
        releaseMapper.insert(rel);

        int releasedCount = autoReleaseService.releaseDue(now, 100);
        assertEquals(0, releasedCount);

        GltUserTicket after = userTicketMapper.selectById(ticket.getId());
        assertNotNull(after);
        assertEquals(0, after.getAvailableQty());
        assertEquals(2, after.getFrozenQty());

        GltUserTicketRelease relAfter = releaseMapper.selectById(rel.getId());
        assertNotNull(relAfter);
        assertEquals(2, relAfter.getStatus());
        assertEquals(0, logMapper.selectCount(null));
    }
}

