//
//  TVResultView.swift
//  Know Em?
//
//  Created by Joe Maghzal on 7/26/21.
//

import SwiftUI
import TMDb
import Combine
import CoreData

struct TVResultView: View {
    @EnvironmentObject var variables: Variables
    @Environment(\.colorScheme) var colorScheme
    @Environment(\.managedObjectContext) var viewContext
    @FetchRequest(entity: Account.entity(), sortDescriptors: [], animation: .spring()) var account: FetchedResults<Account>
    @FetchRequest(entity: WatchItem.entity(), sortDescriptors: [], animation: .spring()) var items: FetchedResults<WatchItem>
    @State var tvShow: TVShow?
    @State var recomendations = [TVShow]()
    @State var cast = [CastMember]()
    @State var crew = [CrewMember]()
    @State var id: Int
    @State var languageSelection = 0
    @State var fetched = false
    @State var finished = false
    @State var showCast = false
    @State var showCrew = false
    @State var trailerID = ""
    @State var rate = false
    @State var showTutorial = false
    @State var rating = 0.0
    @State var videos = [VideoMetadata]()
    var body: some View {
        VStack {
            if !fetched {
                SProgressView()
            }else {
                ScrollView {
                    VStack(spacing: 15) {
                        Group {
                            HStack {
                                IImage(url: "https://www.themoviedb.org/t/p/w300_and_h450_bestv2\(tvShow?.posterPath?.absoluteString ?? "")") { image in
                                    image
                                        .rectFrame()
                                        .clipShape(RoundedRectangle(cornerRadius: 10, style: .continuous))
                                        .shadow(radius: 5)
                                        .contextMenu {
                                            Button(action: {
                                                DispatchQueue.main.async {
                                                    if let url = URL(string: "https://www.themoviedb.org/t/p/w300_and_h450_bestv2\(tvShow?.posterPath?.absoluteString ?? "")"), let data = try? Data(contentsOf: url), let image = UIImage(data: data) {
                                                        UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil)
                                                    }
                                                }
                                            }) {
                                                Text("Save Image")
                                                Image(systemName: "square.and.arrow.down")
                                            }
                                        }
                                }.rectFrame()
                                .clipShape(RoundedRectangle(cornerRadius: 10, style: .continuous))
                                Spacer()
                                VStack(alignment: .leading) {
                                    if let status = tvShow?.status {
                                        HStack {
                                            Text("Status")
                                                .fontWeight(.semibold)
                                            Spacer()
                                        }
                                        HStack {
                                            Text(status)
                                                .padding(.leading, 10)
                                            Spacer()
                                        }
                                    }
                                    if let seasons = tvShow?.numberOfSeasons {
                                        HStack {
                                            Text("Seasons")
                                                .fontWeight(.semibold)
                                            Spacer()
                                        }
                                        HStack {
                                            Text(seasons.asString())
                                                .padding(.leading, 10)
                                            Spacer()
                                        }
                                    }
                                    if let episodes = tvShow?.numberOfEpisodes  {
                                        HStack {
                                            Text("Episodes")
                                                .fontWeight(.semibold)
                                            Spacer()
                                        }
                                        HStack {
                                            Text(episodes.asString())
                                                .padding(.leading, 10)
                                            Spacer()
                                        }
                                    }
                                }
                            }.padding(.leading, 20)
                            if let homepage = tvShow?.homepageURL {
                                HStack {
                                    SLink(url: homepage) {
                                        Text("Home Page")
                                            .foregroundColor(.white)
                                    }.padding(10)
                                    .background(Color.init(colorScheme, to: .buttons))
                                    .contextMenu(navigate: {
                                        UIApplication.shared.open(homepage)
                                    }) {
                                        LinkView(link: homepage.absoluteString)
                                            .environment(\.managedObjectContext, viewContext)
                                            .accentColor(Color(hex: "59AF97"))
                                            .environmentObject(variables)
                                    }menu: {
                                        let openUrl = UIAction(title: "Open", image: UIImage(systemName: "sidebar.left")) { _ in
                                            withAnimation() {
                                                UIApplication.shared.open(homepage)
                                            }
                                        }
                                        let menu = UIMenu(title: homepage.absoluteString, image: nil, identifier: nil, options: .displayInline, children: [openUrl])
                                        return menu
                                    } .clipShape(RoundedRectangle(cornerRadius: 12, style: .continuous))
                                    Spacer()
                                }.padding(.horizontal, 30)
                            }
                            HStack {
                                NavigationLink(destination: ReviewsView(media: .show(id))) {
                                    HStack(spacing: 5) {
                                        Text("Reviews")
                                            .fontWeight(.medium)
                                            .foregroundColor(.white)
                                            .padding(10)
                                            .background(Color(colorScheme, to: .buttons))
                                            .clipShape(RoundedRectangle(cornerRadius: 11, style: .continuous))
                                    }
                                }
                                Spacer()
                                StarsView(rating: $rating, active: true, font: .body, spacing: 2, media: .show(id))
                                    .padding(.horizontal, 10)
                                    .padding(.vertical, rating == 0.0 ? 10: 3)
                                    .background(colorScheme == .dark ? Color.black: Color.white)
                                    .clipShape(RoundedRectangle(cornerRadius: 10, style: .continuous))
                                Spacer()
                                NavigationLink(destination: MediaView(videos: videos)) {
                                    HStack(spacing: 5) {
                                        Text("Media")
                                            .fontWeight(.medium)
                                            .foregroundColor(.white)
                                            .padding(10)
                                            .background(Color(colorScheme, to: .buttons))
                                            .clipShape(RoundedRectangle(cornerRadius: 11, style: .continuous))
                                    }
                                }
                            }.padding(.horizontal, 20)
                            if let languages = tvShow?.languages {
                                if #available(iOS 14.0, *) {
                                    SwipealePickerView(array: languages, selection: $languageSelection) {
                                        ForEach(languages, id: \.self) { language in
                                            Text(language)
                                        }
                                    }.padding(.horizontal, 15)
                                    .frame(height: 30)
                                    .background(colorScheme == .dark ? Color.black: Color.white)
                                    .clipShape(RoundedRectangle(cornerRadius: 10, style: .continuous))
                                    .padding(.horizontal, 30)
                                }else {
                                    ScrollView(.horizontal, showsIndicators: false) {
                                        HStack {
                                            ForEach(languages, id: \.self) { language in
                                                Text(language)
                                            }
                                        }
                                    }.padding(.horizontal, 15)
                                    .frame(height: 30)
                                    .background(colorScheme == .dark ? Color.black: Color.white)
                                    .clipShape(RoundedRectangle(cornerRadius: 10, style: .continuous))
                                    .padding(.horizontal, 30)
                                }
                            }
                        }
                        HStack {
                            Text(tvShow?.genres?.map({$0.name}).getGenres(3) ?? "")
                                .fontWeight(.semibold)
                            Divider()
                            Text((tvShow?.episodeRunTime?.first?.asString() ?? "") + " min")
                            Spacer()
                        }.padding(.horizontal, 20)
                        if trailerID != "" {
                            HStack {
                                Text("Trailer")
                                    .font(.title)
                                    .fontWeight(.semibold)
                                Spacer()
                            }.padding(.horizontal, 20)
                                .padding(.bottom, -10)
                            YouTubeView(id: trailerID)
                                .frame(height: 150)
                                .background(Color(.systemBackground))
                                .cornerRadius(12)
                                .padding(.horizontal, 30)
                        }
                        if let seasons = tvShow?.seasons {
                            ScrollView(.horizontal, showsIndicators: false) {
                                HStack(spacing: 20) {
                                    Spacer()
                                    ForEach(seasons) { season in
                                        NavigationLink(destination: SeasonView(number: season.seasonNumber, tvID: tvShow?.id ?? 0)) {
                                            VStack(spacing: 0) {
                                                Text("Season " + season.seasonNumber.asString())
                                                    .fontWeight(.medium)
                                                IImage(url: "https://www.themoviedb.org/t/p/w300_and_h450_bestv2\(season.posterPath?.absoluteString ?? "")") { image in
                                                    image
                                                        .rectFrame()
                                                        .clipShape(RoundedRectangle(cornerRadius: 10, style: .continuous))
                                                        .shadow(radius: 5)
                                                }.padding(.top, 7)
                                            }
                                        }.padding(.vertical, 10)
                                    }
                                    Spacer()
                                }.padding(.top, 5)
                                .padding(.bottom, 5)
                            }.background((colorScheme == .dark ? Color.black: Color.white).padding(.horizontal, -40))
                        }
                        if let overview = tvShow?.overview {
                            HStack {
                                Text("Overview")
                                    .font(.title)
                                    .fontWeight(.semibold)
                                Spacer()
                            }.padding(.horizontal, 20)
                            .padding(.bottom, -10)
                            Text(overview)
                                .padding(.horizontal, 20)
                                .fixedSize(horizontal: false, vertical: true)
                        }
                        HStack {
                            Text("Recomendations")
                                .font(.title)
                                .fontWeight(.semibold)
                            Spacer()
                        }.padding(.horizontal, 20)
                        .padding(.bottom, -10)
                        ScrollView(.horizontal, showsIndicators: false) {
                            HStack(spacing: 20) {
                                Spacer()
                                ForEach(recomendations) { show in
                                    NavigationLink(destination: TVResultView(id: show.id)) {
                                        VStack(spacing: 10) {
                                            IImage(url:  "https://www.themoviedb.org/t/p/w300_and_h450_bestv2\(show.posterPath?.absoluteString ?? "")") { image in
                                                image
                                                    .rectFrame()
                                                    .clipShape(RoundedRectangle(cornerRadius: 10, style: .continuous))
                                                    .aspectRatio(contentMode: .fit)
                                                    .contextMenu(navigate: {
                                                        withAnimation() {
                                                            recomendations[recomendations.firstIndex(where: {$0.id == show.id}) ?? 0].navigate.toggle()
                                                            // show.navigate.toggle()
                                                        }
                                                    }) {
                                                        TVResultView(id: show.id)
                                                            .environment(\.managedObjectContext, viewContext)
                                                            .accentColor(Color(hex: "59AF97"))
                                                            .environmentObject(variables)
                                                    }menu: {
                                                        let view = UIAction(title: "View", image: UIImage(systemName: "sidebar.left")) { _ in
                                                            withAnimation() {
                                                                recomendations[recomendations.firstIndex(where: {$0.id == show.id}) ?? 0].navigate.toggle()
                                                                //show.navigate.toggle()
                                                            }
                                                        }
                                                        let watch = UIAction(title: "Add to Watch list", image: UIImage(systemName: "bookmark.fill")) { _ in
                                                        }
                                                        let share = UIAction(title: "Share", image: UIImage(systemName: "square.and.arrow.up")) { _ in
                                                        }
                                                        let menu = UIMenu(title: show.name, image: nil, identifier: nil, options: .displayInline, children: [view, watch, share])
                                                        return menu
                                                    }
                                            }.rectFrame()
                                            .clipShape(RoundedRectangle(cornerRadius: 10, style: .continuous))
                                            .shadow(radius: 4)
                                            Text(show.name)
                                                .frame(width: 150, height: 50)
                                            Spacer()
                                        }.padding(.top, 10)
                                    }
                                }
                                Spacer()
                            }.padding(.top, 5)
                            .padding(.bottom, 15)
                        }.background((colorScheme == .dark ? Color.black: Color.white).padding(.horizontal, -40))
                        VStack(spacing: 20) {
                            HStack {
                                Text("Cast & Crew")
                                    .font(.title)
                                    .fontWeight(.semibold)
                                Spacer()
                            }.padding(.horizontal, 20)
                            .padding(.bottom, -10)
                            VStack(spacing: 10) {
                                HStack {
                                    Text("Cast")
                                        .fontWeight(.medium)
                                    Spacer()
                                    Button(action: {
                                        withAnimation() {
                                            showCast.toggle()
                                        }
                                    }) {
                                        Image(systemName: showCast ? "chevron.down": "chevron.right")
                                            .foregroundColor(.accentColor)
                                    }
                                }.padding(.horizontal, 20)
                                if showCast {
                                    VStack(spacing: 10) {
                                        ForEach(cast) { member in
                                            NavigationLink(destination: ResultView(id: member.id)) {
                                                HStack(spacing: 5) {
                                                    IImage(url: "https://www.themoviedb.org/t/p/w300_and_h450_bestv2\(member.profilePath?.absoluteString ?? "")") { image in
                                                        image
                                                            .rectFrame(0.2)
                                                            .clipShape(RoundedRectangle(cornerRadius: 7, style: .continuous))
                                                            .aspectRatio(contentMode: .fit)
                                                    }.rectFrame(0.2)
                                                    .clipShape(RoundedRectangle(cornerRadius: 7, style: .continuous))
                                                    .shadow(radius: 4)
                                                    RoundedRectangle(cornerRadius: 4, style: .continuous)
                                                        .fill(Color.accentColor)
                                                        .frame(width: 1)
                                                        .padding(.leading, 5)
                                                    HStack {
                                                        VStack(alignment: .leading, spacing: 1) {
                                                            Text(member.name)
                                                                .fontWeight(.medium)
                                                                .fixedSize(horizontal: false, vertical: true)
                                                            if member.character != "" {
                                                                Text(member.character)
                                                                    .font(.subheadline)
                                                                    .foregroundColor(.gray)
                                                                    .padding(.top, -3)
                                                                    .padding(.leading, 5)
                                                            }
                                                        }
                                                        Spacer()
                                                    }.padding(10)
                                                    .background(colorScheme == .dark ? Color.black: Color.white)
                                                    .clipShape(RoundedRectangle(cornerRadius: 10, style: .continuous))
                                                    .padding(.leading, 5)
                                                }
                                            }
                                        }
                                    }.padding(.horizontal, 20)
                                }
                                HStack {
                                    Text("Crew")
                                        .fontWeight(.medium)
                                    Spacer()
                                    Button(action: {
                                        withAnimation() {
                                            showCrew.toggle()
                                        }
                                    }) {
                                        Image(systemName: showCrew ? "chevron.down": "chevron.right")
                                            .foregroundColor(.accentColor)
                                    }
                                }.padding(.horizontal, 20)
                                if showCrew {
                                    VStack(spacing: 10) {
                                        ForEach(crew) { member in
                                            NavigationLink(destination: ResultView(id: member.id)) {
                                                HStack(spacing: 5) {
                                                    IImage(url: "https://www.themoviedb.org/t/p/w300_and_h450_bestv2\(member.profilePath?.absoluteString ?? "")") { image in
                                                        image
                                                            .rectFrame(0.2)
                                                            .clipShape(RoundedRectangle(cornerRadius: 7, style: .continuous))
                                                            .aspectRatio(contentMode: .fit)
                                                    }.rectFrame(0.2)
                                                    .clipShape(RoundedRectangle(cornerRadius: 7, style: .continuous))
                                                    .shadow(radius: 4)
                                                    RoundedRectangle(cornerRadius: 4, style: .continuous)
                                                        .fill(Color.accentColor)
                                                        .frame(width: 1)
                                                        .padding(.leading, 5)
                                                    HStack {
                                                        VStack(alignment: .leading, spacing: 1) {
                                                            Text(member.name)
                                                                .fontWeight(.medium)
                                                                .fixedSize(horizontal: false, vertical: true)
                                                            if member.department != "" {
                                                                Text(member.department)
                                                                    .font(.subheadline)
                                                                    .foregroundColor(.gray)
                                                                    .padding(.top, -3)
                                                                    .padding(.leading, 5)
                                                            }
                                                        }
                                                        Spacer()
                                                    }.padding(10)
                                                    .background(colorScheme == .dark ? Color.black: Color.white)
                                                    .clipShape(RoundedRectangle(cornerRadius: 10, style: .continuous))
                                                    .padding(.leading, 5)
                                                }
                                            }
                                            
                                        }
                                    }.padding(.horizontal, 20)
                                }
                            }
                        }
                        Spacer()
                        Text("Provided by The Movie Database")
                            .foregroundColor(.gray)
                            .font(.caption)
                            .padding(.bottom)
                    }
                }
            }
        }.handler(variables: variables)
        .overlay(
            VStack {
                if showTutorial {
                    VStack {
                        Image("shake")
                            .resizable()
                            .aspectRatio(contentMode: .fit)
                            .frame(width: 50, height: 50)
                        Text("Shake your phone to add a rating!")
                            .fontWeight(.medium)
                    }.onAppear {
                        DispatchQueue.main.asyncAfter(deadline: .now() + 4) {
                            withAnimation(.spring()) {
                                showTutorial = false
                            }
                        }
                    }.padding(10)
                        .background(Color.white.opacity(0.75))
                        .clipShape(RoundedRectangle(cornerRadius: 11, style: .continuous))
                        .shadow(color: Color(colorScheme, to: .shadow), radius: 6, x: 0, y: 0)
                }
            }
        ).background(Color(colorScheme, to: .home).edgesIgnoringSafeArea(.all))
        .onShake {
            withAnimation(.spring()) {
                let impact = UIImpactFeedbackGenerator(style: .light)
                impact.impactOccurred()
                TMDbAuth.shared.deleteRating(movie: false, id: id) { value in
                    if value {
                        rating = 0.0
                    }
                }
            }
        }.load {
            DispatchQueue.main.async {
                withAnimation() {
                    if !fetched {
                        fetchData()
                    }
                }
            }
        }.navigationBarTitle(Text(tvShow?.name ?? ""))
        .navigationBarItems(trailing: HStack(spacing: 15) {
            if let movieId = tvShow?.id {
                Button(action: {
                    guard let url = URL(string: "https://www.themoviedb.org/tv/\(movieId)") else {return}
                    Functions.share(items: [url])
                }) {
                    Image(systemName: "square.and.arrow.up")
                }
                Button(action: {
                    DispatchQueue.main.async {
                        TMDbAuth.toggleTWatchList(tvShow: tvShow, items: items, id: account.first?.aid.int())
                    }
                }) {
                    Image(systemName: items.contains(where: {$0.aid == movieId}) ? "bookmark.fill": "bookmark")
                }
            }
        })
    }
    func fetchData() {
        DispatchQueue.main.async {
            withAnimation() {
                let tvService = TMDbAPI.shared.tvShows
                tvService.detailsPublisher(forTVShow: id).sink { completion in
                    switch completion {
                        case .finished:
                            break
                        case .failure(let error):
                            variables.status = .custom(LocalizedStringKey("Error \(error.localizedDescription)"))
                    }
                }receiveValue: { tvData in
                    tvShow = tvData
                    withAnimation() {
                        fetched.toggle()
                        finished.toggle()
                    }
                }.store(in: &cancelBag)
                tvService.creditsPublisher(forTVShow: id).sink { completion in
                    switch completion {
                        case .finished: break
                        case .failure(let error):
                            variables.status = .custom(LocalizedStringKey("Error \(error.localizedDescription)"))
                    }
                }receiveValue: { credits in
                    cast = credits.cast
                    crew = credits.crew
                }.store(in: &cancelBag)
                tvService.recommendationsPublisher(forTVShow: id, page: nil).sink { completion in
                    switch completion {
                        case .finished: break
                        case .failure(let error):
                            variables.status = .custom(LocalizedStringKey("Error \(error.localizedDescription)"))
                    }
                }receiveValue: { recomendationData in
                    recomendations = recomendationData.results
                }.store(in: &cancelBag)
                tvService.videosPublisher(forTVShow: id).sink { completion in
                    switch completion {
                        case .finished: break
                        case .failure(let error):
                            variables.status = .custom(LocalizedStringKey("Error \(error.localizedDescription)"))
                    }
                }receiveValue: { videos in
                    self.videos = videos.results
                    trailerID = videos.results.last (where: {$0.type == VideoType.trailer && $0.site == "YouTube"})?.key ?? ""
                    print(trailerID)
                }.store(in: &cancelBag)
                fetchRating(id: id)
            }
        }
    }
    func fetchRating(id: Int) {
        let session = TMDbAuth.shared.session ?? ""
        let urlString = "https://api.themoviedb.org/3" + MoviesEndpoint.account(movieID: id).url.absoluteString + "?api_key=0a44cf98cb5b27b93bb5900105267313&session_id=\(session)"
        DispatchQueue.main.async {
            let decoder = JSONDecoder()
            if let url = URL(string: urlString), let data = try? Data(contentsOf: url), let ratings = try? decoder.decode(Ratings.self, from: data) {
                rating = Double(ratings.rated.value) / 2
            }
        }
    }
}
