import { state } from './state.js';
import { getFromDB, clearStore, addItemsToStore } from './db.js';
import { showNotification, _ } from './utils.js';
import { switchView, showItemDetails, addStreamToList, downloadM3U, generateStatistics, toggleFavorite, loadRecommendations, applyFilters as applyUIFilters, clearAllFavorites, clearRecommendations, loadInitialContent, loadContent, clearAllHistory } from './ui.js';
import { fetchTMDB } from './api.js';
import { updateAllTokens, addPlexToken } from './plex.js';
import { config } from './config.js';

export class AITools {
    constructor(chatInstance) {
        this.chat = chatInstance;
        this.genreCache = { movie: null, tv: null };
    }

    get toolDefinitions() {
        return [
            {
                type: 'function',
                function: {
                    name: 'search_library',
                    description: _('aiToolSearchLibraryDesc'),
                    parameters: {
                        type: 'object',
                        properties: {
                            query: { type: 'string', description: _('aiToolSearchLibraryQueryDesc') },
                            type: { type: 'string', enum: ['movie', 'series'], description: _('aiToolSearchLibraryTypeDesc') }
                        },
                        required: ['query']
                    }
                }
            },
            {
                type: 'function',
                function: {
                    name: 'navigate_to_page',
                    description: _('aiToolNavigateToPageDesc'),
                    parameters: {
                        type: 'object',
                        properties: {
                            page: {
                                type: 'string',
                                enum: ['movies', 'series', 'stats', 'favorites', 'history', 'recommendations', 'photos', 'providers', 'm3u-generator'],
                                description: _('aiToolNavigateToPagePageDesc')
                            }
                        },
                        required: ['page']
                    }
                }
            },
            {
                type: 'function',
                function: {
                    name: 'get_user_stats',
                    description: _('aiToolGetUserStatsDesc'),
                    parameters: { type: 'object', properties: {} }
                }
            },
            {
                type: 'function',
                function: {
                    name: 'show_item_details',
                    description: _('aiToolShowItemDetailsDesc'),
                    parameters: {
                        type: 'object',
                        properties: {
                            title: { type: 'string', description: _('aiToolShowItemDetailsTitleDesc') },
                            type: { type: 'string', enum: ['movie', 'series'], description: _('aiToolShowItemDetailsTypeDesc') }
                        },
                        required: ['title', 'type']
                    }
                }
            },
            {
                type: 'function',
                function: {
                    name: 'add_to_playlist',
                    description: _('aiToolAddToPlaylistDesc'),
                    parameters: {
                        type: 'object',
                        properties: {
                            title: { type: 'string', description: _('aiToolAddToPlaylistTitleDesc') },
                            type: { type: 'string', enum: ['movie', 'series'], description: _('aiToolAddToPlaylistTypeDesc') }
                        },
                        required: ['title', 'type']
                    }
                }
            },
            {
                type: 'function',
                function: {
                    name: 'check_and_download_titles_list',
                    description: _('aiToolCheckAndDownloadDesc'),
                    parameters: {
                        type: 'object',
                        properties: {
                            titles: {
                                type: 'array',
                                items: { type: 'string' },
                                description: _('aiToolGenerateM3UFromTitlesTitlesDesc')
                            },
                            type: {
                                type: 'string',
                                enum: ['movie', 'series'],
                                description: _('aiToolGenerateM3UTypeDesc')
                            },
                            filename: { type: 'string', description: _('aiToolGenerateM3UFilenameDesc') }
                        },
                        required: ['titles', 'type']
                    }
                }
            },
            {
                type: 'function',
                function: {
                    name: 'toggle_favorite',
                    description: _('aiToolToggleFavoriteDesc'),
                    parameters: {
                        type: 'object',
                        properties: {
                            title: { type: 'string', description: _('aiToolToggleFavoriteTitleDesc') },
                            type: { type: 'string', enum: ['movie', 'series'], description: _('aiToolToggleFavoriteTypeDesc') }
                        },
                        required: ['title', 'type']
                    }
                }
            },
            {
                type: 'function',
                function: {
                    name: 'get_recommendations',
                    description: _('aiToolGetRecommendationsDesc'),
                    parameters: { type: 'object', properties: {} }
                }
            },
            {
                type: 'function',
                function: {
                    name: 'apply_filters',
                    description: _('aiToolApplyFiltersDesc'),
                    parameters: {
                        type: 'object',
                        properties: {
                            type: { type: 'string', enum: ['movie', 'series'], description: _('aiToolApplyFiltersTypeDesc') },
                            genre: { type: 'string', description: _('aiToolApplyFiltersGenreDesc') },
                            year: { type: 'string', description: _('aiToolApplyFiltersYearDesc') },
                            sort: { type: 'string', enum: ['popularity.desc', 'vote_average.desc', 'release_date.desc', 'first_air_date.desc'], description: _('aiToolApplyFiltersSortDesc') }
                        },
                        required: ['type']
                    }
                }
            },
            {
                type: 'function',
                function: {
                    name: 'play_music_by_artist',
                    description: _('aiToolPlayMusicByArtistDesc'),
                    parameters: {
                        type: 'object',
                        properties: {
                            artist_name: { type: 'string', description: _('aiToolPlayMusicByArtistNameDesc') }
                        },
                        required: ['artist_name']
                    }
                }
            },
            {
                type: 'function',
                function: {
                    name: 'clear_chat_history',
                    description: _('aiToolClearChatHistoryDesc'),
                    parameters: { type: 'object', properties: {} }
                }
            },
            {
                type: 'function',
                function: {
                    name: 'delete_database',
                    description: _('aiToolDeleteDatabaseDesc'),
                    parameters: { type: 'object', properties: {} }
                }
            },
            {
                type: 'function',
                function: {
                    name: 'update_all_tokens',
                    description: _('aiToolUpdateAllTokensDesc'),
                    parameters: { type: 'object', properties: {} }
                }
            },
            {
                type: 'function',
                function: {
                    name: 'add_plex_token',
                    description: _('aiToolAddPlexTokenDesc'),
                    parameters: {
                        type: 'object',
                        properties: {
                            token: { type: 'string', description: _('aiToolAddPlexTokenTokenDesc') }
                        },
                        required: ['token']
                    }
                }
            },
            {
                type: 'function',
                function: {
                    name: 'change_region',
                    description: _('aiToolChangeRegionDesc'),
                    parameters: {
                        type: 'object',
                        properties: {
                            region: { type: 'string', description: _('aiToolChangeRegionRegionDesc') }
                        },
                        required: ['region']
                    }
                }
            },
            {
                type: 'function',
                function: {
                    name: 'clear_all_favorites',
                    description: _('aiToolClearAllFavoritesDesc'),
                    parameters: { type: 'object', properties: {} }
                }
            },
            {
                type: 'function',
                function: {
                    name: 'clear_viewing_history',
                    description: "Clears the user's content viewing history from the history page.",
                    parameters: { type: 'object', properties: {} }
                }
            },
            {
                type: 'function',
                function: {
                    name: 'clear_recommendations_view',
                    description: _('aiToolClearRecommendationsViewDesc'),
                    parameters: { type: 'object', properties: {} }
                }
            }
        ];
    }

