import SwiftUI
import WebKit
import DeeplinkIntents
import ComposableArchitecture
import Dependencies
import EventBusClient

@Reducer
public struct WebViewReducer {
    @ObservableState
    public struct State: Equatable {
        public let url: URL
        public let title: String?
        
        public init(url: URL, title: String?) {
            self.url = url
            self.title = title
        }
    }

    public enum Action {
        case task
        case delegate(Delegate)

        public enum Delegate {
            case deeplinkHandled(DeeplinkIntent)
        }
    }
    
    @Dependency(\.eventBus.sendDeeplinkEvent) private var sendDeeplinkEvent

    public init() {}

    public var body: some ReducerOf<Self> {
        Reduce { state, action in
            switch action {
            case .task:
                return .none

            case .delegate(.deeplinkHandled(let intent)):
                sendDeeplinkEvent(.handleDeeplink(intent))
                return .none
            }
        }
    }
}

public struct WebViewScreen: View {
    let store: StoreOf<WebViewReducer>
    
    public init(store: StoreOf<WebViewReducer>) {
        self.store = store
    }
    
    private var statusBarHeight: CGFloat {
        guard let windowScene = UIWindow.current?.windowScene,
              let statusBarManager = windowScene.statusBarManager else {
            return 0
        }
        return statusBarManager.statusBarFrame.height
    }
    
    public var body: some View {
        if let title = store.title, !title.isEmpty {
            WebViewRepresentable(store: store)
                .navigationBarTitle(title)
                .navigationBarTitleDisplayMode(.inline)
                .omniPlayerSafeArea()
        } else {
            WebViewRepresentable(store: store)
                .omniPlayerSafeArea()
                .padding(.top, statusBarHeight + 4)
                .ignoresSafeArea()
        }
    }
}

public struct WebViewRepresentable: UIViewRepresentable {
    let store: StoreOf<WebViewReducer>

    private var request: URLRequest {
        URLRequest(url: store.url, cachePolicy: .returnCacheDataElseLoad)
    }

    public init(store: StoreOf<WebViewReducer>) {
        self.store = store
    }

    // MARK: - UIViewRepresentable

    public func makeCoordinator() -> Coordinator {
        Coordinator(parent: self)
    }

    public func makeUIView(context: Context) -> WKWebView {
        let webView = WKWebView()
        webView.navigationDelegate = context.coordinator
        webView.uiDelegate = context.coordinator
        webView.load(request)
        webView.scrollView.contentInsetAdjustmentBehavior = .never
        webView.scrollView.contentInset = .zero
        webView.scrollView.scrollIndicatorInsets = .zero

        return webView
    }

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

    // MARK: - Event Handling

    func handleDeeplinkIntent(_ intent: DeeplinkIntent) {
        store.send(.delegate(.deeplinkHandled(intent)))
    }

    // MARK: - Coordinator

    public class Coordinator: NSObject, WKNavigationDelegate, WKUIDelegate {
        var parent: WebViewRepresentable

        init(parent: WebViewRepresentable) {
            self.parent = parent
        }

        // MARK: WKNavigationDelegate
        
        public func webView(
            _ webView: WKWebView,
            decidePolicyFor navigationAction: WKNavigationAction,
            decisionHandler: @escaping (WKNavigationActionPolicy) -> Void
        ) {
            guard let url = navigationAction.request.url else {
                decisionHandler(.allow)
                return
            }
            
            let type = navigationAction.navigationType
            
            if type == .linkActivated,
               let host = url.host?.lowercased(),
               !host.hasSuffix("suno.com") && !host.hasSuffix("b.suno.com") {
                UIApplication.shared.open(url)
                decisionHandler(.cancel)
                return
            }

            if let intent = DeeplinkIntent(url: url) {
                if case .webView(_) = intent {
                    decisionHandler(.allow)
                } else {
                    parent.handleDeeplinkIntent(intent)
                    decisionHandler(.cancel)
                }
                return
            }

            decisionHandler(.allow)
        }
        
        // MARK: WKUIDelegate

        public func webView(
            _ webView: WKWebView,
            createWebViewWith configuration: WKWebViewConfiguration,
            for navigationAction: WKNavigationAction,
            windowFeatures: WKWindowFeatures
        ) -> WKWebView? {
            if navigationAction.targetFrame == nil {
                webView.load(navigationAction.request)
            }
            return nil
        }
    }
}
