//
//  DamusPurpleView.swift
//  damus
//
//  Created by William Casarin on 2023-03-21.
//

import SwiftUI
import StoreKit

fileprivate let damus_products = ["purpleyearly","purple"]

enum ProductState {
    case loading
    case loaded([Product])
    case failed
    
    var products: [Product]? {
        switch self {
        case .loading:
            return nil
        case .loaded(let ps):
            return ps
        case .failed:
            return nil
        }
    }
}

enum AccountInfoState {
    case loading
    case loaded(account: DamusPurple.Account)
    case no_account
    case error(message: String)
}

func non_discounted_price(_ product: Product) -> String {
    return (product.price * 1.1984569224).formatted(product.priceFormatStyle)
}

enum DamusPurpleType: String {
    case yearly = "purpleyearly"
    case monthly = "purple"
}

struct PurchasedProduct {
    let tx: StoreKit.Transaction
    let product: Product
}

struct DamusPurpleView: View {
    let damus_state: DamusState
    let keypair: Keypair
    
    @State var my_account_info_state: AccountInfoState = .loading
    @State var products: ProductState
    @State var purchased: PurchasedProduct? = nil
    @State var selection: DamusPurpleType = .yearly
    @State var show_welcome_sheet: Bool = false
    @State var show_manage_subscriptions = false
    @State private var shouldDismissView = false
    
    @Environment(\.dismiss) var dismiss
    
    init(damus_state: DamusState) {
        self._products = State(wrappedValue: .loading)
        self.damus_state = damus_state
        self.keypair = damus_state.keypair
    }
    
    var body: some View {
        NavigationView {
            ZStack {
                Color.black
                    .edgesIgnoringSafeArea(.all)

                Image("purple-blue-gradient-1")
                    .resizable()
                    .edgesIgnoringSafeArea(.all)

                ScrollView {
                    MainContent
                        .padding(.top, 75)
                }
            }
            .navigationBarHidden(true)
            .navigationBarTitleDisplayMode(.inline)
            .navigationBarBackButtonHidden(true)
            .navigationBarItems(leading: BackNav())
        }
        .onReceive(handle_notify(.switched_timeline)) { _ in
            dismiss()
        }
        .onAppear {
            notify(.display_tabbar(false))
            Task {
                await self.load_account()
            }
        }
        .onDisappear {
            notify(.display_tabbar(true))
        }
        .onReceive(handle_notify(.purple_account_update), perform: { account in
            self.my_account_info_state = .loaded(account: account)
        })
        .task {
            await load_products()
        }
        .ignoresSafeArea(.all)
        .sheet(isPresented: $show_welcome_sheet, onDismiss: {
            shouldDismissView = true
        }, content: {
            DamusPurpleNewUserOnboardingView(damus_state: damus_state)
        })
        .manageSubscriptionsSheet(isPresented: $show_manage_subscriptions)
    }
    
    func load_account() async {
        do {
            if let account = try await damus_state.purple.fetch_account(pubkey: damus_state.keypair.pubkey) {
                self.my_account_info_state = .loaded(account: account)
                return
            }
            self.my_account_info_state = .no_account
            return
        }
        catch {
            self.my_account_info_state = .error(message: NSLocalizedString("There was an error loading your account. Please try again later. If problem persists, please contact us at support@damus.io", comment: "Error label when Purple account information fails to load"))
        }
    }
    
    func handle_transactions(products: [Product]) async {
        for await update in StoreKit.Transaction.updates {
            switch update {
                case .verified(let tx):
                    let prod = products.filter({ prod in tx.productID == prod.id }).first
                    
                    if let prod,
                       let expiration = tx.expirationDate,
                       Date.now < expiration
                    {
                        self.purchased = PurchasedProduct(tx: tx, product: prod)
                        break
                    }
                case .unverified:
                    continue
            }
        }
    }
    
    func load_products() async {
        do {
            let products = try await Product.products(for: damus_products)
            self.products = .loaded(products)
            await handle_transactions(products: products)

            print("loaded products", products)
        } catch {
            self.products = .failed
            print("Failed to fetch products: \(error.localizedDescription)")
        }
    }
    
    func IconOnBox(_ name: String) -> some View {
        ZStack {
            RoundedRectangle(cornerRadius: 20.0)
                .background(.ultraThinMaterial, in: RoundedRectangle(cornerRadius: 20.0))
                .frame(width: 80, height: 80)
                .overlay(
                    RoundedRectangle(cornerRadius: 20)
                        .stroke(LinearGradient(
                            colors: [DamusColors.pink, .white.opacity(0), .white.opacity(0.5), .white.opacity(0)],
                            startPoint: .topLeading,
                            endPoint: .bottomTrailing), lineWidth: 1)
                )
            
            Image(name)
                .resizable()
                .frame(width: 50, height: 50)
                .foregroundColor(.white)
        }
    }
    