    async "search_library"({ query, type }) {
        const movieEntries = await getFromDB('movies');
        const seriesEntries = await getFromDB('series');
        const allContent = [
            ...movieEntries.flatMap(e => (e.titulos || []).map(t => ({ ...t, type: 'movie' }))),
            ...seriesEntries.flatMap(e => (e.titulos || []).map(t => ({ ...t, type: 'series' })))
        ];
        const searchTerm = query.toLowerCase().trim();
        let results = allContent.filter(item => item.title.toLowerCase().includes(searchTerm));
        if (type) {
            results = results.filter(item => item.type === type);
        }
        if (results.length === 0) {
            return JSON.stringify({ success: false, message: _('aiToolSearchNotFound', query) });
        }
        const formattedResults = results.slice(0, 10).map(item => ({ title: item.title, year: item.year, type: item.type }));
        return JSON.stringify({ success: true, count: results.length, results: formattedResults });
    }

    "navigate_to_page"({ page }) {
        try {
            switchView(page);
            return JSON.stringify({ success: true, message: _('aiToolNavigateSuccess', page) });
        } catch (error) {
            return JSON.stringify({ success: false, message: _('aiToolNavigateError', page) });
        }
    }

    async "get_user_stats"() {
        try {
            const movieItems = (await getFromDB('movies')).flatMap(s => s.titulos);
            const seriesItems = (await getFromDB('series')).flatMap(s => s.titulos);
            const artistItems = (await getFromDB('artists')).flatMap(s => s.titulos);
            const stats = {
                totalMovies: new Set(movieItems.map(item => item.title)).size,
                totalSeries: new Set(seriesItems.map(item => item.title)).size,
                totalArtists: new Set(artistItems.map(item => item.title)).size,
            };
            switchView('stats');
            return JSON.stringify({ success: true, stats });
        } catch (error) {
            return JSON.stringify({ success: false, message: _('aiToolStatsError') });
        }
    }

