import SwiftUI

struct VODLibraryView: View {
    @EnvironmentObject var appState: AppState
    @StateObject private var viewModel = VODLibraryViewModel()
    @State private var selectedVODItem: VODItem? = nil
    @State private var selectedCategory: Category? = nil
    @State private var showRecentReleasesDetail: Bool = false
    @FocusState private var focusedItem: String?

    // Cached data to avoid expensive recomputation
    @State private var cachedMovieGroupLookup: [String: MovieGroup] = [:]
    @State private var cachedCategoryGroups: [String: [MovieGroup]] = [:]
    @State private var lastPlaylistUpdate: Date?

    var allMovies: [VODItem] {
        appState.playlist?.vodItems.filter { $0.isMovie } ?? []
    }

    /// Get all versions for a given VODItem (uses cache)
    func allVersions(for item: VODItem) -> [VODItem] {
        cachedMovieGroupLookup[item.id]?.versions ?? [item]
    }

    var filteredMovies: [VODItem] {
        if viewModel.searchText.isEmpty {
            return VODItem.sortedByReleaseDate(allMovies, using: appState.tmdbReleaseDates)
        }
        return VODItem.sortedByReleaseDate(
            allMovies.filter { $0.name.localizedCaseInsensitiveContains(viewModel.searchText) },
            using: appState.tmdbReleaseDates
        )
    }

    /// Get deduplicated movies for category (uses cache)
    func groupedMoviesForCategory(_ categoryId: String) -> [MovieGroup] {
        cachedCategoryGroups[categoryId] ?? []
    }

    /// Rebuild caches when playlist changes
    /// Uses AppState's cached groups if available to avoid duplicate computation
    private func rebuildCachesIfNeeded() {
        guard let playlist = appState.playlist else { return }
        guard lastPlaylistUpdate != playlist.lastUpdated else { return }

        print("🎬 VODLibraryView: Rebuilding caches...")
        let startTime = Date()

        let movies = playlist.vodItems.filter { $0.isMovie }

        // Use AppState's cached groups if available, otherwise compute
        let groups: [MovieGroup]
        let lookup: [String: MovieGroup]

        if !appState.cachedMovieGroups.isEmpty && !appState.movieGroupLookup.isEmpty {
            // Reuse AppState's cached data (fast path)
            groups = appState.cachedMovieGroups
            lookup = appState.movieGroupLookup
            print("🎬 VODLibraryView: Using AppState's cached groups (\(groups.count) groups)")
        } else {
            // Compute groups if AppState hasn't done it yet (fallback)
            print("🎬 VODLibraryView: Computing groups (AppState cache empty)")
            groups = movies.groupedByTitle()

            var newLookup: [String: MovieGroup] = [:]
            newLookup.reserveCapacity(movies.count)
            for group in groups {
                for version in group.versions {
                    newLookup[version.id] = group
                }
            }
            lookup = newLookup
        }

        cachedMovieGroupLookup = lookup

        // Build category groups cache by distributing existing groups (fast)
        var categoryCache: [String: [MovieGroup]] = [:]
        categoryCache.reserveCapacity(playlist.categories.count)

        // Build reverse lookup: category -> set of MovieGroup ids
        var categoryGroupIds: [String: Set<String>] = [:]
        for movie in movies {
            guard let categoryId = movie.categoryID,
                  let group = lookup[movie.id] else { continue }
            categoryGroupIds[categoryId, default: []].insert(group.id)
        }

        // Convert group ids to sorted MovieGroup arrays (using cached release years)
        let groupById = Dictionary(uniqueKeysWithValues: groups.map { ($0.id, $0) })
        let cachedYears = appState.cachedReleaseYears

        for category in playlist.categories {
            if let groupIds = categoryGroupIds[category.id] {
                let categoryGroups = groupIds.compactMap { groupById[$0] }
                    .sorted { group1, group2 in
                        // Use pre-computed years from cache (fast)
                        let year1 = cachedYears[group1.id] ?? 0
                        let year2 = cachedYears[group2.id] ?? 0
                        if year1 != year2 {
                            return year1 > year2
                        }
                        return group1.name < group2.name
                    }
                categoryCache[category.id] = categoryGroups
            } else {
                categoryCache[category.id] = []
            }
        }
        cachedCategoryGroups = categoryCache

        lastPlaylistUpdate = playlist.lastUpdated
        print("🎬 VODLibraryView: Cache rebuilt in \(Date().timeIntervalSince(startTime))s")
    }

