import { ref, computed, watch, type Ref } from 'vue';
import type { ChannelState } from '../store/chat';
import { getApiBase } from '../utils/apiBase';

interface ServerConfig {
    defaultAgent?: string;
    allowedAgents?: string[];
    agents?: Agent[];
}

interface ChannelInfo {
    state: ChannelState;
    connections: number;
    handoverActive: boolean;
    activeTurnId: string | null;
}

export interface Agent {
    id: string;
    name: string;
    model?: string;
    modelFull?: string;
    modelName?: string;
    promptPrice: number | null;
    completionPrice: number | null;
    segment?: string;   // 'personal' | 'common' | 'utility'
    role?: string;      // 'owner' | 'member' | 'common' | 'guest' | 'utility'
    modes?: string[];   // ['private', 'public'] | ['private'] | ['public']
}

// These are refs so they can be watched and reacted to by Vue components
const _allAgents: Ref<Agent[]> = ref([]);
// Restore agent from URL or sessionStorage at init (before WS auth fires)
const _initAgent = (() => {
    const url = new URLSearchParams(window.location.hash.split('?')[1] || '').get('agent');
    if (url) return url;
    const saved = sessionStorage.getItem('agent');
    if (saved) return saved;
    return ''; // truly first visit — server will provide default via ready message
})();
const _selectedAgent: Ref<string> = ref(_initAgent);
// Restore mode from URL or sessionStorage at init (before WS auth fires)
const _initMode = (() => {
    const url = new URLSearchParams(window.location.hash.split('?')[1] || '').get('mode');
    if (url === 'public' || url === 'private') return url;
    const saved = sessionStorage.getItem('agent_mode');
    if (saved === 'public' || saved === 'private') return saved;
    return 'private';
})();
const _selectedMode: Ref<'private' | 'public'> = ref(_initMode as 'private' | 'public');
const _defaultAgent: Ref<string> = ref('titan'); // Default fallback
const _allowedAgentIds: Ref<string[]> = ref([]); // List of agent IDs allowed for the current user

