// AppleSignInManager.m
// 封装“用 Apple 登录”的实现与存储

#import "AppleSignInManager.h"
#import <UIKit/UIKit.h>
#import <Security/Security.h>

static NSString * const kKBAppleUserIdentifierKey = @"com.company.keyboard.apple.user"; // 钥匙串键名

@interface AppleSignInManager ()
@property (nonatomic, weak) UIViewController *presentingVC;
@property (nonatomic, copy) KBAppleSignInCompletion completion;
@end

@implementation AppleSignInManager

+ (instancetype)shared {
    static AppleSignInManager *instance;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{ instance = [AppleSignInManager new]; });
    return instance;
}

- (NSString *)storedUserIdentifier {
    return [self.class keychainLoad:kKBAppleUserIdentifierKey];
}

- (void)signInFromViewController:(UIViewController *)presenting completion:(KBAppleSignInCompletion)completion {
    if (!NSThread.isMainThread) {
        // 确保在主线程发起，否则可能得到 Unknown(1000)
        dispatch_async(dispatch_get_main_queue(), ^{ [self signInFromViewController:presenting completion:completion]; });
        return;
    }
    if (@available(iOS 13.0, *)) {
        self.presentingVC = presenting;
        self.completion = completion;

        ASAuthorizationAppleIDProvider *provider = [ASAuthorizationAppleIDProvider new];
        ASAuthorizationAppleIDRequest *request = provider.createRequest;
        request.requestedScopes = @[ASAuthorizationScopeFullName, ASAuthorizationScopeEmail];

        ASAuthorizationController *controller = [[ASAuthorizationController alloc] initWithAuthorizationRequests:@[request]];
        controller.delegate = self;
        controller.presentationContextProvider = self;
        [controller performRequests];
    } else {
        if (completion) {
            NSError *err = [NSError errorWithDomain:@"AppleSignIn" code:-1 userInfo:@{NSLocalizedDescriptionKey: @"Apple 登录需要 iOS 13 及以上版本"}];
            completion(nil, err);
        }
    }
}

- (void)checkCredentialStateWithCompletion:(void(^)(ASAuthorizationAppleIDProviderCredentialState state))completion {
    if (!completion) return;
    if (@available(iOS 13.0, *)) {
        NSString *userID = self.storedUserIdentifier;
        if (!userID) {
            completion(ASAuthorizationAppleIDProviderCredentialNotFound);
            return;
        }
        ASAuthorizationAppleIDProvider *provider = [ASAuthorizationAppleIDProvider new];
        [provider getCredentialStateForUserID:userID completion:^(ASAuthorizationAppleIDProviderCredentialState credentialState, NSError * _Nullable error) {
            dispatch_async(dispatch_get_main_queue(), ^{ completion(credentialState); });
        }];
    } else {
        completion(ASAuthorizationAppleIDProviderCredentialNotFound);
    }
}

// 使用指定的 userIdentifier 检查凭证状态（无需本地存储）
- (void)checkCredentialStateForUserID:(NSString *)userID completion:(void(^)(ASAuthorizationAppleIDProviderCredentialState state))completion {
    if (!completion) return;
    if (@available(iOS 13.0, *)) {
        if (userID.length == 0) {
            completion(ASAuthorizationAppleIDProviderCredentialNotFound);
            return;
        }
        ASAuthorizationAppleIDProvider *provider = [ASAuthorizationAppleIDProvider new];
        [provider getCredentialStateForUserID:userID completion:^(ASAuthorizationAppleIDProviderCredentialState credentialState, NSError * _Nullable error) {
            dispatch_async(dispatch_get_main_queue(), ^{ completion(credentialState); });
        }];
    } else {
        completion(ASAuthorizationAppleIDProviderCredentialNotFound);
    }
}

#pragma mark - 授权回调 (ASAuthorizationControllerDelegate)

- (void)authorizationController:(ASAuthorizationController *)controller didCompleteWithAuthorization:(ASAuthorization *)authorization API_AVAILABLE(ios(13.0)) {
    if (@available(iOS 13.0, *)) {
        ASAuthorizationAppleIDCredential *credential = authorization.credential;
        // 为了让键盘扩展/主 App 能识别“是否已登录”，在本地持久化 userIdentifier 到钥匙串。
        // 仅保存一个标记（不包含敏感信息），业务登录态仍以服务端为准。
        NSString *userID = credential.user ?: @"";
        if (userID.length > 0) {
            [self.class keychainSave:kKBAppleUserIdentifierKey value:userID];
        }
        if (self.completion) {
            self.completion(credential, nil);
        }
    }
    self.completion = nil;
    self.presentingVC = nil;
}

- (void)authorizationController:(ASAuthorizationController *)controller didCompleteWithError:(NSError *)error API_AVAILABLE(ios(13.0)) {
    if (self.completion) {
        self.completion(nil, error);
    }
    self.completion = nil;
    self.presentingVC = nil;
}

#pragma mark - 授权界面展示锚点 (ASAuthorizationControllerPresentationContextProviding)

- (ASPresentationAnchor)presentationAnchorForAuthorizationController:(ASAuthorizationController *)controller API_AVAILABLE(ios(13.0)) {
    // 优先用传入 VC 的 window
    UIWindow *win = self.presentingVC.view.window;
    if (win) return win;
    // iOS13+ 从前台激活的 scene 中取 keyWindow
    for (UIScene *scene in UIApplication.sharedApplication.connectedScenes) {
        if (scene.activationState == UISceneActivationStateForegroundActive && [scene isKindOfClass:[UIWindowScene class]]) {
            UIWindowScene *ws = (UIWindowScene *)scene;
            for (UIWindow *w in ws.windows) { if (w.isKeyWindow) return w; }
            if (ws.windows.firstObject) return ws.windows.firstObject;
        }
    }
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
    return UIApplication.sharedApplication.keyWindow ?: UIApplication.sharedApplication.windows.firstObject;
#pragma clang diagnostic pop
}

#pragma mark - Keychain 工具

// 本地登出：删除已存储的 userIdentifier，使 App 重新要求登录
- (void)signOut {
    NSDictionary *query = @{(__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword,
                             (__bridge id)kSecAttrService: kKBAppleUserIdentifierKey,
                             (__bridge id)kSecAttrAccount: kKBAppleUserIdentifierKey};
    SecItemDelete((__bridge CFDictionaryRef)query);
}

+ (BOOL)keychainSave:(NSString *)key value:(NSString *)value {
    if (!key) return NO;
    NSData *data = [value dataUsingEncoding:NSUTF8StringEncoding];

    NSDictionary *query = @{(__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword,
                             (__bridge id)kSecAttrService: key,
                             (__bridge id)kSecAttrAccount: key};

    SecItemDelete((__bridge CFDictionaryRef)query);

    NSMutableDictionary *attributes = [query mutableCopy];
    attributes[(__bridge id)kSecValueData] = data ?: [NSData data];

    OSStatus status = SecItemAdd((__bridge CFDictionaryRef)attributes, NULL);
    return (status == errSecSuccess);
}

+ (NSString *)keychainLoad:(NSString *)key {
    if (!key) return nil;
    NSDictionary *query = @{(__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword,
                             (__bridge id)kSecAttrService: key,
                             (__bridge id)kSecAttrAccount: key,
                             (__bridge id)kSecReturnData: @YES,
                             (__bridge id)kSecMatchLimit: (__bridge id)kSecMatchLimitOne};

    CFTypeRef dataRef = NULL;
    OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &dataRef);
    if (status != errSecSuccess || !dataRef) return nil;

    NSData *data = (__bridge_transfer NSData *)dataRef;
    return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
}

@end
