import { extension_settings } from "/scripts/extensions.js";
import { saveSettingsDebounced } from "/script.js";
import { extensionName } from "../settings.js";

const RULE_PROFILE_KEY = 'ruleProfiles';
const RULE_ASSIGNMENTS_KEY = 'ruleProfileAssignments';

// ── 功能槽定义 ──────────────────────────────────────────────────────────────────
export const RULE_SLOTS = {
    table:             { label: '表格提取规则' },
    historiography:    { label: '史官/总结提取规则' },
    condensation:      { label: '翰林院·浓缩规则' },
    queryPreprocessing:{ label: '翰林院·查询预处理规则' },
};

function sanitizeRuleProfile(profile = {}) {
    const exclusionRules = Array.isArray(profile.exclusionRules)
        ? profile.exclusionRules
            .map(rule => ({
                start: String(rule?.start ?? '').trim(),
                end: String(rule?.end ?? '').trim(),
            }))
            .filter(rule => rule.start)
        : [];

    return {
        id: String(profile.id ?? '').trim(),
        name: String(profile.name ?? '').trim(),
        tagExtractionEnabled: Boolean(profile.tagExtractionEnabled),
        tags: String(profile.tags ?? ''),
        exclusionRules,
        excludeUserMessages: Boolean(profile.excludeUserMessages),
    };
}

function cloneRuleProfile(profile = {}) {
    return {
        id: profile.id || '',
        name: profile.name || '',
        tagExtractionEnabled: Boolean(profile.tagExtractionEnabled),
        tags: profile.tags || '',
        exclusionRules: Array.isArray(profile.exclusionRules)
            ? profile.exclusionRules.map(rule => ({
                start: rule.start || '',
                end: rule.end || '',
            }))
            : [],
        excludeUserMessages: Boolean(profile.excludeUserMessages),
    };
}

function createRuleProfileId(name = 'rule-profile') {
    const base = String(name || 'rule-profile')
        .toLowerCase()
        .replace(/[^a-z0-9]+/g, '-')
        .replace(/^-+|-+$/g, '') || 'rule-profile';
    return `${base}-${Date.now().toString(36)}`;
}

function ensureSettingsRoot() {
    if (!extension_settings[extensionName]) {
        extension_settings[extensionName] = {};
    }
    return extension_settings[extensionName];
}

function ensureProfileMap() {
    const settings = ensureSettingsRoot();
    if (!settings[RULE_PROFILE_KEY] || typeof settings[RULE_PROFILE_KEY] !== 'object' || Array.isArray(settings[RULE_PROFILE_KEY])) {
        settings[RULE_PROFILE_KEY] = {};
    }
    return settings[RULE_PROFILE_KEY];
}

function ensureAssignments() {
    const settings = ensureSettingsRoot();
    if (!settings[RULE_ASSIGNMENTS_KEY] || typeof settings[RULE_ASSIGNMENTS_KEY] !== 'object' || Array.isArray(settings[RULE_ASSIGNMENTS_KEY])) {
        settings[RULE_ASSIGNMENTS_KEY] = {};
    }
    return settings[RULE_ASSIGNMENTS_KEY];
}

function mergeRuleConfig(profile, fallback = {}) {
    const safeFallback = sanitizeRuleProfile({
        id: fallback.id,
        name: fallback.name,
        tagExtractionEnabled: fallback.tagExtractionEnabled,
        tags: fallback.tags,
        exclusionRules: fallback.exclusionRules,
    });

    if (!profile) {
        return safeFallback;
    }

    return {
        id: profile.id,
        name: profile.name,
        tagExtractionEnabled: profile.tagExtractionEnabled,
        tags: profile.tags,
        exclusionRules: cloneRuleProfile(profile).exclusionRules.length > 0
            ? cloneRuleProfile(profile).exclusionRules
            : safeFallback.exclusionRules,
    };
}

function _dispatchChange() {
    const profiles = Object.values(ensureProfileMap())
        .map(p => cloneRuleProfile(p))
        .sort((a, b) => (a.name || a.id).localeCompare(b.name || b.id, 'zh-Hans-CN'));
    const assignments = { ...ensureAssignments() };
    document.dispatchEvent(new CustomEvent('amily2:ruleProfilesChanged', {
        detail: { profiles, assignments },
    }));
}

export class RuleProfileManager {
    listProfiles() {
        const profiles = Object.values(ensureProfileMap())
            .map(profile => cloneRuleProfile(profile))
            .sort((left, right) => {
                const leftName = left.name || left.id;
                const rightName = right.name || right.id;
                return leftName.localeCompare(rightName, 'zh-Hans-CN');
            });
        return profiles;
    }

    getProfile(id) {
        if (!id) return null;
        const profile = ensureProfileMap()[id];
        return profile ? cloneRuleProfile(profile) : null;
    }

    saveProfile(profile) {
        const normalized = sanitizeRuleProfile(profile);
        const profileId = normalized.id || createRuleProfileId(normalized.name);
        const nextProfile = {
            ...normalized,
            id: profileId,
            name: normalized.name || profileId,
        };

        ensureProfileMap()[profileId] = nextProfile;
        saveSettingsDebounced();
        _dispatchChange();
        return cloneRuleProfile(nextProfile);
    }

    deleteProfile(id) {
        if (!id) return false;
        const profiles = ensureProfileMap();
        if (!profiles[id]) return false;
        delete profiles[id];
        saveSettingsDebounced();
        _dispatchChange();
        return true;
    }

