package com.kt.event.content.infra.gateway;

import com.kt.event.content.biz.domain.Content;
import com.kt.event.content.biz.domain.GeneratedImage;
import com.kt.event.content.biz.usecase.out.ContentReader;
import com.kt.event.content.biz.usecase.out.ContentWriter;
import com.kt.event.content.infra.gateway.entity.ContentEntity;
import com.kt.event.content.infra.gateway.entity.GeneratedImageEntity;
import com.kt.event.content.infra.gateway.repository.ContentJpaRepository;
import com.kt.event.content.infra.gateway.repository.GeneratedImageJpaRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * Content 영속성 Gateway
 * ContentReader, ContentWriter outbound port 구현
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class ContentGateway implements ContentReader, ContentWriter {

    private final ContentJpaRepository contentRepository;
    private final GeneratedImageJpaRepository imageRepository;

    // ========================================
    // ContentReader 구현
    // ========================================

    @Override
    @Transactional(readOnly = true)
    public Optional<Content> findByEventDraftIdWithImages(Long eventDraftId) {
        log.debug("이벤트 콘텐츠 조회 (with images): eventDraftId={}", eventDraftId);
        return contentRepository.findByEventDraftIdWithImages(eventDraftId)
                .map(ContentEntity::toDomain);
    }

    @Override
    @Transactional(readOnly = true)
    public Optional<GeneratedImage> findImageById(Long imageId) {
        log.debug("이미지 조회: imageId={}", imageId);
        return imageRepository.findById(imageId)
                .map(GeneratedImageEntity::toDomain);
    }

    @Override
    @Transactional(readOnly = true)
    public List<GeneratedImage> findImagesByEventDraftId(Long eventDraftId) {
        log.debug("이미지 목록 조회: eventDraftId={}", eventDraftId);
        return imageRepository.findByEventDraftId(eventDraftId).stream()
                .map(GeneratedImageEntity::toDomain)
                .collect(Collectors.toList());
    }

    // ========================================
    // ContentWriter 구현
    // ========================================

    @Override
    @Transactional
    public Content save(Content content) {
        log.debug("콘텐츠 저장: eventDraftId={}", content.getEventDraftId());

        // Content Entity 조회 또는 생성
        ContentEntity contentEntity = contentRepository.findByEventDraftId(content.getEventDraftId())
                .orElseGet(() -> ContentEntity.create(
                        content.getEventDraftId(),
                        content.getEventTitle(),
                        content.getEventDescription()
                ));

        // Content 업데이트
        contentEntity.update(content.getEventTitle(), content.getEventDescription());

        // 저장
        ContentEntity saved = contentRepository.save(contentEntity);

        return saved.toDomain();
    }

    @Override
    @Transactional
    public GeneratedImage saveImage(GeneratedImage image) {
        log.debug("이미지 저장: eventDraftId={}, style={}, platform={}",
                image.getEventDraftId(), image.getStyle(), image.getPlatform());

        // Content Entity 조회
        ContentEntity contentEntity = contentRepository.findByEventDraftId(image.getEventDraftId())
                .orElseThrow(() -> new IllegalStateException("Content를 먼저 저장해야 합니다"));

        // GeneratedImageEntity 생성
        GeneratedImageEntity imageEntity = GeneratedImageEntity.create(
                image.getEventDraftId(),
                image.getStyle(),
                image.getPlatform(),
                image.getCdnUrl(),
                image.getPrompt()
        );

        // Content와 연결
        contentEntity.addImage(imageEntity);

        // 선택 상태 설정
        if (image.isSelected()) {
            imageEntity.select();
        }

        // 저장
        GeneratedImageEntity saved = imageRepository.save(imageEntity);

        return saved.toDomain();
    }
}
