//
//  KBLoginVM.m
//

#import "KBLoginVM.h"
#import "AppleSignInManager.h"
#import "KBNetworkManager.h"
#import "KBAuthManager.h"
#import "KBAPI.h"
#import "KBUser.h"

@interface KBLoginVM ()
@property (atomic, strong, readwrite, nullable) KBUser *currentUser;
@end

@implementation KBLoginVM

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

- (BOOL)isLoggedIn {
    return [[KBAuthManager shared] isLoggedIn];
}

- (void)signInWithAppleFromViewController:(UIViewController *)presenter
                                completion:(KBLoginCompletion)completion {
    // 调起 Apple 登录
    [[AppleSignInManager shared] signInFromViewController:presenter completion:^(ASAuthorizationAppleIDCredential * _Nullable credential, NSError * _Nullable error) {
        if (error) { if (completion) completion(NO, error); return; }
        if (![credential isKindOfClass:[ASAuthorizationAppleIDCredential class]]) {
            if (completion) completion(NO, [NSError errorWithDomain:@"KBLogin" code:-1 userInfo:@{NSLocalizedDescriptionKey: @"无效的登录凭证"}]);
            return;
        }

        ASAuthorizationAppleIDCredential *cred = (ASAuthorizationAppleIDCredential *)credential;
        // identityToken/authorizationCode 均可按后端要求传递；本项目后端使用 identityToken 映射为 code
        NSString *identityToken = cred.identityToken ? [[NSString alloc] initWithData:cred.identityToken encoding:NSUTF8StringEncoding] : nil;
        NSString *authorizationCode = cred.authorizationCode ? [[NSString alloc] initWithData:cred.authorizationCode encoding:NSUTF8StringEncoding] : nil;

        NSMutableDictionary *params = [NSMutableDictionary dictionary];
        if (identityToken.length) params[@"code"] = identityToken;
        if (authorizationCode.length) params[@"accessCode"] = authorizationCode; // 仅供后端需要时使用
        if (cred.user.length) params[@"userID"] = cred.user; // 可选

        // 向服务端发起校验
        [[KBNetworkManager shared] POST:API_APPLE_LOGIN jsonBody:params headers:nil completion:^(id  _Nullable jsonOrData, NSURLResponse * _Nullable response, NSError * _Nullable error) {
            if (error) { if (completion) completion(NO, error); return; }

            // 从返回 JSON 中提取 token（支持常见命名与层级 data/user）
            // 先解析用户模型（使用 MJExtension）
            KBUser *user = [KBUser userFromResponseObject:jsonOrData];
            self.currentUser = user;
            NSString *token = user.token ?: [self.class tokenFromResponseObject:jsonOrData];
            if (token.length == 0) {
                if (completion) completion(NO, [NSError errorWithDomain:@"KBLogin" code:-2 userInfo:@{NSLocalizedDescriptionKey: @"未返回 token"}]);
                return;
            }

            // 保存登录态到共享钥匙串；供 App 与扩展共享
            BOOL ok = [[KBAuthManager shared] saveAccessToken:token
                                                refreshToken:nil
                                                  expiryDate:nil
                                              userIdentifier:cred.user];
            if (completion) completion(ok, ok ? nil : [NSError errorWithDomain:@"KBLogin" code:-3 userInfo:@{NSLocalizedDescriptionKey: @"保存登录态失败"}]);
        }];
    }];
}

#pragma mark - Helpers

// 宽松解析：token / access_token / accessToken，支持顶层或 data/user 层
+ (NSString *)tokenFromResponseObject:(id)obj {
    if (![obj isKindOfClass:[NSDictionary class]]) return nil;
    NSDictionary *dict = (NSDictionary *)obj;

    NSString *(^pick)(NSDictionary *) = ^NSString *(NSDictionary *d) {
        NSArray *keys = @[ @"token", @"access_token", @"accessToken" ];
        for (NSString *k in keys) {
            id v = d[k]; if ([v isKindOfClass:NSString.class] && ((NSString *)v).length > 0) return v;
        }
        return nil;
    };

    NSString *t = pick(dict);
    if (t.length) return t;

    id data = dict[@"data"]; if ([data isKindOfClass:NSDictionary.class]) { t = pick(data); if (t.length) return t; }
    id user = dict[@"user"]; if ([user isKindOfClass:NSDictionary.class]) { t = pick(user); if (t.length) return t; }

    // 扩展：允许后端将 token 放在 data.session.token
    NSDictionary *d2 = dict[@"data"]; if ([d2 isKindOfClass:NSDictionary.class]) {
        NSDictionary *session = d2[@"session"]; if ([session isKindOfClass:NSDictionary.class]) { t = pick(session); if (t.length) return t; }
    }
    return nil;
}

@end
