/*
|--------------------------------------------------------------------------
| Agência PSI
|--------------------------------------------------------------------------
| Arquivo: src/composables/useConversationTags.js
| Data: 2026-04-21
|
| Tags aplicáveis a threads de conversa (urgente, primeira consulta, etc).
| Combina tags do sistema (tenant_id NULL) com custom do tenant.
|--------------------------------------------------------------------------
*/

import { ref, computed } from 'vue';
import { supabase } from '@/lib/supabase/client';
import { tenantDb } from '@/lib/supabase/tenantClient';
import { useTenantStore } from '@/stores/tenantStore';

function sanitizeName(raw) {
    if (typeof raw !== 'string') return '';
    return raw.trim().slice(0, 40);
}

function toSlug(name) {
    return sanitizeName(name)
        .normalize('NFD').replace(/[̀-ͯ]/g, '')
        .toLowerCase()
        .replace(/[^a-z0-9]+/g, '-')
        .replace(/^-+|-+$/g, '')
        .slice(0, 40);
}

export function useConversationTags() {
    const tenantStore = useTenantStore();

    const allTags = ref([]);           // todas as tags disponíveis (system + custom)
    const threadTagIds = ref(new Set()); // tag_ids aplicados na thread atual
    const loading = ref(false);
    const saving = ref(false);

    const threadTags = computed(() =>
        allTags.value.filter((t) => threadTagIds.value.has(t.id))
    );

    // ── Carrega todas as tags visíveis (system + custom do tenant) ────
    async function loadAllTags() {
        const tenantId = tenantStore.activeTenantId;
        loading.value = true;
        try {
            // RLS filtra automaticamente: system (tenant_id IS NULL) + custom do tenant ativo
            const { data, error } = await tenantDb().from('conversation_tags')
                .select('id, name, slug, color, icon, position, is_system')
                .order('position', { ascending: true })
                .order('name', { ascending: true });
            if (error) throw error;
            allTags.value = data || [];
        } catch (e) {
            console.error('[useConversationTags] loadAllTags:', e?.message);
            allTags.value = [];
        } finally {
            loading.value = false;
        }
    }

    // ── Carrega tags aplicadas em MÚLTIPLAS threads (batch) ────
    // Retorna Map<thread_key, tag_id[]> pra renderização em Kanban
    async function loadForThreads(threadKeys) {
        const tenantId = tenantStore.activeTenantId;
        if (!tenantId || !Array.isArray(threadKeys) || !threadKeys.length) return new Map();
        try {
            const { data, error } = await tenantDb().from('conversation_thread_tags')
                .select('thread_key, tag_id')
                .in('thread_key', threadKeys);
            if (error) throw error;
            const map = new Map();
            for (const row of data || []) {
                if (!map.has(row.thread_key)) map.set(row.thread_key, []);
                map.get(row.thread_key).push(row.tag_id);
            }
            return map;
        } catch (e) {
            console.error('[useConversationTags] loadForThreads:', e?.message);
            return new Map();
        }
    }

    // ── Carrega tags aplicadas em uma thread ────
    async function loadForThread(threadKey) {
        const tenantId = tenantStore.activeTenantId;
        if (!tenantId || !threadKey) {
            threadTagIds.value = new Set();
            return;
        }
        try {
            const { data, error } = await tenantDb().from('conversation_thread_tags')
                .select('tag_id')
                .eq('thread_key', threadKey);
            if (error) throw error;
            threadTagIds.value = new Set((data || []).map((r) => r.tag_id));
        } catch (e) {
            console.error('[useConversationTags] loadForThread:', e?.message);
            threadTagIds.value = new Set();
        }
    }

    // ── Toggle: adiciona ou remove tag da thread ────
    async function toggleOnThread(threadKey, tagId) {
        const tenantId = tenantStore.activeTenantId;
        if (!tenantId || !threadKey || !tagId) return { ok: false, error: 'invalid_params' };

        saving.value = true;
        const hasTag = threadTagIds.value.has(tagId);

        try {
            if (hasTag) {
                const { error } = await tenantDb().from('conversation_thread_tags')
                    .delete()
                    .eq('thread_key', threadKey)
                    .eq('tag_id', tagId);
                if (error) throw error;
                const next = new Set(threadTagIds.value);
                next.delete(tagId);
                threadTagIds.value = next;
            } else {
                const { data: authData } = await supabase.auth.getUser();
                const userId = authData?.user?.id;
                if (!userId) return { ok: false, error: 'not_authenticated' };
                const { error } = await tenantDb().from('conversation_thread_tags')
                    .insert({
                        thread_key: threadKey,
                        tag_id: tagId,
                        tagged_by: userId
                    });
                if (error) throw error;
                const next = new Set(threadTagIds.value);
                next.add(tagId);
                threadTagIds.value = next;
            }
            return { ok: true, added: !hasTag };
        } catch (e) {
            return { ok: false, error: e?.message || 'toggle_failed' };
        } finally {
            saving.value = false;
        }
    }

    // ── Cria tag custom ────
    async function createCustomTag({ name, color = '#6366f1', icon = null }) {
        const tenantId = tenantStore.activeTenantId;
        const cleanName = sanitizeName(name);
        if (!tenantId || !cleanName) return { ok: false, error: 'invalid_params' };

        const slug = toSlug(cleanName);
        if (!slug) return { ok: false, error: 'invalid_slug' };

        saving.value = true;
        try {
            const { data, error } = await tenantDb().from('conversation_tags')
                .insert({
                    name: cleanName,
                    slug,
                    color,
                    icon,
                    is_system: false
                })
                .select('id, name, slug, color, icon, position, is_system')
                .single();
            if (error) throw error;
            allTags.value = [...allTags.value, data].sort((a, b) => (a.position - b.position) || a.name.localeCompare(b.name));
            return { ok: true, tag: data };
        } catch (e) {
            return { ok: false, error: e?.message || 'create_failed' };
        } finally {
            saving.value = false;
        }
    }

    // ── Atualiza tag custom ────
    async function updateCustomTag(id, { name, color, icon }) {
        if (!id) return { ok: false, error: 'invalid_id' };
        const patch = {};
        if (name !== undefined) {
            const clean = sanitizeName(name);
            if (!clean) return { ok: false, error: 'invalid_name' };
            patch.name = clean;
            patch.slug = toSlug(clean);
            if (!patch.slug) return { ok: false, error: 'invalid_slug' };
        }
        if (color !== undefined) patch.color = color;
        if (icon !== undefined) patch.icon = icon;
        if (!Object.keys(patch).length) return { ok: false, error: 'nothing_to_update' };

        saving.value = true;
        try {
            const { data, error } = await tenantDb().from('conversation_tags')
                .update(patch)
                .eq('id', id)
                .select('id, name, slug, color, icon, position, is_system')
                .single();
            if (error) throw error;
            allTags.value = allTags.value
                .map((t) => (t.id === id ? data : t))
                .sort((a, b) => (a.position - b.position) || a.name.localeCompare(b.name));
            return { ok: true, tag: data };
        } catch (e) {
            return { ok: false, error: e?.message || 'update_failed' };
        } finally {
            saving.value = false;
        }
    }

    // ── Remove tag custom (system bloqueada por RLS) ────
    async function deleteCustomTag(id) {
        if (!id) return { ok: false, error: 'invalid_id' };
        saving.value = true;
        try {
            const { error } = await tenantDb().from('conversation_tags').delete().eq('id', id);
            if (error) throw error;
            allTags.value = allTags.value.filter((t) => t.id !== id);
            const next = new Set(threadTagIds.value);
            next.delete(id);
            threadTagIds.value = next;
            return { ok: true };
        } catch (e) {
            return { ok: false, error: e?.message || 'delete_failed' };
        } finally {
            saving.value = false;
        }
    }

    function clear() {
        threadTagIds.value = new Set();
    }

    return {
        allTags,
        threadTags,
        threadTagIds,
        loading,
        saving,
        loadAllTags,
        loadForThread,
        loadForThreads,
        toggleOnThread,
        createCustomTag,
        updateCustomTag,
        deleteCustomTag,
        clear
    };
}
