package com.mosquito.project.service;

import com.mosquito.project.config.AppConfig;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.util.HashMap;
import java.util.Map;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;

class ShareConfigServiceTest {

    private ShareConfigService service;
    private AppConfig appConfig;

    @BeforeEach
    void setUp() {
        appConfig = new AppConfig();
        AppConfig.ShortLinkConfig shortLinkConfig = new AppConfig.ShortLinkConfig();
        shortLinkConfig.setLandingBaseUrl("https://example.com/landing");
        shortLinkConfig.setCdnBaseUrl("https://cdn.example.com");
        appConfig.setShortLink(shortLinkConfig);
        service = new ShareConfigService(appConfig);
    }

    @Test
    void buildShareUrl_fallsBackToDefaultTemplateAndEncodesExtraParams() {
        Map<String, String> extraParams = new HashMap<>();
        extraParams.put("channel", "summer promo");
        extraParams.put("source", "email");

        String url = service.buildShareUrl(100L, 200L, "missing-template", extraParams);

        assertTrue(url.startsWith("https://example.com/landing?"));
        assertTrue(url.contains("activityId=100"));
        assertTrue(url.contains("inviter=200"));
        assertTrue(url.contains("channel=summer+promo"));
        assertTrue(url.contains("source=email"));
    }

    @Test
    void getShareMeta_resolvesPlaceholdersAndUsesTemplate() {
        ShareConfigService.ShareTemplate template = new ShareConfigService.ShareTemplate();
        template.setTitle("活动{{activityId}}");
        template.setDescription("邀请用户{{userId}}参与");
        template.setImageUrl("https://cdn.example.com/share.png");
        template.setLandingPageUrl("https://example.com/landing");
        Map<String, String> utmParams = new HashMap<>();
        utmParams.put("utm_source", "mosquito");
        utmParams.put("utm_medium", "share");
        template.setUtmParams(utmParams);

        service.registerTemplate("custom", template);

        Map<String, Object> meta = service.getShareMeta(101L, 202L, "custom");

        assertEquals("活动101", meta.get("title"));
        assertEquals("邀请用户202参与", meta.get("description"));
        assertEquals("https://cdn.example.com/share.png", meta.get("image"));

        String url = String.valueOf(meta.get("url"));
        assertTrue(url.contains("activityId=101"));
        assertTrue(url.contains("inviter=202"));
        assertTrue(url.contains("utm_source=mosquito"));
        assertTrue(url.contains("utm_medium=share"));
    }

    @Test
    void buildShareUrl_shouldHandleNullExtraParams() {
        ShareConfigService.ShareTemplate template = new ShareConfigService.ShareTemplate();
        template.setLandingPageUrl("https://example.com/landing");
        service.registerTemplate("test", template);

        String url = service.buildShareUrl(1L, 2L, "test", null);

        assertNotNull(url);
        assertTrue(url.contains("activityId=1"));
        assertTrue(url.contains("inviter=2"));
    }

    @Test
    void buildShareUrl_shouldHandleNullUtmParams() {
        ShareConfigService.ShareTemplate template = new ShareConfigService.ShareTemplate();
        template.setLandingPageUrl("https://example.com/landing");
        template.setUtmParams(null);
        service.registerTemplate("test", template);

        String url = service.buildShareUrl(1L, 2L, "test", null);

        assertNotNull(url);
        assertTrue(url.contains("activityId=1"));
    }

    @Test
    void buildShareUrl_shouldSkipNullKeysInExtraParams() {
        ShareConfigService.ShareTemplate template = new ShareConfigService.ShareTemplate();
        template.setLandingPageUrl("https://example.com/landing");
        service.registerTemplate("test", template);

        Map<String, String> extraParams = new HashMap<>();
        extraParams.put(null, "value");
        extraParams.put("key", null);
        extraParams.put("valid", "data");

        String url = service.buildShareUrl(1L, 2L, "test", extraParams);

        assertNotNull(url);
        assertTrue(url.contains("valid=data"));
    }