    resolveProfile(id, fallback = {}) {
        return mergeRuleConfig(this.getProfile(id), fallback);
    }

    // ── 功能槽分配 ──────────────────────────────────────────────────────────────

    getAssignment(slot) {
        if (!RULE_SLOTS[slot]) return null;
        return ensureAssignments()[slot] || null;
    }

    setAssignment(slot, profileId) {
        if (!RULE_SLOTS[slot]) return false;
        const assignments = ensureAssignments();
        if (profileId) {
            assignments[slot] = profileId;
        } else {
            delete assignments[slot];
        }
        saveSettingsDebounced();
        _dispatchChange();
        return true;
    }

    getAssignedProfile(slot) {
        const id = this.getAssignment(slot);
        if (!id) return null;
        const profile = ensureProfileMap()[id];
        return profile ? cloneRuleProfile(profile) : null;
    }
}

export const ruleProfileManager = new RuleProfileManager();

export function resolveRuleConfig(ruleProfileId, fallback = {}) {
    return ruleProfileManager.resolveProfile(ruleProfileId, fallback);
}

/**
 * 通过功能槽名解析规则配置（推荐方式）
 * 先查 assignments，再回退到旧字段
 */
export function resolveSlotRuleConfig(slot, legacyFallback = {}) {
    const assignedId = ruleProfileManager.getAssignment(slot);
    if (assignedId) {
        const profile = ruleProfileManager.getProfile(assignedId);
        if (profile) return profile;
    }
    // 回退到旧的 resolve 路径
    return sanitizeRuleProfile(legacyFallback);
}

export function resolveCondensationRuleConfig(settings = {}) {
    const condensation = settings.condensation || {};
    return resolveSlotRuleConfig('condensation', {
        ...condensation,
        ruleProfileId: condensation.ruleProfileId,
    });
}

export function resolveQueryPreprocessingRuleConfig(settings = {}) {
    const queryPreprocessing = settings.queryPreprocessing || {};
    return resolveSlotRuleConfig('queryPreprocessing', {
        ...queryPreprocessing,
        ruleProfileId: queryPreprocessing.ruleProfileId,
    });
}

export function resolveTableRuleConfig(settings = {}) {
    return resolveSlotRuleConfig('table', {
        id: settings.table_rule_profile_id,
        tagExtractionEnabled: Boolean(settings.table_tags_to_extract),
        tags: settings.table_tags_to_extract || '',
        exclusionRules: settings.table_exclusion_rules || [],
    });
}

export function resolveHistoriographyRuleConfig(settings = {}) {
    return resolveSlotRuleConfig('historiography', {
        id: settings.historiographyRuleProfileId,
        tagExtractionEnabled: settings.historiographyTagExtractionEnabled ?? false,
        tags: settings.historiographyTags || '',
        exclusionRules: settings.historiographyExclusionRules || [],
    });
}

// ── 一次性迁移：旧分散 profileId 字段 → 统一 assignments ─────────────────────
;(() => {
    const settings = ensureSettingsRoot();
    const assignments = ensureAssignments();
    let changed = false;

    // table: table_rule_profile_id → assignments.table
    if (settings.table_rule_profile_id && !assignments.table) {
        assignments.table = settings.table_rule_profile_id;
        changed = true;
    }

    // historiography: historiographyRuleProfileId → assignments.historiography
    if (settings.historiographyRuleProfileId && !assignments.historiography) {
        assignments.historiography = settings.historiographyRuleProfileId;
        changed = true;
    }

    // condensation: condensation.ruleProfileId → assignments.condensation
    const condensation = settings.condensation || {};
    if (condensation.ruleProfileId && !assignments.condensation) {
        assignments.condensation = condensation.ruleProfileId;
        changed = true;
    }

    // queryPreprocessing: queryPreprocessing.ruleProfileId → assignments.queryPreprocessing
    const queryPreprocessing = settings.queryPreprocessing || {};
    if (queryPreprocessing.ruleProfileId && !assignments.queryPreprocessing) {
        assignments.queryPreprocessing = queryPreprocessing.ruleProfileId;
        changed = true;
    }

    if (changed) {
        saveSettingsDebounced();
        console.log('[RuleProfiles] 已迁移旧规则配置分配到统一 assignments。', assignments);
    }
})();

setTimeout(() => {
    try {
        const ctx = window.Amily2Bus?.register('RuleProfiles');
        if (!ctx) {
            console.warn('[RuleProfiles] Amily2Bus 尚未就绪，注册跳过。');
            return;
        }
        ctx.expose({
            listProfiles: () => ruleProfileManager.listProfiles(),
            getProfile: (id) => ruleProfileManager.getProfile(id),
            saveProfile: (profile) => ruleProfileManager.saveProfile(profile),
            deleteProfile: (id) => ruleProfileManager.deleteProfile(id),
            resolveProfile: (id, fallback) => ruleProfileManager.resolveProfile(id, fallback),
            getAssignment: (slot) => ruleProfileManager.getAssignment(slot),
            setAssignment: (slot, id) => ruleProfileManager.setAssignment(slot, id),
            getAssignedProfile: (slot) => ruleProfileManager.getAssignedProfile(slot),
            RULE_SLOTS,
        });
        ctx.log('RuleProfiles', 'info', 'RuleProfiles 服务已注册到 Bus。');
    } catch (error) {
        console.error('[RuleProfiles] Bus 注册失败:', error);
    }
}, 0);
