package com.zioinfo.kintex.auth;

import com.zioinfo.kintex.auth.mapper.UserMapper;
import com.zioinfo.kintex.auth.profile.ProfilePhotoService;
import com.zioinfo.kintex.common.error.ApiException;
import com.zioinfo.kintex.common.error.ErrorCode;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;

import java.nio.file.Path;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

/**
 * 프로필 사진 서비스 — 매직바이트 판별 + base64 저장/검증 단위테스트.
 * DB(UserMapper)는 목으로 대체하고 파일 저장은 임시 디렉터리로 격리한다.
 */
class ProfilePhotoServiceTest {

    // ── 매직바이트 판별(SVG/위조 헤더 차단) ─────────────────────────

    @Test
    void detectsPng() {
        byte[] png = {(byte) 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A, 0, 0};
        assertEquals("png", ProfilePhotoService.detectImageType(png));
    }

    @Test
    void detectsJpeg() {
        byte[] jpg = {(byte) 0xFF, (byte) 0xD8, (byte) 0xFF, (byte) 0xE0, 0, 0};
        assertEquals("jpg", ProfilePhotoService.detectImageType(jpg));
    }

    @Test
    void detectsWebp() {
        byte[] webp = {'R', 'I', 'F', 'F', 0, 0, 0, 0, 'W', 'E', 'B', 'P'};
        assertEquals("webp", ProfilePhotoService.detectImageType(webp));
    }

    @Test
    void rejectsSvgAndText() {
        byte[] svg = "<svg xmlns=\"http://www.w3.org/2000/svg\"></svg>".getBytes();
        assertNull(ProfilePhotoService.detectImageType(svg), "SVG(실행형)는 이미지로 판별되면 안 됨");
        byte[] script = "<script>alert(1)</script>".getBytes();
        assertNull(ProfilePhotoService.detectImageType(script));
    }

    // ── base64 업로드 저장 ──────────────────────────────────────────

    @Test
    void base64PngRoundTrip(@TempDir Path tmp) {
        UserMapper mapper = mock(UserMapper.class);
        when(mapper.findPhotoMeta("u1")).thenReturn(null);
        ProfilePhotoService svc = new ProfilePhotoService(mapper, tmp.toString());

        byte[] png = {(byte) 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A, 1, 2, 3};
        String b64 = java.util.Base64.getEncoder().encodeToString(png);

        String url = svc.uploadBase64("u1", b64, "image/png");
        assertEquals("/api/auth/users/u1/photo", url);
    }

    @Test
    void base64RejectsNonImage(@TempDir Path tmp) {
        UserMapper mapper = mock(UserMapper.class);
        ProfilePhotoService svc = new ProfilePhotoService(mapper, tmp.toString());
        String b64 = java.util.Base64.getEncoder().encodeToString("not-an-image".getBytes());
        ApiException ex = assertThrows(ApiException.class, () -> svc.uploadBase64("u1", b64, "image/png"));
        assertEquals(ErrorCode.VALIDATION, ex.getCode());
    }

    @Test
    void loadReturns404WhenNoPhoto(@TempDir Path tmp) {
        UserMapper mapper = mock(UserMapper.class);
        when(mapper.findPhotoMeta("u1")).thenReturn(null);
        ProfilePhotoService svc = new ProfilePhotoService(mapper, tmp.toString());
        ApiException ex = assertThrows(ApiException.class, () -> svc.load("u1"));
        assertEquals(ErrorCode.NOT_FOUND, ex.getCode());
    }

    @Test
    void serveUrlBuildsExpectedPath() {
        assertEquals("/api/auth/users/abc/photo", ProfilePhotoService.serveUrl("abc"));
        assertNotNull(ProfilePhotoService.serveUrl("x"));
        assertTrue(ProfilePhotoService.serveUrl("x").startsWith("/api/auth/"));
    }
}