    var continueWatchingMovies: [WatchHistoryEntry] {
        appState.watchHistory.filter { $0.isMovie }
    }

    var allCategories: [Category] {
        appState.playlist?.categories ?? []
    }

    /// Categories sorted by year (newest first), then alphabetically
    var sortedCategories: [Category] {
        allCategories.sorted { cat1, cat2 in
            let year1 = cat1.year ?? 0
            let year2 = cat2.year ?? 0
            if year1 != year2 {
                return year1 > year2  // Newest year first
            }
            return cat1.name < cat2.name  // Alphabetical tiebreaker
        }
    }

    var featuredCategories: [Category] {
        // Get year-based categories (like "2025 Releases", "2024 Releases") sorted newest first
        let yearCategories = sortedCategories.filter { $0.year != nil && !$0.name.localizedCaseInsensitiveContains("24/7") }
        return Array(yearCategories.prefix(5))
    }

    var regularCategories: [Category] {
        sortedCategories.filter { !$0.name.localizedCaseInsensitiveContains("24/7") }
    }

    var liveCategories: [Category] {
        allCategories.filter { $0.name.localizedCaseInsensitiveContains("24/7") }
    }

    func moviesForCategory(_ categoryId: String) -> [VODItem] {
        // Get deduplicated movies from cache
        let groups = groupedMoviesForCategory(categoryId)
        let primaryItems = groups.map { $0.primaryItem }
        return VODItem.sortedByReleaseDate(primaryItems, using: appState.tmdbReleaseDates)
    }

    /// Trigger cache rebuild on playlist changes
    private func onPlaylistChange() {
        Task {
            await MainActor.run {
                rebuildCachesIfNeeded()
            }
        }
    }

    var isSearching: Bool {
        !viewModel.searchText.isEmpty
    }

    var body: some View {
        NavigationStack {
            ZStack {
                Color.black.ignoresSafeArea()

                if appState.isLoading {
                    LoadingView()
                } else if let error = appState.error {
                    ErrorView(error: error, onRetry: {
                        Task {
                            await appState.loadPlaylist(forceRefresh: true)
                        }
                    }, onDismiss: {
                        appState.clearError()
                    })
                } else if !allMovies.isEmpty {
                    ScrollView {
                        VStack(spacing: 40) {
                            headerView

                            if isSearching {
                                searchResultsView
                            } else {
                                browseView
                            }
                        }
                    }
                    .navigationDestination(item: $selectedVODItem) { item in
                        VODDetailView(vodItem: item, allVersions: allVersions(for: item))
                            .environmentObject(appState)
                    }
                    .navigationDestination(item: $selectedCategory) { category in
                        CategoryDetailView(
                            category: category,
                            movies: moviesForCategory(category.id)
                        )
                        .environmentObject(appState)
                    }
                    .navigationDestination(isPresented: $showRecentReleasesDetail) {
                        RecentReleasesDetailView(movies: appState.recentReleases)
                            .environmentObject(appState)
                    }
                } else {
                    emptyStateView
                }
            }
            .navigationTitle("")
            .toolbar(.hidden, for: .navigationBar)
            .onAppear {
                rebuildCachesIfNeeded()
            }
            .onChange(of: appState.playlist?.lastUpdated) { _, _ in
                onPlaylistChange()
            }
            .onChange(of: appState.cachedMovieGroups.count) { _, newCount in
                // Rebuild category caches when AppState's groups become available
                if newCount > 0 && cachedCategoryGroups.isEmpty {
                    lastPlaylistUpdate = nil  // Force rebuild
                    rebuildCachesIfNeeded()
                }
            }
        }
    }

