//
//  LibraryView.swift
//  Sora
//
//  Created by Francesco on 05/01/25.
//

import Kingfisher
import SwiftUI

struct LibraryView: View {
    @EnvironmentObject private var libraryManager: LibraryManager
    @EnvironmentObject private var continueWatchingManager: ContinueWatchingManager
    @EnvironmentObject private var moduleManager: ModuleManager
    @EnvironmentObject private var profileStore: ProfileStore

    @AppStorage("hideEmptySections") private var hideEmptySections: Bool?
    @AppStorage("mediaColumnsPortrait") private var mediaColumnsPortrait = 2
    @AppStorage("mediaColumnsLandscape") private var mediaColumnsLandscape = 4

    @Environment(\.verticalSizeClass) var verticalSizeClass

    @State private var selectedBookmark: LibraryItem?
    @State private var isDetailActive = false

    @State private var continueWatchingItems: [ContinueWatchingItem] = []
    @State private var isLandscape: Bool = UIDevice.current.orientation.isLandscape
    @State private var showProfileSettings = false

    private let columns = [
        GridItem(.adaptive(minimum: 150), spacing: 12)
    ]

    private var columnsCount: Int {
        if UIDevice.current.userInterfaceIdiom == .pad {
            let isLandscape = UIScreen.main.bounds.width > UIScreen.main.bounds.height
            return isLandscape ? mediaColumnsLandscape : mediaColumnsPortrait
        } else {
            return verticalSizeClass == .compact ? mediaColumnsLandscape : mediaColumnsPortrait
        }
    }

    private var cellWidth: CGFloat {
        let keyWindow = UIApplication.shared.connectedScenes
            .compactMap { ($0 as? UIWindowScene)?.windows.first(where: { $0.isKeyWindow }) }
            .first
        let safeAreaInsets = keyWindow?.safeAreaInsets ?? .zero
        let safeWidth = UIScreen.main.bounds.width - safeAreaInsets.left - safeAreaInsets.right
        let totalSpacing: CGFloat = 16 * CGFloat(columnsCount + 1)
        let availableWidth = safeWidth - totalSpacing
        return availableWidth / CGFloat(columnsCount)
    }