export function useAgents(connected: Ref<boolean>) {
    // --- State --- //
    const allAgents = _allAgents;
    const selectedAgent = _selectedAgent;
    const selectedMode = _selectedMode;
    const defaultAgent = _defaultAgent;
    const allowedAgentIds = _allowedAgentIds;

    const agentModels: Ref<any[]> = ref([]); // Assuming agent models can be of any type for now

    // --- Computed --- //
    const filteredAgents = computed(() => {
        if (allowedAgentIds.value.length === 0) return allAgents.value;
        return allAgents.value.filter(a => allowedAgentIds.value.includes(a.id));
    });

    // --- Actions --- //

    /**
     * Called when the server sends new config (e.g., on auth_ok or ready message).
     * Updates agent list, allowed agents, and attempts to set a default selected agent.
     */
    function updateFromServer(data: ServerConfig): void {
        if (data.agents) {
            allAgents.value = data.agents;
        }
        if (data.defaultAgent) {
            _defaultAgent.value = data.defaultAgent;
        }
        if (data.allowedAgents) {
            _allowedAgentIds.value = data.allowedAgents;
        }

        // Restore mode: URL ?mode= > sessionStorage > default 'private'
        const urlParams = new URLSearchParams(window.location.hash.split('?')[1] || '');
        const urlMode = urlParams.get('mode');
        const savedMode = sessionStorage.getItem('agent_mode');
        if (urlMode === 'public' || urlMode === 'private') {
            _selectedMode.value = urlMode;
        } else if (savedMode === 'public' || savedMode === 'private') {
            _selectedMode.value = savedMode;
        }

        // Set selected agent:
        // 1. From ?agent= URL param if valid and allowed.
        // 2. From sessionStorage if valid and allowed.
        // 3. Leave empty — NO_AGENT_SELECTED state, user must pick.
        const urlAgent = urlParams.get('agent');
        const savedAgent = sessionStorage.getItem('agent');
        const isUrlAgentAllowed = urlAgent && _allowedAgentIds.value.includes(urlAgent);
        const isSavedAgentAllowed = savedAgent && _allowedAgentIds.value.includes(savedAgent);

        if (isUrlAgentAllowed) {
            selectedAgent.value = urlAgent as string;
        } else if (isSavedAgentAllowed) {
            selectedAgent.value = savedAgent as string;
        }
        // else: leave selectedAgent empty — AgentsView shows agent picker
    }

    async function fetchAgentModels(): Promise<void> {
        try {
            const protocol = window.location.protocol === 'https:' ? 'https:' : 'http:';
            const host = window.location.hostname;
            // Use the HTTP /agents endpoint for full models list if needed, but current /dev uses WS for stats.
            // This function might be redundant if all agent info comes from WS 'config' or 'stats' messages.
            const sessionToken = localStorage.getItem('nyx_session') ?? '';
            const res = await fetch(`${protocol}//${host}/agents`, {
                headers: { Authorization: `Bearer ${sessionToken}` },
            });
            agentModels.value = await res.json();
        } catch (e) {
            console.error('Failed to fetch agent models:', e);
        }
    }

    // Attempt to set a default agent initially, and whenever allowed agents change.
    // Note: this might trigger before updateFromServer if localStorage has an old agent value.
    // updateFromServer should be the primary setter.
    watch([connected, _allowedAgentIds], () => {
        if (connected.value && !_selectedAgent.value) {
            // Only run if connected and no agent is currently selected
            updateFromServer({}); // Pass empty to trigger default agent logic
        }
    });


    // --- Channel state polling (round-robin, one agent per tick) --- //
    // Map: agentId → { private: ChannelInfo, public: ChannelInfo }
    const channelStates = ref<Record<string, { private: ChannelInfo | null; public: ChannelInfo | null }>>({});
    let _pollTimer: ReturnType<typeof setInterval> | null = null;
    let _pollIdx = 0;

    async function fetchOneAgent(agentId: string): Promise<void> {
        const sessionToken = localStorage.getItem('nyx_session') ?? '';
        if (!sessionToken) return;
        try {
            const apiBase = getApiBase();
            const res = await fetch(`${apiBase}/api/channels/${agentId}`, {
                headers: { Authorization: `Bearer ${sessionToken}` },
            });
            if (!res.ok) return;
            const data = await res.json();
            channelStates.value = {
                ...channelStates.value,
                [agentId]: {
                    private: data.private ?? null,
                    public: data.public ?? null,
                },
            };
        } catch {
            // Silent
        }
    }

    function pollNextAgent() {
        const agents = allAgents.value;
        if (!agents.length) return;
        _pollIdx = _pollIdx % agents.length;
        fetchOneAgent(agents[_pollIdx].id);
        _pollIdx++;
    }

    function startChannelPolling() {
        if (_pollTimer) return;
        _pollIdx = 0;
        pollNextAgent(); // immediate first
        _pollTimer = setInterval(pollNextAgent, 1000); // 1 agent per second
    }

    function stopChannelPolling() {
        if (_pollTimer) { clearInterval(_pollTimer); _pollTimer = null; }
    }

    // Helper: get channel state for an agent by id + mode
    function getChannelState(agentId: string, mode: 'private' | 'public'): ChannelInfo | null {
        const entry = channelStates.value[agentId];
        if (!entry) return null;
        return mode === 'private' ? entry.private : entry.public;
    }

    let currentUserRef: Ref<string> | null = null;
    function setCurrentUser(userRef: Ref<string>) { currentUserRef = userRef; }

    // Channel state polling disabled — indicators removed from sidebar in 0.6.45
    // Keeping the functions for future use if needed.
    // watch(connected, (val) => {
    //     if (val) startChannelPolling();
    //     else stopChannelPolling();
    // }, { immediate: true });

    // Keep sessionStorage in sync with agent + mode (URL managed by router)
    function syncStorage() {
        if (_selectedAgent.value) sessionStorage.setItem('agent', _selectedAgent.value);
        sessionStorage.setItem('agent_mode', _selectedMode.value);
    }
    watch([_selectedAgent, _selectedMode], syncStorage);

    return {
        allAgents, selectedAgent, selectedMode, defaultAgent, allowedAgentIds,
        agentModels, filteredAgents, channelStates,
        fetchAgentModels, updateFromServer, getChannelState, setCurrentUser,
        startChannelPolling, stopChannelPolling,
    };
}