    @Test
    void getShareMeta_shouldHandleNullTitle() {
        ShareConfigService.ShareTemplate template = new ShareConfigService.ShareTemplate();
        template.setTitle(null);
        template.setDescription("desc");
        template.setImageUrl("img");
        template.setLandingPageUrl("https://example.com/landing");
        service.registerTemplate("test", template);

        Map<String, Object> meta = service.getShareMeta(1L, 2L, "test");

        assertEquals("", meta.get("title"));
    }

    @Test
    void getShareMeta_shouldHandleNullDescription() {
        ShareConfigService.ShareTemplate template = new ShareConfigService.ShareTemplate();
        template.setTitle("title");
        template.setDescription(null);
        template.setImageUrl("img");
        template.setLandingPageUrl("https://example.com/landing");
        service.registerTemplate("test", template);

        Map<String, Object> meta = service.getShareMeta(1L, 2L, "test");

        assertEquals("", meta.get("description"));
    }

    @Test
    void getShareMeta_shouldHandleNullImageUrl() {
        ShareConfigService.ShareTemplate template = new ShareConfigService.ShareTemplate();
        template.setTitle("title");
        template.setDescription("desc");
        template.setImageUrl(null);
        template.setLandingPageUrl("https://example.com/landing");
        service.registerTemplate("test", template);

        Map<String, Object> meta = service.getShareMeta(1L, 2L, "test");

        assertEquals("", meta.get("image"));
    }

    @Test
    void getShareMeta_shouldResolveTimestampPlaceholder() {
        ShareConfigService.ShareTemplate template = new ShareConfigService.ShareTemplate();
        template.setTitle("活动{{timestamp}}");
        template.setDescription("desc");
        template.setImageUrl("img");
        template.setLandingPageUrl("https://example.com/landing");
        service.registerTemplate("test", template);

        Map<String, Object> meta = service.getShareMeta(1L, 2L, "test");

        String title = (String) meta.get("title");
        assertTrue(title.startsWith("活动"));
        assertTrue(title.length() > 2);
    }

    @Test
    void getShareMeta_shouldFallbackToDefaultTemplate() {
        Map<String, Object> meta = service.getShareMeta(1L, 2L, "nonexistent");

        assertEquals("邀请您参与活动", meta.get("title"));
        assertEquals("快来加入我们的活动吧！", meta.get("description"));
        assertTrue(((String) meta.get("image")).contains("/default-share.png"));
    }

    @Test
    void registerTemplate_shouldStoreTemplate() {
        ShareConfigService.ShareTemplate template = new ShareConfigService.ShareTemplate();
        template.setTitle("test");
        service.registerTemplate("mytemplate", template);

        ShareConfigService.ShareTemplate retrieved = service.getTemplate("mytemplate");

        assertNotNull(retrieved);
        assertEquals("test", retrieved.getTitle());
    }

    @Test
    void getTemplate_shouldReturnNullForNonexistent() {
        ShareConfigService.ShareTemplate retrieved = service.getTemplate("nonexistent");

        assertEquals(null, retrieved);
    }

    @Test
    void buildShareUrl_shouldHandleEmptyUtmParams() {
        ShareConfigService.ShareTemplate template = new ShareConfigService.ShareTemplate();
        template.setLandingPageUrl("https://example.com/landing");
        template.setUtmParams(new HashMap<>());
        service.registerTemplate("test", template);

        String url = service.buildShareUrl(1L, 2L, "test", null);

        assertNotNull(url);
        assertTrue(url.contains("activityId=1"));
    }

    @Test
    void buildShareUrl_shouldHandleEmptyExtraParams() {
        ShareConfigService.ShareTemplate template = new ShareConfigService.ShareTemplate();
        template.setLandingPageUrl("https://example.com/landing");
        service.registerTemplate("test", template);

        String url = service.buildShareUrl(1L, 2L, "test", new HashMap<>());

        assertNotNull(url);
        assertTrue(url.contains("activityId=1"));
    }
}