    async "show_item_details"({ title, type }) {
        const content = await this.findTmdbContent(title, type);
        if (!content) {
            return JSON.stringify({ success: false, message: _('aiToolItemNotFound', title) });
        }
        showItemDetails(Number(content.id), content.type);
        return JSON.stringify({ success: true, message: _('aiToolShowItemDetailsSuccess', title) });
    }

    async "add_to_playlist"({ title, type }) {
        const content = await this.findLocalContent(title, type);
        if (!content) {
            return JSON.stringify({ success: false, message: _('aiToolItemNotFound', title) });
        }
        addStreamToList(content.title, content.type);
        return JSON.stringify({ success: true, message: _('aiToolAddToPlaylistSuccess', title) });
    }

    async "check_and_download_titles_list"({ titles, type, filename }) {
        try {
            if (!titles || titles.length === 0) {
                return JSON.stringify({ success: false, message: _('aiToolM3UNoTitlesProvided') });
            }

            showNotification(_('aiToolM3UCheckingTitles'), 'info');

            const plexStore = type === 'movie' ? 'movies' : 'series';
            const jellyfinStore = type === 'movie' ? 'jellyfin_movies' : 'jellyfin_series';

            const plexContent = await getFromDB(plexStore);
            const jellyfinContent = await getFromDB(jellyfinStore);

            const allLocalItems = [
                ...plexContent.flatMap(server => server.titulos || []),
                ...jellyfinContent.flatMap(lib => lib.titulos || [])
            ];

            const normalize = (str) => str ? str.toLowerCase().trim().replace(/[^a-z0-9]/g, '') : '';
            const normalizedTitlesFromAI = new Set(titles.map(normalize));

            const matchedItems = [];
            const seenTitles = new Set();
            
            for (const localItem of allLocalItems) {
                const normalizedLocalTitle = normalize(localItem.title);
                if (normalizedTitlesFromAI.has(normalizedLocalTitle) && !seenTitles.has(normalizedLocalTitle)) {
                    matchedItems.push({ title: localItem.title, type });
                    seenTitles.add(normalizedLocalTitle);
                }
            }

            if (matchedItems.length === 0) {
                return JSON.stringify({ success: true, message: _('aiToolM3UNoLocalMatchesForDownload') });
            }
            
            downloadM3U(matchedItems, null, filename);

            return JSON.stringify({ success: true, message: _('aiToolM3UDownloadStarted', [String(matchedItems.length), String(titles.length)]) });

        } catch (error) {
            return JSON.stringify({ success: false, message: `Error creating playlist: ${error.message}` });
        }
    }

