package com.gxwebsoft.cms.service.impl;

import com.gxwebsoft.cms.entity.CmsWebsite;
import com.gxwebsoft.cms.mapper.CmsWebsiteMapper;
import com.gxwebsoft.cms.service.CmsNavigationService;
import com.gxwebsoft.common.core.utils.RedisUtil;
import com.gxwebsoft.shop.vo.ShopVo;
import org.junit.jupiter.api.Test;

import java.lang.reflect.Field;
import java.util.Collections;

import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

class CmsWebsiteServiceImplCacheTest {

    @Test
    void getSiteInfo_cacheValueIsJsonNull_shouldFallbackToDb() throws Exception {
        Integer tenantId = 1;

        RedisUtil redisUtil = mock(RedisUtil.class);
        CmsNavigationService cmsNavigationService = mock(CmsNavigationService.class);
        CmsWebsiteMapper cmsWebsiteMapper = mock(CmsWebsiteMapper.class);

        // 历史缓存可能存在字符串 "null"；Jackson 解析后会得到 null，需回源 DB。
        when(redisUtil.get("SiteInfo:" + tenantId)).thenReturn("null");
        when(cmsNavigationService.listRel(any())).thenReturn(Collections.emptyList());

        CmsWebsite website = new CmsWebsite();
        website.setTenantId(tenantId);
        website.setTenantName("tenant");
        website.setWebsiteName("site");
        when(cmsWebsiteMapper.getByTenantId(tenantId)).thenReturn(website);

        CmsWebsiteServiceImpl service = new CmsWebsiteServiceImpl();
        setField(service, "redisUtil", redisUtil);
        setField(service, "cmsNavigationService", cmsNavigationService);
        setField(service, "baseMapper", cmsWebsiteMapper);

        ShopVo vo = service.getSiteInfo(tenantId);

        assertNotNull(vo);
        verify(redisUtil).delete("SiteInfo:" + tenantId);
        verify(cmsWebsiteMapper).getByTenantId(tenantId);
    }

    private static void setField(Object target, String fieldName, Object value) throws Exception {
        Class<?> c = target.getClass();
        while (c != null) {
            try {
                Field f = c.getDeclaredField(fieldName);
                f.setAccessible(true);
                f.set(target, value);
                return;
            } catch (NoSuchFieldException ignored) {
                c = c.getSuperclass();
            }
        }
        throw new NoSuchFieldException(fieldName);
    }
}

