import SwiftUI
import WebKit

@MainActor
final class WebViewModel: ObservableObject {
    static let homeURL = URL(string: "https://gartogqq.top/m/")!

    @Published var isLoading = true
    @Published var errorMessage: String?
    weak var webView: WKWebView?

    func reload() {
        errorMessage = nil
        isLoading = true
        guard let webView else { return }
        if webView.url == nil {
            webView.load(URLRequest(url: Self.homeURL))
        } else {
            webView.reload()
        }
    }
}

struct WebViewContainer: UIViewRepresentable {
    @ObservedObject var model: WebViewModel

    func makeCoordinator() -> Coordinator {
        Coordinator(model: model)
    }

    func makeUIView(context: Context) -> WKWebView {
        let configuration = WKWebViewConfiguration()
        configuration.websiteDataStore = .default()
        configuration.allowsInlineMediaPlayback = true
        configuration.mediaTypesRequiringUserActionForPlayback = []
        configuration.defaultWebpagePreferences.allowsContentJavaScript = true
        configuration.applicationNameForUserAgent = "YGKSGameTradeApp/1.1"

        let webView = WKWebView(frame: .zero, configuration: configuration)
        webView.navigationDelegate = context.coordinator
        webView.uiDelegate = context.coordinator
        webView.allowsBackForwardNavigationGestures = true
        webView.allowsLinkPreview = false
        webView.scrollView.contentInsetAdjustmentBehavior = .automatic
        model.webView = webView
        webView.load(URLRequest(url: WebViewModel.homeURL, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 30))
        return webView
    }

    func updateUIView(_ webView: WKWebView, context: Context) {}

    final class Coordinator: NSObject, WKNavigationDelegate, WKUIDelegate {
        private let model: WebViewModel

        init(model: WebViewModel) {
            self.model = model
        }

        func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction,
                     decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
            guard let url = navigationAction.request.url,
                  let scheme = url.scheme?.lowercased() else {
                decisionHandler(.cancel)
                return
            }

            if scheme == "about" || scheme == "data" || scheme == "blob" {
                decisionHandler(.allow)
                return
            }

            if scheme == "http" || scheme == "https" {
                if isOfficialSite(url) {
                    if scheme == "http", var secure = URLComponents(url: url, resolvingAgainstBaseURL: false) {
                        secure.scheme = "https"
                        if let secureURL = secure.url {
                            webView.load(URLRequest(url: secureURL))
                        }
                        decisionHandler(.cancel)
                        return
                    }
                    if navigationAction.targetFrame == nil {
                        webView.load(navigationAction.request)
                        decisionHandler(.cancel)
                    } else {
                        decisionHandler(.allow)
                    }
                    return
                }
                UIApplication.shared.open(url)
                decisionHandler(.cancel)
                return
            }

            UIApplication.shared.open(url, options: [:])
            decisionHandler(.cancel)
        }

        func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
            model.errorMessage = nil
            model.isLoading = true
        }

        func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
            model.isLoading = false
        }

        func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
            show(error)
        }

        func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) {
            if (error as NSError).code != NSURLErrorCancelled {
                show(error)
            }
        }

        func webViewWebContentProcessDidTerminate(_ webView: WKWebView) {
            webView.reload()
        }

        func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration,
                     for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {
            if let url = navigationAction.request.url, isOfficialSite(url) {
                webView.load(navigationAction.request)
            } else if let url = navigationAction.request.url {
                UIApplication.shared.open(url)
            }
            return nil
        }

        private func show(_ error: Error) {
            model.isLoading = false
            model.errorMessage = error.localizedDescription + "\n\n请检查网络连接后重试。"
        }

        private func isOfficialSite(_ url: URL) -> Bool {
            guard let host = url.host?.lowercased() else { return false }
            return host == "gartogqq.top" || host.hasSuffix(".gartogqq.top")
        }
    }
}
