package com.zioinfo.kintex.module.m5.reroom;

import com.zioinfo.kintex.common.error.ApiException;
import com.zioinfo.kintex.common.error.ErrorCode;
import com.zioinfo.kintex.module.m5.RenderJobService;
import com.zioinfo.kintex.module.m5.dto.ReRoomJobRequest;
import com.zioinfo.kintex.module.m5.dto.RenderJobDto;
import com.zioinfo.kintex.module.m5.reroom.dto.ReRoomRenderRequest;
import com.zioinfo.kintex.module.m5.reroom.dto.ReferenceImageDto;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;

/**
 * ReRoomAI 방식 사진 시안(image-to-image) 오케스트레이션 — 소유자 지시 13.2.
 *
 * <p>흐름: 참조 이미지 업로드({@link ReRoomReferenceStore}) → 스타일/지시 검증 → 참조 로컬경로·공개URL 해석 →
 * {@link RenderJobService#publishReRoom} 로 발행(상태/콜백/푸시/쿼터 재사용). 나노바나나 실호출은 Python 워커 담당.
 *
 * <p>보안: GEMINI_API_KEY 는 백엔드에서 다루지 않는다. style 은 서버 화이트리스트로만 허용,
 * instruction 은 프롬프트 "교체" 파트에만 삽입되며 워커가 보존(구조) 지시를 고정한다.
 */
@Service
public class ReRoomStudioService {

    /** ReRoom 스타일 화이트리스트 — prompts/reroom_styles.json 키와 정합(워커 단일 출처). */
    private static final Set<String> ALLOWED_STYLES = Set.of(
            "modern", "minimal", "tech", "luxury", "korean_traditional", "eco");

    private final ReRoomReferenceStore referenceStore;
    private final RenderJobService renderJobService;

    public ReRoomStudioService(ReRoomReferenceStore referenceStore, RenderJobService renderJobService) {
        this.referenceStore = referenceStore;
        this.renderJobService = renderJobService;
    }

    /** 참조 이미지 업로드 → {referenceId, url}. */
    public ReferenceImageDto uploadReference(MultipartFile file) {
        return referenceStore.store(file);
    }

    /** 사진 시안 렌더 발행 → RenderJobDto(QUEUED). 상태는 기존 GET /render-jobs/{jobId} 로 폴링. */
    public RenderJobDto render(String eventId, String boothId, ReRoomRenderRequest request) {
        String style = request.style() == null ? "" : request.style().trim();
        if (!ALLOWED_STYLES.contains(style)) {
            throw new ApiException(ErrorCode.VALIDATION, "지원하지 않는 스타일입니다.");
        }
        // 참조 이미지 해석(존재 검증 포함) — 워커 소비용 로컬경로 + 프론트 표시용 공개 URL.
        String localPath = referenceStore.resolveLocalPath(request.referenceId());
        String publicUrl = referenceStore.publicUrl(request.referenceId());

        // 메타데이터/해시용 최소 씬(부스 컨텍스트). 프롬프트는 워커의 reroom 경로가 style/instruction 으로 조립.
        Map<String, Object> scene = new LinkedHashMap<>();
        scene.put("reroom", true);
        scene.put("style", style);
        Map<String, Object> booth = new LinkedHashMap<>();
        booth.put("id", boothId);
        scene.put("booth", booth);

        String instruction = request.instruction() == null ? null : request.instruction().trim();

        ReRoomJobRequest job = new ReRoomJobRequest(
                "R1", scene, localPath, publicUrl, style,
                instruction == null || instruction.isBlank() ? null : instruction);
        return renderJobService.publishReRoom(eventId, boothId, job);
    }
}
