package com.loremind.application.generationcontext;

import com.loremind.domain.campaigncontext.Arc;
import com.loremind.domain.campaigncontext.Chapter;
import com.loremind.domain.campaigncontext.Scene;
import com.loremind.domain.campaigncontext.ports.ArcRepository;
import com.loremind.domain.campaigncontext.ports.ChapterRepository;
import com.loremind.domain.campaigncontext.ports.SceneRepository;
import com.loremind.domain.generationcontext.NarrativeEntityContext;
import org.springframework.stereotype.Component;

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

/**
 * Service applicatif qui construit un {@link NarrativeEntityContext}
 * depuis une entité Arc / Chapter / Scene du Campaign Context.
 *
 * Responsabilité unique : mapper les champs textuels spécifiques de chaque
 * type vers la map uniforme `fields` du VO. Utilise LinkedHashMap pour
 * préserver l'ordre des champs dans le prompt (lisibilité).
 */
@Component
public class NarrativeEntityContextBuilder {

    private final ArcRepository arcRepository;
    private final ChapterRepository chapterRepository;
    private final SceneRepository sceneRepository;

    public NarrativeEntityContextBuilder(
            ArcRepository arcRepository,
            ChapterRepository chapterRepository,
            SceneRepository sceneRepository) {
        this.arcRepository = arcRepository;
        this.chapterRepository = chapterRepository;
        this.sceneRepository = sceneRepository;
    }

    /**
     * Charge l'entité narrative ciblée et la projette vers un VO du GenerationContext.
     *
     * @param entityType "arc", "chapter" ou "scene" (insensible à la casse)
     * @param entityId   l'ID de l'entité
     * @throws IllegalArgumentException si le type est inconnu ou l'entité introuvable
     */
    public NarrativeEntityContext build(String entityType, String entityId) {
        String normalized = entityType == null ? "" : entityType.trim().toLowerCase();
        switch (normalized) {
            case "arc":     return fromArc(loadArc(entityId));
            case "chapter": return fromChapter(loadChapter(entityId));
            case "scene":   return fromScene(loadScene(entityId));
            default:
                throw new IllegalArgumentException("Type d'entité narrative inconnu: " + entityType);
        }
    }

    // --- Chargement ---------------------------------------------------------

    private Arc loadArc(String id) {
        return arcRepository.findById(id)
                .orElseThrow(() -> new IllegalArgumentException("Arc non trouvé: " + id));
    }

    private Chapter loadChapter(String id) {
        return chapterRepository.findById(id)
                .orElseThrow(() -> new IllegalArgumentException("Chapitre non trouvé: " + id));
    }

    private Scene loadScene(String id) {
        return sceneRepository.findById(id)
                .orElseThrow(() -> new IllegalArgumentException("Scène non trouvée: " + id));
    }

    // --- Mapping entité → VO ------------------------------------------------

    private NarrativeEntityContext fromArc(Arc a) {
        Map<String, String> fields = new LinkedHashMap<>();
        putField(fields, "description (synopsis)", a.getDescription());
        putField(fields, "themes",     a.getThemes());
        putField(fields, "stakes",     a.getStakes());
        putField(fields, "rewards",    a.getRewards());
        putField(fields, "resolution", a.getResolution());
        putField(fields, "gmNotes",    a.getGmNotes());
        return NarrativeEntityContext.builder()
                .entityType("arc")
                .title(a.getName())
                .fields(fields)
                .build();
    }

    private NarrativeEntityContext fromChapter(Chapter c) {
        Map<String, String> fields = new LinkedHashMap<>();
        putField(fields, "description (synopsis)", c.getDescription());
        putField(fields, "playerObjectives", c.getPlayerObjectives());
        putField(fields, "narrativeStakes", c.getNarrativeStakes());
        putField(fields, "gmNotes",          c.getGmNotes());
        return NarrativeEntityContext.builder()
                .entityType("chapter")
                .title(c.getName())
                .fields(fields)
                .build();
    }

    private NarrativeEntityContext fromScene(Scene s) {
        Map<String, String> fields = new LinkedHashMap<>();
        putField(fields, "description",          s.getDescription());
        putField(fields, "location",             s.getLocation());
        putField(fields, "timing",               s.getTiming());
        putField(fields, "atmosphere",           s.getAtmosphere());
        putField(fields, "playerNarration",      s.getPlayerNarration());
        putField(fields, "choicesConsequences",  s.getChoicesConsequences());
        putField(fields, "combatDifficulty",     s.getCombatDifficulty());
        putField(fields, "enemies",              s.getEnemies());
        putField(fields, "gmSecretNotes",        s.getGmSecretNotes());
        return NarrativeEntityContext.builder()
                .entityType("scene")
                .title(s.getName())
                .fields(fields)
                .build();
    }

    /** Null/blank devient chaîne vide — uniforme côté prompt, pas de NPE côté LLM. */
    private static void putField(Map<String, String> target, String key, String value) {
        target.put(key, value == null ? "" : value);
    }
}
