package com.ruoyi.app.omgpay;

import com.ruoyi.app.omgpay.dto.OmgNotifyRequest;
import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.system.omgpay.service.OmgIpnAuditService;
import org.junit.jupiter.api.Test;
import org.springframework.core.io.Resource;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;

import java.lang.reflect.Method;
import java.nio.charset.StandardCharsets;
import java.util.List;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

class OmgPaymentReturnControllerTest {

    @Test
    void exposesPaymentResultContractOnly() throws Exception {
        Method result = OmgPaymentReturnController.class.getDeclaredMethod("result", OmgNotifyRequest.class);

        assertArrayEquals(new String[]{"/result"}, result.getAnnotation(PostMapping.class).value());
        assertNotNull(result.getAnnotation(Anonymous.class));
        assertNotNull(result.getParameters()[0].getAnnotation(OmgNotifyForm.class));
    }

    @Test
    void returnsSafeNonCachedHtmlHeadersAndServiceStatus() {
        OmgPaymentClientReturnService service = mock(OmgPaymentClientReturnService.class);
        OmgIpnAuditService audit = mock(OmgIpnAuditService.class);
        OmgNotifyRequest request = new OmgNotifyRequest("127.0.0.1", "raw", List.of(), null);
        when(service.paymentResult(request)).thenReturn(new OmgPaymentReturnPage(400, "<html>safe</html>"));

        ResponseEntity<String> response = new OmgPaymentReturnController(service, audit).result(request);

        assertEquals(400, response.getStatusCode().value());
        assertEquals("<html>safe</html>", response.getBody());
        assertEquals("no-store", response.getHeaders().getFirst("Cache-Control"));
        assertEquals("no-referrer", response.getHeaders().getFirst("Referrer-Policy"));
        assertTrue(response.getHeaders().getFirst("Content-Security-Policy").contains("default-src 'none'"));
        assertTrue(response.getHeaders().getFirst("Content-Security-Policy").contains("script-src 'self' 'unsafe-inline'"));
        org.mockito.Mockito.verify(audit).append("127.0.0.1", "raw");
    }

    @Test
    void packagesTheOfficialUniAppWebViewBridgeLocally() {
        assertNotNull(getClass().getResource("/static/omg/uni.webview.1.5.8.js"));
    }

    @Test
    void exposesThePackagedUniAppBridgeThroughAnAnonymousJavascriptEndpoint() throws Exception {
        Method bridge = OmgPaymentReturnController.class.getDeclaredMethod("bridge");

        assertArrayEquals(new String[]{"/bridge.js"}, bridge.getAnnotation(GetMapping.class).value());
        assertNotNull(bridge.getAnnotation(Anonymous.class));

        OmgPaymentClientReturnService service = mock(OmgPaymentClientReturnService.class);
        OmgIpnAuditService audit = mock(OmgIpnAuditService.class);
        ResponseEntity<?> response = (ResponseEntity<?>) bridge.invoke(
                new OmgPaymentReturnController(service, audit));

        assertEquals(200, response.getStatusCode().value());
        assertEquals("application/javascript;charset=UTF-8", response.getHeaders().getContentType().toString());
        assertEquals("no-store", response.getHeaders().getFirst("Cache-Control"));
        Resource body = assertInstanceOf(Resource.class, response.getBody());
        String script = new String(body.getInputStream().readAllBytes(), StandardCharsets.UTF_8);
        assertTrue(script.startsWith("/*! DCloud uni-app web-view SDK 1.5.8"));
    }
}
