//
//  LNAppConfig.swift
//  Lanu
//
//  Created by OneeChan on 2025/11/6.
//

import Foundation
import Combine

enum LNAppEnvType: Codable, CaseIterable {
    case test
    case official
    
    var text: String {
        switch self {
        case .test: "测试环境"
        case .official: "线上环境"
        }
    }
}

enum LNAppLanguage: Codable {
    case chiness
    case english
    case indonesian
    
    var text: String {
        switch self {
        case .chiness: "中文"
        case .english: "English"
        case .indonesian: "Bahasa Indonesia"
        }
    }
    
    var bundleName: String {
        switch self {
        case .chiness: "zh-Hans"
        case .english: "en"
        case .indonesian: "id"
        }
    }
    
    var languageCode: String {
        switch self {
        case .chiness: "zh"
        case .english: "en"
        case .indonesian: "id"
        }
    }
    
    var countryCode: String {
        switch self {
        case .chiness: "CN"
        case .english: "US"
        case .indonesian: "ID"
        }
    }
    
    var isSelected: Bool {
        self == LNAppConfig.shared.curLang
    }
    
    static var available: [LNAppLanguage] {
        [.chiness, .english, .indonesian]
    }
}

class LNAppConfig {
    static var shared = LNAppConfig()
    
    @Published
    private(set) var hasNewVersion = false
    private(set) var isForeground = true {
        didSet {
            LNEventDeliver.notifyEvent { ($0 as? LNAppMainEvent)?.onAppStateChanged(foreground: self.isForeground) }
        }
    }
    
    var curEnv: LNAppEnvType = LNUserDefaults[.appEnv, .official] {
        didSet {
            LNUserDefaults[.appEnv] = curEnv
        }
    }
    
    var countryCode: String {
        if #available(iOS 16.0, *) {
            Locale.current.region?.identifier ?? ""
        } else {
            Locale.current.regionCode ?? ""
        }
    }
    
    private static var defaultLanguage: LNAppLanguage {
        let lang = Locale.preferredLanguages.first ?? "en"
        return if lang == LNAppLanguage.chiness.bundleName {
            .chiness
        } else if lang == LNAppLanguage.indonesian.bundleName {
            .indonesian
        } else {
            .english
        }
    }
    var curLang: LNAppLanguage = LNUserDefaults[.appLanguage, defaultLanguage] {
        didSet {
            guard oldValue != curLang else { return }
            LNUserDefaults[.appLanguage] = curLang
            LNEventDeliver.notifyEvent {
                ($0 as? LNAppMainEvent)?.onAppLanguageChanged(newLanguage: self.curLang)
            }
        }
    }
    
    var languageBundleMap: [LNAppLanguage: Bundle] = {
        LNAppLanguage.available.reduce(into: [LNAppLanguage: Bundle](), { result, language in
            let bundle = if let path = Bundle.main.path(forResource: language.bundleName, ofType: "lproj"),
                            let bundle = Bundle(path: path) {
                bundle
            } else {
                Bundle.main
            }
            result[language] = bundle
        })
    }()
    var languageBundle: Bundle {
        languageBundleMap[curLang] ?? Bundle.main
    }
    
    init() {
        checkNewVersion()
        LNEventDeliver.addObserver(self)
        NotificationCenter.default.addObserver(
            forName: UIApplication.didEnterBackgroundNotification,
            object: nil, queue: .main)
        { [weak self] _ in
            guard let self else { return }
            isForeground = false
        }
        NotificationCenter.default.addObserver(
            forName: UIApplication.willEnterForegroundNotification,
            object: nil, queue: .main)
        { [weak self] _ in
            guard let self else { return }
            isForeground = true
        }
    }
}

extension LNAppConfig {
    func jumpToAppStore() {
        let appStoreJumpURL = "https://apps.apple.com/us/app/gamigo/id6756352551?action=write-review"
        guard let url = URL(string: appStoreJumpURL) else { return }
        
        if UIApplication.shared.canOpenURL(url) {
            UIApplication.shared.open(url, options: [:], completionHandler: nil)
        }
    }
    
    private func checkNewVersion() {
        let appStoreLookupURL = "https://itunes.apple.com/lookup?bundleId=\(curAppBundleIdentifier)"
        guard let url = URL(string: appStoreLookupURL) else {
            return
        }
            
        let task = URLSession.shared.dataTask(with: url)
        { [weak self] data, response,
            error in
            guard let self = self else { return }
               
            guard error == nil,
                  let data else {
                return
            }
            
            if let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any],
               let results = json["results"] as? [[String: Any]],
               let appStoreVersion = results.first?["version"] as? String {
                hasNewVersion = curAppVersion != appStoreVersion
            }
        }
        task.resume()
    }
}

extension LNAppConfig: LNNetworkMonitorNotify {
    func onNetworkStateChanged(state: LNNetworkState) {
        if case .available = state {
            checkNewVersion()
        }
    }
}
