import { ConnectionTargetResolver } from "../../connections/services/ConnectionTargetResolver.js";
import { ChronicleNarrativeModel } from "../models/ChronicleNarrativeModel.js";

export class RegionChronicleViewModel {
    static prepareEvent(event = {}, { excludeEntityId = "" } = {}) {
        const excluded = String(excludeEntityId || "");
        const participants = (event.participants || []).map(participant => {
            const entityId = String(participant.id || participant.entityId || "");
            const node = entityId ? ConnectionTargetResolver.fromEntityReference({ entityId }) : null;
            const resolved = node ? ConnectionTargetResolver.resolveDisplayNodeSync(node) : null;
            return {
                ...participant,
                entityId,
                name: resolved?.missing === false ? resolved.name : participant.name,
                imageSrc: resolved?.missing === false ? resolved.img : participant.imageSrc,
                canOpen: !!node && resolved?.missing === false && ConnectionTargetResolver.canUserSeeNode(resolved)
            };
        });
        const factionColor = participants.find(participant => participant.role === "faction" && /^#[0-9a-f]{6}$/i.test(participant.color))?.color;
        const narrative = ChronicleNarrativeModel.normalize(event.narrative).map(segment => {
            if (segment.type !== "entity") return segment;
            const node = ConnectionTargetResolver.fromEntityReference({ entityId: segment.entityId });
            const resolved = node ? ConnectionTargetResolver.resolveDisplayNodeSync(node) : null;
            return {
                ...segment,
                text: resolved?.missing === false ? resolved.name : segment.fallback
            };
        });
        const message = narrative.map(segment => segment.text).join("");
        const scope = ["personal", "local", "regional"].includes(String(event.scope || ""))
            ? String(event.scope)
            : "regional";
        return {
            ...event,
            scope,
            label: String(event.label || "Regional Event"),
            icon: String(event.icon || "fas fa-book-open"),
            message,
            narrative,
            accentStyle: `--augur-chronicle-event-accent:${factionColor || "#8b6b3f"}`,
            participants: participants.filter(participant => participant.entityId !== excluded),
            searchableParticipants: participants,
            resources: Array.isArray(event.resources) ? event.resources : []
        };
    }

    static matchesFilters(event, filters = {}) {
        const participants = event.searchableParticipants || event.participants || [];
        const participantKey = participant => String(participant.id || participant.entityId || participant.uuid || participant.name || "");
        if (filters.faction && !participants.some(participant => participant.role === "faction" && participantKey(participant) === filters.faction)) return false;
        if (filters.actor && !participants.some(participant => participant.role === "actor" && participantKey(participant) === filters.actor)) return false;
        if (filters.location && !participants.some(participant => participant.role === "location" && participantKey(participant) === filters.location)) return false;
        if (filters.type && String(event.type || "") !== filters.type) return false;
        if (filters.scope === "regional" && event.scope === "personal") return false;
        if (filters.scope === "personal" && event.scope !== "personal") return false;
        const year = Number(event.year || 0);
        if (filters.yearFrom && year < Number(filters.yearFrom)) return false;
        if (filters.yearTo && year > Number(filters.yearTo)) return false;
        const search = String(filters.search || "").trim().toLocaleLowerCase();
        if (search) {
            const haystack = [
                event.message,
                event.label,
                event.type,
                ...participants.map(participant => participant.name),
                ...(event.resources || []).map(resource => resource.name)
            ].filter(Boolean).join(" ").toLocaleLowerCase();
            if (!haystack.includes(search)) return false;
        }
        return true;
    }

    static groupByYear(events = []) {
        const byYear = new Map();
        for (const event of events) {
            const year = Number(event?.year || 0);
            if (!byYear.has(year)) byYear.set(year, []);
            byYear.get(year).push(event);
        }
        return [...byYear.entries()]
            .sort(([left], [right]) => left - right)
            .map(([year, entries]) => ({ year, events: entries }));
    }

    static participantOptions(events, role) {
        const values = new Map();
        for (const event of events || []) {
            for (const participant of event.searchableParticipants || event.participants || []) {
                if (participant.role !== role) continue;
                const value = String(participant.id || participant.entityId || participant.uuid || participant.name || "");
                if (value && !values.has(value)) values.set(value, String(participant.name || value));
            }
        }
        return [...values.entries()].map(([value, label]) => ({ value, label })).sort((a, b) => a.label.localeCompare(b.label));
    }

    static typeOptions(events = []) {
        const values = new Map();
        for (const event of events) {
            const value = String(event.type || "");
            if (value && !values.has(value)) values.set(value, String(event.label || value));
        }
        return [...values.entries()].map(([value, label]) => ({ value, label })).sort((a, b) => a.label.localeCompare(b.label));
    }

    static summaryItems(chronicle) {
        const summary = chronicle?.summary || {};
        const settlements = Number(summary.villages || 0) + Number(summary.towns || 0) + Number(summary.cities || 0);
        const resourceSites = Number(summary.loggingCamps || 0) + Number(summary.clayPits || 0) + Number(summary.mines || 0);
        const fortifications = Number(summary.strongholds || 0) + Number(summary.castles || 0);
        return [
            { label: "Years", value: Number(chronicle?.years || summary.years || 0), icon: "fas fa-calendar-days" },
            { label: "Settlements", value: settlements, icon: "fas fa-city" },
            { label: "Resource Sites", value: resourceSites, icon: "fas fa-hammer" },
            { label: "Fortifications", value: fortifications, icon: "fas fa-shield-halved" },
            { label: "Roads", value: Number(summary.roads || 0), icon: "fas fa-road" },
            { label: "People", value: Number(summary.people || 0), icon: "fas fa-user-group" },
            { label: "Factions", value: Number(summary.factions || 0), icon: "fas fa-flag" },
            { label: "Relationships", value: Number(summary.relationships || 0), icon: "fas fa-people-arrows" }
        ].filter(item => item.value > 0);
    }
}