    private var browseView: some View {
        VStack(spacing: 40) {
            // Continue Watching
            if !continueWatchingMovies.isEmpty {
                ContinueWatchingRow(entries: continueWatchingMovies) { entry in
                    if let vodItem = allMovies.first(where: { $0.id == entry.id }) {
                        selectedVODItem = vodItem
                    }
                }
            }

            // Recently Released (TMDB)
            if !appState.recentReleases.isEmpty {
                RecentReleasesRow(
                    movies: appState.recentReleases,
                    releaseDates: appState.tmdbReleaseDates,
                    onSeeAll: {
                        showRecentReleasesDetail = true
                    },
                    onSelectMovie: { movie in
                        selectedVODItem = movie
                    }
                )
            }

            // Featured Category Rows
            ForEach(featuredCategories) { category in
                let categoryMovies = moviesForCategory(category.id)
                if !categoryMovies.isEmpty {
                    FeaturedCategoryRow(
                        category: category,
                        movies: categoryMovies,
                        releaseDates: appState.tmdbReleaseDates,
                        onSeeAll: {
                            selectedCategory = category
                        },
                        onSelectMovie: { movie in
                            selectedVODItem = movie
                        }
                    )
                }
            }

            // Browse Categories Row
            if !regularCategories.isEmpty {
                CategoryCardsRow(categories: regularCategories, title: "Browse Categories") { category in
                    selectedCategory = category
                }
                .padding(.bottom, liveCategories.isEmpty ? 60 : 0)
            }

            // 24/7 Live Categories Row
            if !liveCategories.isEmpty {
                CategoryCardsRow(categories: liveCategories, title: "24/7 Channels") { category in
                    selectedCategory = category
                }
                .padding(.bottom, 60)
            }
        }
    }

    private var searchResultsView: some View {
        VStack(spacing: 20) {
            HStack {
                Text("\(filteredMovies.count) results for \"\(viewModel.searchText)\"")
                    .font(.title3)
                    .foregroundColor(.gray)
                Spacer()
            }
            .padding(.horizontal, 80)

            let columns = Array(repeating: GridItem(.flexible(), spacing: Constants.UI.vodGridSpacing), count: Constants.UI.vodGridColumns)

            LazyVGrid(columns: columns, spacing: Constants.UI.vodGridSpacing) {
                ForEach(filteredMovies) { item in
                    Button {
                        selectedVODItem = item
                    } label: {
                        VODCardView(
                            vodItem: item,
                            isFocused: focusedItem == item.id,
                            releaseDate: appState.tmdbReleaseDates[item.id]
                        )
                    }
                    .buttonStyle(.plain)
                    .focused($focusedItem, equals: item.id)
                }
            }
            .padding(.horizontal, 80)
            .padding(.bottom, 60)
        }
    }

    private var headerView: some View {
        VStack(spacing: 25) {
            HStack(spacing: 20) {
                Text("Movies")
                    .font(.system(size: 60, weight: .bold))
                    .foregroundColor(.white)

                Spacer()

                SearchBar(text: $viewModel.searchText, placeholder: "Search movies...")
                    .frame(width: 400)

                Button(action: {
                    Task {
                        await appState.loadPlaylist(forceRefresh: true)
                    }
                }) {
                    Image(systemName: "arrow.clockwise")
                        .font(.title3)
                        .foregroundColor(.white)
                        .padding()
                        .background(Color.white.opacity(0.1))
                        .cornerRadius(10)
                }

                if appState.isDevelopmentMode {
                    Button(action: {
                        Task {
                            await appState.clearWatchHistory()
                        }
                    }) {
                        Image(systemName: "trash")
                            .font(.title3)
                            .foregroundColor(.white)
                            .padding()
                            .background(Color.orange.opacity(0.3))
                            .cornerRadius(10)
                    }
                }

                Button(action: {
                    Task {
                        await appState.logout()
                    }
                }) {
                    HStack {
                        Image(systemName: "rectangle.portrait.and.arrow.right")
                        Text("Logout")
                    }
                    .font(.title3)
                    .foregroundColor(.white)
                    .padding()
                    .background(Color.red.opacity(0.3))
                    .cornerRadius(10)
                }
            }
            .padding(.horizontal, 80)
            .padding(.top, 60)
        }
    }

    private var emptyStateView: some View {
        VStack(spacing: 30) {
            Image(systemName: "film")
                .font(.system(size: 100))
                .foregroundColor(.gray)

            Text("No Movies Available")
                .font(.title)
                .foregroundColor(.white)

            Text("Pull down to refresh or check back later")
                .font(.title3)
                .foregroundColor(.gray)

            Button("Refresh") {
                Task {
                    await appState.loadPlaylist(forceRefresh: true)
                }
            }
            .buttonStyle(.plain)
            .padding()
            .background(Color.blue)
            .cornerRadius(10)
            .foregroundColor(.white)
        }
    }
}

#Preview {
    VODLibraryView()
        .environmentObject(AppState(developmentMode: true))
}
