package com.tiedup.remake.dialogue;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
 * A dialogue entry containing an ID, conditions, and weighted variants.
 * Represents a single dialogue "slot" that can be filled with different text
 * based on personality and context.
 *
 * Personality System: Data-driven dialogue
 */
public class DialogueEntry {

    private static final Random RANDOM = new Random();

    private final String id;
    private final DialogueCondition condition;
    private final List<DialogueVariant> variants;

    public DialogueEntry(
        String id,
        DialogueCondition condition,
        List<DialogueVariant> variants
    ) {
        this.id = id;
        this.condition = condition;
        this.variants = new ArrayList<>(variants);
    }

    public DialogueEntry(String id, DialogueCondition condition) {
        this(id, condition, new ArrayList<>());
    }

    public String getId() {
        return id;
    }

    public DialogueCondition getCondition() {
        return condition;
    }

    public List<DialogueVariant> getVariants() {
        return variants;
    }

    /**
     * Add a variant to this entry.
     */
    public DialogueEntry addVariant(DialogueVariant variant) {
        this.variants.add(variant);
        return this;
    }

    /**
     * Add a simple text variant with default weight.
     */
    public DialogueEntry addVariant(String text) {
        this.variants.add(new DialogueVariant(text));
        return this;
    }

    /**
     * Add a text variant with specified weight.
     */
    public DialogueEntry addVariant(String text, int weight) {
        this.variants.add(new DialogueVariant(text, weight));
        return this;
    }

    /**
     * Check if this entry matches the given context.
     */
    public boolean matches(DialogueContext context) {
        return condition.matches(context);
    }

    /**
     * Select a random variant based on weights.
     *
     * @return Selected variant, or null if no variants available
     */
    public DialogueVariant selectVariant() {
        if (variants.isEmpty()) {
            return null;
        }

        // Calculate total weight
        int totalWeight = 0;
        for (DialogueVariant variant : variants) {
            totalWeight += variant.getWeight();
        }

        if (totalWeight <= 0) {
            return variants.get(RANDOM.nextInt(variants.size()));
        }

        // Weighted random selection
        int roll = RANDOM.nextInt(totalWeight);
        int cumulative = 0;

        for (DialogueVariant variant : variants) {
            cumulative += variant.getWeight();
            if (roll < cumulative) {
                return variant;
            }
        }

        return variants.get(0); // Fallback
    }

    /**
     * Select a random variant and format with context variables.
     *
     * @param context Context for variable substitution
     * @return Formatted dialogue text, or null if no variants
     */
    public String getFormattedDialogue(DialogueContext context) {
        DialogueVariant variant = selectVariant();
        if (variant == null) {
            return null;
        }

        String text = context.substituteVariables(variant.getText());

        // Format action text with asterisks
        if (variant.isAction()) {
            text = "*" + text + "*";
        }

        // Apply gag filter if speaker is gagged
        if (context.isGagged()) {
            // Don't muffle action text (already in asterisks)
            if (!text.startsWith("*") || !text.endsWith("*")) {
                text = GagTalkManager.transformToGaggedSpeech(text);
            }
        }

        return text;
    }

    /**
     * Check if this entry has any variants.
     */
    public boolean hasVariants() {
        return !variants.isEmpty();
    }

    // --- Static builder methods ---

    /**
     * Create an entry that matches any context.
     */
    public static DialogueEntry any(String id) {
        return new DialogueEntry(id, DialogueCondition.any());
    }

    /**
     * Create an entry with a condition builder.
     */
    public static DialogueEntry withCondition(
        String id,
        DialogueCondition condition
    ) {
        return new DialogueEntry(id, condition);
    }

    @Override
    public String toString() {
        return (
            "DialogueEntry{" +
            "id='" +
            id +
            '\'' +
            ", variants=" +
            variants.size() +
            '}'
        );
    }
}