    func Icon(_ name: String) -> some View {
        Image(name)
            .resizable()
            .frame(width: 50, height: 50)
            .foregroundColor(.white)
    }
    
    func Title(_ txt: String) -> some View {
        Text(txt)
            .font(.title3)
            .bold()
            .foregroundColor(.white)
            .padding(.bottom, 3)
    }
    
    func Subtitle(_ txt: String) -> some View {
        Text(txt)
            .foregroundColor(.white.opacity(0.65))
    }
    
    var ProductLoadError: some View {
        Text(NSLocalizedString("Subscription Error", comment: "Ah dang there was an error loading subscription information from the AppStore. Please try again later :("))
            .foregroundColor(.white)
    }
    
    var SaveText: Text {
        Text(NSLocalizedString("Save 14%", comment: "Percentage of purchase price the user will save"))
            .font(.callout)
            .italic()
            .foregroundColor(DamusColors.green)
    }
     
    func subscribe(_ product: Product) async throws {
        let result = try await product.purchase()
        switch result {
            case .success(.verified(let tx)):
                print("success \(tx.debugDescription)")
                show_welcome_sheet = true
            case .success(.unverified(let tx, let res)):
                print("success unverified \(tx.debugDescription) \(res.localizedDescription)")
                show_welcome_sheet = true
            case .pending:
                break
            case .userCancelled:
                break
            @unknown default:
                break
        }
        
        switch result {
            case .success:
                // TODO (will): why do this here?
                //self.damus_state.purple.starred_profiles_cache[keypair.pubkey] = nil
                Task {
                    await self.damus_state.purple.send_receipt()
                }
            default:
                break
        }
    }
    
    var product: Product? {
        return self.products.products?.filter({
            prod in prod.id == selection.rawValue
        }).first
    }
    
    func price_description(product: Product) -> some View {
        if product.id == "purpleyearly" {
            return (
                AnyView(
                    HStack(spacing: 10) {
                        Text(NSLocalizedString("Annually", comment: "Annual renewal of purple subscription"))
                        Spacer()
                        Text(verbatim: non_discounted_price(product)).strikethrough().foregroundColor(DamusColors.white.opacity(0.5))
                        Text(verbatim: product.displayPrice).fontWeight(.bold)
                    }
                )
            )
        } else {
            return (
                AnyView(
                    HStack(spacing: 10) {
                        Text(NSLocalizedString("Monthly", comment: "Monthly renewal of purple subscription"))
                        Spacer()
                        Text(verbatim: product.displayPrice).fontWeight(.bold)
                    }
                )
            )
        }
    }
    
    func ProductsView(_ products: [Product]) -> some View {
        VStack(spacing: 10) {
            Text(NSLocalizedString("Save 20% off on an annual subscription", comment: "Savings for purchasing an annual subscription"))
                .font(.callout.bold())
                .foregroundColor(.white)
            ForEach(products) { product in
                Button(action: {
                    Task { @MainActor in
                        do {
                            try await subscribe(product)
                        } catch {
                            print(error.localizedDescription)
                        }
                    }
                }, label: {
                    price_description(product: product)
                })
                .buttonStyle(GradientButtonStyle())
            }
        }
        .padding(.horizontal, 20)
    }
    
    func PurchasedView(_ purchased: PurchasedProduct) -> some View {
        VStack(spacing: 10) {
            Text(NSLocalizedString("Purchased!", comment: "User purchased a subscription"))
                .font(.title2)
                .foregroundColor(.white)
            price_description(product: purchased.product)
                .foregroundColor(.white)
                .opacity(0.65)
                .frame(width: 200)
            Text(NSLocalizedString("Purchased on", comment: "Indicating when the user purchased the subscription"))
                .font(.title2)
                .foregroundColor(.white)
            Text(format_date(date: purchased.tx.purchaseDate))
                .foregroundColor(.white)
                .opacity(0.65)
            if let expiry = purchased.tx.expirationDate {
                Text(NSLocalizedString("Renews on", comment: "Indicating when the subscription will renew"))
                    .font(.title2)
                    .foregroundColor(.white)
                Text(format_date(date: expiry))
                    .foregroundColor(.white)
                    .opacity(0.65)
            }
            Button(action: {
                show_manage_subscriptions = true
            }, label: {
                Text(NSLocalizedString("Manage", comment: "Manage the damus subscription"))
            })
            .buttonStyle(GradientButtonStyle())
        }
    }
    
    var ProductStateView: some View {
        Group {
            if damus_state.purple.enable_purple_iap_support {
                switch self.products {
                    case .failed:
                        ProductLoadError
                    case .loaded(let products):
                        if let purchased {
                            PurchasedView(purchased)
                        } else {
                            ProductsView(products)
                        }
                    case .loading:
                        ProgressView()
                            .progressViewStyle(.circular)
                }
            }
        }
    }
    
