#import "TQWebViewConfigurator.h"
#import "TQNavigationDelegate.h"
#import "TQUIDelegate.h"
#import "TQDownloadManager.h"
#import "TQSchemeInterceptor.h"
#import <objc/runtime.h>

#pragma mark - DelegateRetainer (private)

/// 内部强引用持有 delegate / 下载管理器,防止被 ARC 释放。
/// 通过 objc_setAssociatedObject 关联到 WKWebView 实例上,生命周期与 webView 一致。
@interface TQDelegateRetainer : NSObject
@property (nonatomic, strong) TQNavigationDelegate *navDelegate;
@property (nonatomic, strong) TQUIDelegate *uiDelegate;
@property (nonatomic, strong) TQDownloadManager *downloadManager;
@end

@implementation TQDelegateRetainer
@end


#pragma mark - TQWebViewHandle

static char kTQHandleRetainerKey;

@interface TQWebViewHandle ()
@property (nonatomic, weak, nullable) WKWebView *webView;
@property (nonatomic, strong) TQDelegateRetainer *retainer;
- (instancetype)initWithWebView:(WKWebView *)webView
                       retainer:(TQDelegateRetainer *)retainer;
@end

@implementation TQWebViewHandle

- (instancetype)initWithWebView:(WKWebView *)webView
                       retainer:(TQDelegateRetainer *)retainer {
    if (self = [super init]) {
        _webView = webView;
        _retainer = retainer;
    }
    return self;
}

- (void)loadURL:(NSURL *)url {
    [self.webView loadRequest:[NSURLRequest requestWithURL:url]];
}

- (void)detach {
    WKWebView *wv = self.webView;
    if (!wv) return;
    wv.navigationDelegate = nil;
    wv.UIDelegate = nil;
    objc_setAssociatedObject(wv, &kTQHandleRetainerKey, nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (void)detachAndDestroy {
    WKWebView *wv = self.webView;
    if (!wv) {
        [self detach];
        return;
    }
    [self detach];
    [wv stopLoading];
    // 先加载空白页清空 JS 上下文,避免 WKWebView 在释放时因残留 JS 回调产生警告
    [wv loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"about:blank"]]];
    [wv removeFromSuperview];
}

- (void)attemptBlankRecoveryIfNeeded {
    [self.retainer.navDelegate attemptBlankRecoveryIfNeeded];
}

@end


#pragma mark - TQWebViewConfigurator

@implementation TQWebViewConfigurator

+ (TQWebViewHandle *)applyToWebView:(WKWebView *)webView
                     hostController:(UIViewController *)hostController
                             config:(TQWebViewConfig *)config
                          callbacks:(TQSignCallbacks *)callbacks {
    TQWebViewConfig *cfg = [(config ?: [TQWebViewConfig defaultConfig]) copy];
    TQSignCallbacks *cb = callbacks ?: [TQSignCallbacks callbacks];

    // 包装 callbacks → 主线程派发
    TQOnEventBlock onEvent = ^(id<TQSdkEvent> event) {
        dispatch_async(dispatch_get_main_queue(), ^{
            if (cb.onEvent) cb.onEvent(event);
        });
    };
    TQOnSignResultBlock onSignResult = ^(TQSignResult *result) {
        dispatch_async(dispatch_get_main_queue(), ^{
            if (cb.onSignResult) cb.onSignResult(result);
        });
    };

    TQSchemeInterceptor *schemeInterceptor =
        [[TQSchemeInterceptor alloc] initWithOnSignResult:onSignResult onEvent:onEvent];
    TQExternalSchemeHandler *externalSchemeHandler =
        [[TQExternalSchemeHandler alloc] initWithExternalSchemes:cfg.externalSchemes
                                                          onEvent:onEvent];

    TQNavigationDelegate *navDelegate =
        [[TQNavigationDelegate alloc] initWithConfig:cfg
                                    schemeInterceptor:schemeInterceptor
                                externalSchemeHandler:externalSchemeHandler
                                              onEvent:onEvent];
    TQUIDelegate *uiDelegate =
        [[TQUIDelegate alloc] initWithOnEvent:onEvent
                            hostingController:hostController];

    // 创建下载管理器(统一 URLSession + Cookie 同步,全版本可用)
    TQDownloadManager *downloadMgr =
        [[TQDownloadManager alloc] initWithOnEvent:onEvent
                                     hostController:hostController];
    [navDelegate setDownloadManager:downloadMgr];

    // 替换 delegate(幂等)
    webView.navigationDelegate = navDelegate;
    webView.UIDelegate = uiDelegate;

    // 把 webView weak ref 给 navDelegate,使其能在 lifetime didBecomeActive 时
    // 主动检查 webView 是否处于白屏态并恢复(覆盖渲染进程被静默回收的场景)
    [navDelegate bindWebView:webView];

    // UA 注入已由 TQWKConfigurationFactory.makeConfiguration 在创建 WKWebView 之前完成,
    // 此处无需额外操作(applicationNameForUserAgent 是同步设置,创建后即生效)。

    // 强引用所有 delegate(防止释放)
    TQDelegateRetainer *retainer = [[TQDelegateRetainer alloc] init];
    retainer.navDelegate = navDelegate;
    retainer.uiDelegate = uiDelegate;
    retainer.downloadManager = downloadMgr;
    objc_setAssociatedObject(webView, &kTQHandleRetainerKey, retainer, OBJC_ASSOCIATION_RETAIN_NONATOMIC);

    return [[TQWebViewHandle alloc] initWithWebView:webView retainer:retainer];
}

@end
