package com.zioinfo.mall.event;

import com.zioinfo.mall.admin.AuditService;
import com.zioinfo.mall.ai.OllamaClient;
import com.zioinfo.mall.event.mapper.EventMapper;
import com.zioinfo.mall.promotion.MallCoupon;
import com.zioinfo.mall.promotion.mapper.PromotionMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * 이벤트/캠페인 서비스 — 발행·참여(연계 쿠폰 자동 발급)·AI 카피 보조·성과 집계.
 *
 * <p>연계 쿠폰은 promotion 모듈(mall_coupon)을 재사용한다. AI 카피는 Ollama(localhost)
 * + Java 폴백. 외부 호출 없음.
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class EventService {

    private final EventMapper mapper;
    private final PromotionMapper promotionMapper;
    private final OllamaClient ollama;
    private final AuditService auditService;

    // ---------- 조회 ----------
    public List<MallEvent> list(String status, String type, boolean activeOnly) {
        return mapper.findEvents(status, type, activeOnly);
    }

    /** 진행중 이벤트(스토어프론트). 등급 지정 시 전체대상 + 해당 등급 전용만. */
    public List<MallEvent> ongoing(String tier) {
        List<MallEvent> events = mapper.findOngoing(tier);
        for (MallEvent e : events) e.setBanners(mapper.findBanners(e.getId(), true));
        return events;
    }

    public MallEvent detail(Long id) {
        MallEvent e = mapper.findById(id);
        if (e == null) throw new RuntimeException("ERR-EVT-404: 이벤트를 찾을 수 없습니다");
        e.setBanners(mapper.findBanners(id, false));
        return e;
    }

    /** 진행중 이벤트의 활성 배너(홈 캐러셀). */
    public List<MallEventBanner> activeBanners() {
        return mapper.findActiveBanners();
    }

    // ---------- CRUD ----------
    @Transactional
    public MallEvent create(MallEvent e, String actor) {
        e.setCreatedBy(actor);
        mapper.insert(e);
        if (e.getBanners() != null) {
            for (MallEventBanner b : e.getBanners()) {
                b.setEventId(e.getId());
                mapper.insertBanner(b);
            }
        }
        auditService.log(actor, "EVENT_CREATE", e.getCode() == null ? String.valueOf(e.getId()) : e.getCode(), e.getTitle());
        return detail(e.getId());
    }

    @Transactional
    public MallEvent update(Long id, MallEvent e, String actor) {
        e.setId(id);
        mapper.update(e);
        if (e.getBanners() != null) {
            mapper.deleteBannersByEvent(id);
            for (MallEventBanner b : e.getBanners()) {
                b.setEventId(id);
                mapper.insertBanner(b);
            }
        }
        auditService.log(actor, "EVENT_UPDATE", String.valueOf(id), e.getTitle());
        return detail(id);
    }

    @Transactional
    public MallEvent publish(Long id, String actor) {
        MallEvent e = mapper.findById(id);
        if (e == null) throw new RuntimeException("ERR-EVT-404: 이벤트를 찾을 수 없습니다");
        mapper.updateStatus(id, "PUBLISHED");
        auditService.log(actor, "EVENT_PUBLISH", String.valueOf(id), e.getTitle());
        return detail(id);
    }

    @Transactional
    public MallEvent end(Long id, String actor) {
        mapper.updateStatus(id, "ENDED");
        auditService.log(actor, "EVENT_END", String.valueOf(id), null);
        return detail(id);
    }

    @Transactional
    public void delete(Long id, String actor) {
        mapper.deleteBannersByEvent(id);
        mapper.delete(id);
        auditService.log(actor, "EVENT_DELETE", String.valueOf(id), null);
    }

    // ---------- 참여 (연계 쿠폰 자동 발급) ----------
    /**
     * 이벤트 참여 — 등급 자격 검증 후 연계 쿠폰을 발급(발급수 증가)하고 참여 이력 기록.
     * 쿠폰 미연계 이벤트는 참여 이력만 기록.
     */
    @Transactional
    public Map<String, Object> join(Long eventId, String owner, String memberTier) {
        MallEvent e = mapper.findById(eventId);
        if (e == null) throw new RuntimeException("ERR-EVT-404: 이벤트를 찾을 수 없습니다");
        if (!"PUBLISHED".equals(e.getStatus()) || !Boolean.TRUE.equals(e.getActive())) {
            throw new RuntimeException("ERR-EVT-409: 진행중 이벤트가 아닙니다");
        }
        if (!isEligibleTier(e.getTargetTiers(), memberTier)) {
            throw new RuntimeException("ERR-EVT-403: 이벤트 대상 등급이 아닙니다");
        }
        Map<String, Object> out = new LinkedHashMap<>();
        out.put("eventId", eventId);
        out.put("eventCode", e.getCode());
        String reward = null;
        Long couponId = e.getCouponId();
        if (couponId != null) {
            MallCoupon c = promotionMapper.findCouponById(couponId);
            if (c != null && Boolean.TRUE.equals(c.getActive())) {
                promotionMapper.incCouponIssued(couponId);
                out.put("coupon", Map.of("id", c.getId(), "code", c.getCode(), "name", c.getName()));
                reward = "COUPON:" + c.getCode();
            }
        }
        if (e.getBonusPointRate() != null) {
            out.put("bonusPointRate", e.getBonusPointRate());
            if (reward == null) reward = "BONUS_POINT:" + e.getBonusPointRate();
        }
        if (e.getGiftDescription() != null && !e.getGiftDescription().isBlank()) {
            out.put("gift", e.getGiftDescription());
            if (reward == null) reward = "GIFT";
        }
        mapper.insertParticipation(eventId, owner, couponId, null, reward);
        out.put("joined", true);
        return out;
    }

    // ---------- 성과 ----------
    public Map<String, Object> performance(Long eventId) {
        MallEvent e = mapper.findById(eventId);
        if (e == null) throw new RuntimeException("ERR-EVT-404: 이벤트를 찾을 수 없습니다");
        Map<String, Object> perf = mapper.performance(eventId);
        Map<String, Object> out = new LinkedHashMap<>(perf == null ? Map.of() : perf);
        out.put("eventId", eventId);
        out.put("title", e.getTitle());
        out.put("status", e.getStatus());
        return out;
    }

    // ---------- AI 카피 보조 ----------
    /** 이벤트 카피(헤드라인/서브) 생성 보조. Ollama 실패 시 템플릿 폴백. */
    public Map<String, Object> copyAssist(String eventType, String theme, String tone) {
        String prompt = "You are a flower-shop marketing copywriter. Write a punchy event banner for "
                + "type='" + eventType + "' theme='" + (theme == null ? "" : theme) + "' tone='"
                + (tone == null ? "warm" : tone) + "'. Reply as: HEADLINE | SUBTEXT.";
        String ai = ollama.generate(prompt);
        Map<String, Object> out = new LinkedHashMap<>();
        if (ai != null && !ai.isBlank() && ai.contains("|")) {
            String[] parts = ai.split("\\|", 2);
            out.put("headline", parts[0].trim());
            out.put("subtext", parts[1].trim());
            out.put("source", "ollama");
        } else {
            String[] fb = fallbackCopy(eventType, theme);
            out.put("headline", fb[0]);
            out.put("subtext", fb[1]);
            out.put("source", "fallback");
        }
        return out;
    }

    // ---------- helpers ----------
    private boolean isEligibleTier(String targetTiers, String memberTier) {
        if (targetTiers == null || targetTiers.isBlank()) return true; // 전체 대상
        if (memberTier == null) return false;
        for (String t : targetTiers.split(",")) {
            if (t.trim().equalsIgnoreCase(memberTier.trim())) return true;
        }
        return false;
    }

    private String[] fallbackCopy(String eventType, String theme) {
        String t = theme == null || theme.isBlank() ? "Fresh Blooms" : theme;
        return switch (eventType == null ? "" : eventType.toUpperCase()) {
            case "DISCOUNT" -> new String[]{t + " Sale", "Save on hand-tied bouquets — limited time only."};
            case "POINT_BONUS" -> new String[]{"Double Points Event", "Earn bonus loyalty points on every " + t + " order."};
            case "GIFT" -> new String[]{"Free Gift With Purchase", "A little something extra with your " + t + "."};
            case "TIER_ONLY" -> new String[]{"Members-Only Preview", "Exclusive early access to " + t + " for our top members."};
            case "SEASON" -> new String[]{t + " Seasonal Collection", "Celebrate the season with our florist's picks."};
            default -> new String[]{t, "Discover our latest floral arrangements."};
        };
    }
}