    var MainContent: some View {
        VStack {
            DamusPurpleLogoView()
            
            switch my_account_info_state {
                case .loading:
                    ProgressView()
                        .progressViewStyle(.circular)
                case .loaded(let account):
                    DamusPurpleAccountView(damus_state: damus_state, account: account)
                case .no_account:
                    MarketingContent
                case .error(let message):
                    Text(message)
                        .foregroundStyle(.red)
                        .multilineTextAlignment(.center)
                        .padding()
            }
            
            Spacer()
        }
    }
    
    var MarketingContent: some View {
        VStack {
            VStack(alignment: .leading, spacing: 30) {
                Subtitle(NSLocalizedString("Help us stay independent in our mission for Freedom tech with our Purple subscription, and look cool doing it!", comment: "Damus purple subscription pitch"))
                    .multilineTextAlignment(.center)
                
                HStack(spacing: 20) {
                    IconOnBox("heart.fill")
                    
                    VStack(alignment: .leading) {
                        Title(NSLocalizedString("Help Build The Future", comment: "Title for funding future damus development"))
                        
                        Subtitle(NSLocalizedString("Support Damus development to help build the future of decentralized communication on the web.", comment: "Reason for supporting damus development"))
                    }
                }
                
                HStack(spacing: 20) {
                    IconOnBox("ai-3-stars.fill")
                    
                    VStack(alignment: .leading) {
                        Title(NSLocalizedString("Exclusive features", comment: "Features only available on subscription service"))
                            .padding(.bottom, -3)
                        
                        HStack(spacing: 3) {
                            Image("calendar")
                                .resizable()
                                .frame(width: 15, height: 15)
                            
                            Text(NSLocalizedString("Coming soon", comment: "Feature is still in development and will be available soon"))
                                .font(.caption)
                                .bold()
                        }
                        .foregroundColor(DamusColors.pink)
                        .padding(.vertical, 3)
                        .padding(.horizontal, 8)
                        .background(DamusColors.lightBackgroundPink)
                        .cornerRadius(30.0)
                        
                        Subtitle(NSLocalizedString("Be the first to access upcoming premium features: Automatic translations, longer note storage, and more", comment: "Description of new features to be expected"))
                            .padding(.top, 3)
                    }
                }
                
                HStack(spacing: 20) {
                    IconOnBox("badge")
                    
                    VStack(alignment: .leading) {
                        Title(NSLocalizedString("Supporter Badge", comment: "Title for supporter badge"))
                        
                        Subtitle(NSLocalizedString("Get a special badge on your profile to show everyone your contribution to Freedom tech", comment: "Supporter badge description"))
                    }
                }
                
                HStack {
                    Spacer()
                    Link(
                        damus_state.purple.enable_purple_iap_support ?
                            NSLocalizedString("Learn more about the features", comment: "Label for a link to the Damus website, to allow the user to learn more about the features of Purple")
                            :
                            NSLocalizedString("Coming soon! Visit our website to learn more", comment: "Label announcing Purple, and inviting the user to learn more on the website"),
                        destination: damus_state.purple.environment.damus_website_url()
                    )
                    .foregroundColor(DamusColors.pink)
                    .padding()
                    Spacer()
                }
                
            }
            .padding([.trailing, .leading], 30)
            .padding(.bottom, 20)
            
            VStack(alignment: .center) {
                ProductStateView
            }
            .padding([.top], 20)
        }
    }
}

struct DamusPurpleLogoView: View {
    var body: some View {
        HStack(spacing: 20) {
            Image("damus-dark-logo")
                .resizable()
                .frame(width: 60, height: 60)
                .clipShape(RoundedRectangle(cornerRadius: 15.0))
                .overlay(
                    RoundedRectangle(cornerRadius: 15)
                        .stroke(LinearGradient(
                            colors: [DamusColors.lighterPink.opacity(0.8), .white.opacity(0), DamusColors.deepPurple.opacity(0.6)],
                            startPoint: .topLeading,
                            endPoint: .bottomTrailing), lineWidth: 1)
                )
                .shadow(radius: 5)
            
            VStack(alignment: .leading) {
                Text(NSLocalizedString("Purple", comment: "Subscription service name"))
                    .font(.system(size: 60.0).weight(.bold))
                    .foregroundStyle(
                        LinearGradient(
                            colors: [DamusColors.lighterPink, DamusColors.deepPurple],
                            startPoint: .bottomLeading,
                            endPoint: .topTrailing
                        )
                    )
                    .foregroundColor(.white)
                    .tracking(-2)
            }
        }
        .padding(.bottom, 30)
    }
}

struct DamusPurpleView_Previews: PreviewProvider {
    static var previews: some View {
        /*
        DamusPurpleView(products: [
            DamusProduct(name: "Yearly", id: "purpleyearly", price: Decimal(69.99)),
            DamusProduct(name: "Monthly", id: "purple", price: Decimal(6.99)),
        ])
         */
        
        DamusPurpleView(damus_state: test_damus_state)
    }
}