    async "toggle_favorite"({ title, type }) {
        const item = await this.findTmdbContent(title, type);
        if (!item) {
            return JSON.stringify({ success: false, message: _('aiToolItemNotFound', title) });
        }
        toggleFavorite(item.id, type);
        const isFavorite = state.favorites.some(fav => fav.id === item.id && fav.type === type);
        const message = isFavorite ? _('aiToolFavoriteAdded', title) : _('aiToolFavoriteRemoved', title);
        return JSON.stringify({ success: true, message });
    }

    async "get_recommendations"() {
        switchView('recommendations');
        return JSON.stringify({ success: true, message: _('aiToolRecommendationsSuccess') });
    }

    async "apply_filters"({ type, genre, year, sort }) {
        switchView(type === 'movie' ? 'movies' : 'series');
        let genreId = '';
        if (genre) {
            genreId = await this.getGenreId(genre, type);
            if (!genreId) {
                return JSON.stringify({ success: false, message: _('aiToolApplyFiltersGenreNotFound', genre) });
            }
        }
        state.currentParams.genre = genreId;
        state.currentParams.year = year || '';
        state.currentParams.sort = sort || 'popularity.desc';
        applyUIFilters();
        return JSON.stringify({ success: true, message: _('aiToolApplyFiltersSuccess') });
    }

    async "play_music_by_artist"({ artist_name }) {
        if (!state.musicPlayer || !state.musicPlayer.isReady) {
            return JSON.stringify({ success: false, message: _('aiToolPlayMusicNotReady') });
        }
        const allArtists = state.musicPlayer._generateFullArtistListForToken('all');
        const searchTerm = artist_name.toLowerCase().trim();
        const artist = allArtists.find(a => a.title.toLowerCase() === searchTerm);
        if (!artist) {
            return JSON.stringify({ success: false, message: _('aiToolPlayMusicArtistNotFound', artist_name) });
        }
        state.musicPlayer.showPlayer();
        const songs = await state.musicPlayer.getArtistSongs(artist);
        if (!songs || songs.length === 0) {
            return JSON.stringify({ success: false, message: _('aiToolPlayMusicNoSongs', artist_name) });
        }
        state.musicPlayer.cancionesActuales = songs;
        state.musicPlayer.playSong(0);
        return JSON.stringify({ success: true, message: _('aiToolPlayMusicSuccess', artist_name) });
    }

    async "clear_chat_history"() {
        try {
            this.chat.clearHistory();
            return JSON.stringify({ success: true, message: _('aiToolChatHistoryCleared') });
        } catch (error) {
            return JSON.stringify({ success: false, message: _('aiToolChatHistoryClearError', error.message) });
        }
    }

    async "delete_database"() {
        try {
            if (confirm(_('aiToolConfirmDeleteDatabase'))) {
                if (state.db) {
                    state.db.close();
                }
                const deleteRequest = indexedDB.deleteDatabase(config.dbName);
                return new Promise((resolve) => {
                    deleteRequest.onsuccess = () => {
                        setTimeout(() => window.location.reload(), 1500);
                        resolve(JSON.stringify({ success: true, message: _('aiToolDatabaseDeleted') }));
                    };
                    deleteRequest.onerror = (event) => {
                        resolve(JSON.stringify({ success: false, message: _('aiToolDatabaseDeleteError', event.target.error) }));
                    };
                    deleteRequest.onblocked = () => {
                        resolve(JSON.stringify({ success: false, message: _('aiToolDatabaseDeleteBlocked') }));
                    };
                });
            } else {
                return JSON.stringify({ success: false, message: _('aiToolDeleteDatabaseCancelled') });
            }
        } catch (error) {
            return JSON.stringify({ success: false, message: _('aiToolDatabaseDeleteError', error.message) });
        }
    }

    async "update_all_tokens"() {
        try {
            await updateAllTokens();
            return JSON.stringify({ success: true, message: _('aiToolUpdateAllTokensSuccess') });
        } catch (error) {
            return JSON.stringify({ success: false, message: _('aiToolUpdateAllTokensError', error.message) });
        }
    }