    var body: some View {
        NavigationView {
            ScrollView {
                VStack(alignment: .leading, spacing: 12) {
                    if hideEmptySections != true || !continueWatchingManager.items.isEmpty {
                        Text("Continue Watching")
                            .font(.title2)
                            .bold()
                            .padding(.horizontal, 20)
                    }

                    if !(hideEmptySections ?? false) && continueWatchingManager.items.isEmpty {
                        VStack(spacing: 8) {
                            Image(systemName: "play.circle")
                                .font(.largeTitle)
                                .foregroundColor(.secondary)
                                .accessibilityLabel("Play Icon")
                            Text("No items to continue watching.")
                                .font(.headline)
                            Text("Recently watched content will appear here.")
                                .font(.caption)
                                .foregroundColor(.secondary)
                        }
                        .padding()
                        .frame(maxWidth: .infinity)
                    } else {
                        ContinueWatchingSection(items: $continueWatchingManager.items, markAsWatched: { item in
                            markContinueWatchingItemAsWatched(item: item)
                        }, removeItem: { item in
                            removeContinueWatchingItem(item: item)
                        })
                    }

                    if hideEmptySections != true || !libraryManager.bookmarks.isEmpty {
                        Text("Bookmarks")
                            .font(.title2)
                            .bold()
                            .padding(.horizontal, 20)
                    }

                    if !(hideEmptySections ?? false) && libraryManager.bookmarks.isEmpty {
                        VStack(spacing: 8) {
                            Image(systemName: "magazine")
                                .font(.largeTitle)
                                .foregroundColor(.secondary)
                                .accessibilityLabel("Magazine Icon")
                            Text("You have no items saved.")
                                .font(.headline)
                            Text("Bookmark items for an easier access later.")
                                .font(.caption)
                                .foregroundColor(.secondary)
                        }
                        .padding()
                        .frame(maxWidth: .infinity)
                    } else {
                        LazyVGrid(columns: Array(repeating: GridItem(.flexible(), spacing: 12), count: columnsCount), spacing: 12) {
                            ForEach(libraryManager.bookmarks) { item in
                                if let module = moduleManager.modules.first(where: { $0.id.uuidString == item.moduleId }) {
                                    Button(action: {
                                                    selectedBookmark = item
                                                    isDetailActive = true
                                                    }) {
                                        VStack(alignment: .leading) {
                                            ZStack {
                                                KFImage(URL(string: item.imageUrl))
                                                    .placeholder {
                                                        RoundedRectangle(cornerRadius: 10)
                                                            .fill(Color.gray.opacity(0.3))
                                                            .aspectRatio(2 / 3, contentMode: .fit)
                                                            .shimmering()
                                                    }
                                                    .resizable()
                                                    .aspectRatio(contentMode: .fill)
                                                    .frame(height: cellWidth * 3 / 2)
                                                    .frame(maxWidth: cellWidth)
                                                    .cornerRadius(10)
                                                    .clipped()
                                                    .overlay(
                                                        KFImage(URL(string: module.metadata.iconUrl))
                                                            .resizable()
                                                            .frame(width: 24, height: 24)
                                                            .cornerRadius(4)
                                                            .padding(4),
                                                        alignment: .topLeading
                                                    )
                                            }
                                            Text(item.title)
                                                .font(.subheadline)
                                                .foregroundColor(.primary)
                                                .lineLimit(1)
                                                .multilineTextAlignment(.leading)
                                        }
                                    }
                                    .contextMenu {
                                        Button(role: .destructive, action: {
                                            libraryManager.removeBookmark(item: item)
                                        }) {
                                            Label("Remove from Bookmarks", systemImage: "trash")
                                        }
                                    }
                                }
                            }
                        }
                        .padding(.horizontal, 20)
                        NavigationLink(
                            destination: Group {
                                if let bookmark = selectedBookmark,
                                    let module = moduleManager.modules.first(where: { $0.id.uuidString == bookmark.moduleId }) {
                                    MediaInfoView(
                                        title: bookmark.title,
                                        imageUrl: bookmark.imageUrl,
                                        href: bookmark.href,
                                        module: module
                                    )
                                } else {
                                    Text("No Data Available")
                                }
                            },
                            isActive: $isDetailActive
                        ) {
                            EmptyView()
                        }
                        .onAppear {
                            updateOrientation()
                        }
                        .onReceive(NotificationCenter.default.publisher(for: UIDevice.orientationDidChangeNotification)) { _ in
                            updateOrientation()
                        }
                    }
                }
                .padding(.vertical, 20)

                NavigationLink(
                    destination: SettingsViewProfile(),
                    isActive: $showProfileSettings,
                    label: { EmptyView() }
                )
                .hidden()
            }
            .navigationTitle("Library")
            .toolbar {
                ToolbarItem(placement: .navigationBarLeading) {
                    Menu {
                        ForEach(profileStore.profiles) { profile in
                            Button {
                                profileStore.setCurrentProfile(profile)
                            } label: {
                                if profile == profileStore.currentProfile {
                                    Label("\(profile.emoji) \(profile.name)", systemImage: "checkmark")
                                } else {
                                    Text("\(profile.emoji) \(profile.name)")
                                }
                            }
                        }

                        Divider()

                        Button {
                            showProfileSettings = true
                        } label: {
                            Label("Edit Profiles", systemImage: "slider.horizontal.3")
                        }
                    } label: {
                        Circle()
                            .fill(Color.secondary.opacity(0.3))
                            .frame(width: 32, height: 32)
                            .overlay(
                                Text(profileStore.currentProfile.emoji)
                                    .font(.system(size: 20))
                                    .foregroundStyle(.primary)
                            )
                    }
                }
            }
        }
        .navigationViewStyle(StackNavigationViewStyle())
        .onAppear {
            updateOrientation()
            continueWatchingManager.loadItems()
        }
        .onReceive(NotificationCenter.default.publisher(for: UIDevice.orientationDidChangeNotification)) { _ in
            updateOrientation()
        }
    }

    private func markContinueWatchingItemAsWatched(item: ContinueWatchingItem) {
        let key = "lastPlayedTime_\(item.fullUrl)"
        let totalKey = "totalTime_\(item.fullUrl)"
        UserDefaults.standard.set(99_999_999.0, forKey: key)
        UserDefaults.standard.set(99_999_999.0, forKey: totalKey)
        continueWatchingManager.remove(item: item)
    }

    private func removeContinueWatchingItem(item: ContinueWatchingItem) {
        continueWatchingManager.remove(item: item)
    }

    private func updateOrientation() {
        DispatchQueue.main.async {
            isLandscape = UIDevice.current.orientation.isLandscape
        }
    }
}

struct ContinueWatchingSection: View {
    @Binding var items: [ContinueWatchingItem]
    var markAsWatched: (ContinueWatchingItem) -> Void
    var removeItem: (ContinueWatchingItem) -> Void

    var body: some View {
        VStack(alignment: .leading) {
            ScrollView(.horizontal, showsIndicators: false) {
                HStack(spacing: 8) {
                    ForEach(Array(items.reversed())) { item in
                        ContinueWatchingCell(item: item, markAsWatched: {
                            markAsWatched(item)
                        }, removeItem: {
                            removeItem(item)
                        })
                    }
                }
                .padding(.horizontal, 20)
            }
            .frame(height: 190)
        }
    }
}

struct ContinueWatchingCell: View {
    @EnvironmentObject private var continueWatchingManager: ContinueWatchingManager

    let item: ContinueWatchingItem
    var markAsWatched: () -> Void
    var removeItem: () -> Void

    @State private var currentProgress = 0.0

    var body: some View {
        Button(action: {
            if UserDefaults.standard.string(forKey: "externalPlayer") == "Default" {
                let videoPlayerViewController = VideoPlayerViewController(module: item.module, continueWatchingManager: continueWatchingManager)
                videoPlayerViewController.streamUrl = item.streamUrl
                videoPlayerViewController.fullUrl = item.fullUrl
                videoPlayerViewController.episodeImageUrl = item.imageUrl
                videoPlayerViewController.episodeNumber = item.episodeNumber
                videoPlayerViewController.mediaTitle = item.mediaTitle
                videoPlayerViewController.subtitles = item.subtitles ?? ""
                videoPlayerViewController.aniListID = item.aniListID ?? 0
                videoPlayerViewController.modalPresentationStyle = .fullScreen

                if let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
                   let rootVC = windowScene.windows.first?.rootViewController {
                    FindTopViewController.findViewController(rootVC).present(videoPlayerViewController, animated: true, completion: nil)
                }
            } else {
                let customMediaPlayer = CustomMediaPlayerViewController(
                    module: item.module,
                    continueWatchingManager: continueWatchingManager,
                    urlString: item.streamUrl,
                    fullUrl: item.fullUrl,
                    title: item.mediaTitle,
                    episodeNumber: item.episodeNumber,
                    onWatchNext: nil,
                    subtitlesURL: item.subtitles,
                    aniListID: item.aniListID ?? 0,
                    episodeImageUrl: item.imageUrl
                )
                customMediaPlayer.modalPresentationStyle = .fullScreen

                if let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
                   let rootVC = windowScene.windows.first?.rootViewController {
                    FindTopViewController.findViewController(rootVC).present(customMediaPlayer, animated: true, completion: nil)
                }
            }
        }) {
            VStack(alignment: .leading) {
                ZStack {
                    KFImage(URL(string: item.imageUrl.isEmpty ? "https://raw.githubusercontent.com/cranci1/Sora/refs/heads/main/assets/banner2.png" : item.imageUrl))
                        .placeholder {
                            RoundedRectangle(cornerRadius: 10)
                                .fill(Color.gray.opacity(0.3))
                                .frame(width: 240, height: 135)
                                .shimmering()
                        }
                        .setProcessor(RoundCornerImageProcessor(cornerRadius: 10))
                        .resizable()
                        .aspectRatio(16 / 9, contentMode: .fill)
                        .frame(width: 240, height: 135)
                        .cornerRadius(10)
                        .clipped()
                        .overlay(
                            KFImage(URL(string: item.module.metadata.iconUrl))
                                .resizable()
                                .frame(width: 24, height: 24)
                                .cornerRadius(4)
                                .padding(4),
                            alignment: .topLeading
                        )
                }
                .overlay(
                    ZStack {
                        Rectangle()
                            .fill(Color.black.opacity(0.3))
                            .blur(radius: 3)
                            .frame(height: 30)

                        ProgressView(value: currentProgress)
                            .progressViewStyle(LinearProgressViewStyle(tint: .white))
                            .padding(.horizontal, 8)
                            .scaleEffect(x: 1, y: 1.5, anchor: .center)
                    },
                    alignment: .bottom
                )

                VStack(alignment: .leading) {
                    Text("Episode \(item.episodeNumber)")
                        .font(.caption)
                        .lineLimit(1)
                        .foregroundColor(.secondary)

                    Text(item.mediaTitle)
                        .font(.caption)
                        .lineLimit(2)
                        .foregroundColor(.primary)
                        .multilineTextAlignment(.leading)
                }
            }
            .frame(width: 240, height: 170)
        }
        .contextMenu {
            Button(action: { markAsWatched() }) {
                Label("Mark as Watched", systemImage: "checkmark.circle")
            }
            Button(role: .destructive, action: { removeItem() }) {
                Label("Remove Item", systemImage: "trash")
            }
        }
        .onAppear {
            updateProgress()
        }
        .onReceive(NotificationCenter.default.publisher(for: UIApplication.didBecomeActiveNotification)) { _ in
            updateProgress()
        }
    }

    private func updateProgress() {
        let lastPlayedTime = UserDefaults.standard.double(forKey: "lastPlayedTime_\(item.fullUrl)")
        let totalTime = UserDefaults.standard.double(forKey: "totalTime_\(item.fullUrl)")

        if totalTime > 0 {
            let ratio = lastPlayedTime / totalTime
            // Clamp ratio between 0 and 1:
            currentProgress = max(0, min(ratio, 1))
        } else {
            currentProgress = max(0, min(item.progress, 1))
        }
    }
}