    async "add_plex_token"({ token }) {
        try {
            await addPlexToken(token);
            return JSON.stringify({ success: true, message: _('aiToolAddPlexTokenSuccess') });
        } catch (error) {
            return JSON.stringify({ success: false, message: _('aiToolAddPlexTokenError', error.message) });
        }
    }

    async "change_region"({ region }) {
        try {
            state.settings.watchRegion = region;
            await addItemsToStore('settings', [{ id: 'user_settings', ...state.settings }]);
            await loadInitialContent();
            if (['movies', 'series', 'search'].includes(state.currentView)) {
                await loadContent();
            }
            return JSON.stringify({ success: true, message: _('aiToolChangeRegionSuccess', region) });
        } catch (error) {
            return JSON.stringify({ success: false, message: _('aiToolChangeRegionError', error.message) });
        }
    }

    async "clear_all_favorites"() {
        try {
            clearAllFavorites();
            return JSON.stringify({ success: true, message: _('aiToolFavoritesCleared') });
        } catch (error) {
            return JSON.stringify({ success: false, message: _('aiToolFavoritesClearError', error.message) });
        }
    }

    async "clear_viewing_history"() {
        try {
            clearAllHistory();
            return JSON.stringify({ success: true, message: "Viewing history has been cleared." });
        } catch (error) {
            return JSON.stringify({ success: false, message: `Failed to clear viewing history: ${error.message}` });
        }
    }

    async "clear_recommendations_view"() {
        try {
            clearRecommendations();
            return JSON.stringify({ success: true, message: _('aiToolRecommendationsCleared') });
        } catch (error) {
            return JSON.stringify({ success: false, message: _('aiToolRecommendationsClearError', error.message) });
        }
    }

    async findLocalContent(title, type) {
        const movieEntries = await getFromDB('movies');
        const seriesEntries = await getFromDB('series');
        const allContent = [
            ...movieEntries.flatMap(e => (e.titulos || []).map(t => ({ ...t, type: 'movie' }))),
            ...seriesEntries.flatMap(e => (e.titulos || []).map(t => ({ ...t, type: 'series' })))
        ];
        const searchTerm = title.toLowerCase().trim();
        return allContent.find(item => item.title.toLowerCase() === searchTerm && (!type || item.type === type));
    }

    async findTmdbContent(title, type) {
        try {
            const searchResults = await fetchTMDB(`search/${type}?query=${encodeURIComponent(title)}`);
            if (searchResults && searchResults.results.length > 0) {
                const item = searchResults.results[0];
                return { id: item.id, type };
            }
            return null;
        } catch (error) {
            return null;
        }
    }

    async getGenreId(genreName, type) {
        if (!this.genreCache[type]) {
            try {
                const data = await fetchTMDB(`genre/${type}/list`);
                this.genreCache[type] = data.genres;
            } catch (error) {
                return null;
            }
        }
        const genre = this.genreCache[type].find(g => g.name.toLowerCase() === genreName.toLowerCase());
        return genre ? genre.id : null;
    }

    async executeTool(toolCall) {
        const functionName = toolCall.function.name;
        const args = JSON.parse(toolCall.function.arguments);

        if (typeof this[functionName] === 'function') {
            this.chat.addTypingIndicator();
            try {
                const result = await this[functionName](args);
                return result;
            } catch (error) {
                const errorMessage = _('aiToolExecutionError', functionName, error.message);
                this.chat.addMessage(errorMessage, 'tool-result', true, functionName);
                return JSON.stringify({ success: false, error: errorMessage });
            } finally {
                this.chat.removeTypingIndicator();
            }
        } else {
            const errorMessage = _('aiToolUnknown', functionName);
            this.chat.addMessage(errorMessage, 'tool-result', true, functionName);
            return JSON.stringify({ success: false, error: errorMessage });
        }
    }
}