//
//  WebViewController.m
//  EkycSampleObjC
//
//  Created by Alchera on 2023/03/14.
//

#import "WebViewController.h"

@interface WebViewController ()

@property NSString *responseName;
@property NSString *result;
@property NSString *responseJson;

@end

@implementation WebViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.navigationItem.title = @"eKYC";
}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    [self checkCameraPermission];
    [self.navigationController setNavigationBarHidden:NO];
}

/* View 불러오기 */
- (void)loadView {
    WKWebViewConfiguration *webConfiguration = [WKWebViewConfiguration new];
    [webConfiguration setAllowsInlineMediaPlayback:YES];
    
    // 고객 정보를 담은 postMessage 설정
    NSString *requestData = [self encodedPostMessage];
    if (requestData != nil) {
        WKUserScript *userScript = [[WKUserScript alloc] initWithSource:[NSString stringWithFormat:@"postMessage('%@')", requestData]
                                                          injectionTime:WKUserScriptInjectionTimeAtDocumentEnd
                                                       forMainFrameOnly:YES];
        [webConfiguration.userContentController addUserScript:userScript];
        webConfiguration.preferences.javaScriptEnabled = YES;
    }
    // 메시지 수신할 핸들러 등록
    self.responseName = @"alcherakyc";
    [webConfiguration.userContentController addScriptMessageHandler:self name:self.responseName];
    
    self.webView = [[WKWebView alloc] initWithFrame:CGRectZero configuration:webConfiguration];
    [self.webView setUIDelegate:self];
    self.view = self.webView;
}


/* WebView 불러오기 */
- (void)loadWebView {
    NSURL *url = [NSURL URLWithString:@"https://kyc.useb.co.kr/auth"];
    if (url == nil) return;
    
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    
    [self.webView loadRequest:request];
}

/* KYC 결과 창으로 이동 */
- (void)loadReportView {
    NSLog(@"ekyc result: %@", self.result);
    NSLog(@"ekyc responseJson: %@", self.responseJson);
}

/* webView Javascript Alert 처리 */
- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler {
    
    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:message message:nil preferredStyle:UIAlertControllerStyleAlert];
    UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"확인" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
        completionHandler();
    }];
    
    [alertController addAction:cancelAction];
    
    dispatch_async(dispatch_get_main_queue(), ^{
        [self presentViewController:alertController animated:YES completion:nil];
    });
}

/* WebView 메시지 핸들러 */
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
    if (message.name != self.responseName || message.body == nil) return;
    
    NSString *decodedMessage = [self decodedPostMessage:message.body];
    if (decodedMessage == nil) {
        NSLog(@"KYC 응답 메시지 분석에 실패했습니다.");
        return;
    }
    KycResponse *kycResponse = [KycResponse parsingJson:decodedMessage];
    if (kycResponse == nil) {
        NSLog(@"KYC 응답 메시지 변환에 실패했습니다.");
        return;
    }
    
    self.result = kycResponse.result;
    if ([kycResponse.result isEqualToString:@"success"]) {
        NSLog(@"KYC 작업이 성공했습니다.");
        self.responseJson = decodedMessage;
    } else if ([kycResponse.result isEqualToString:@"failed"]) {
        NSLog(@"KYC가 작업이 실패했습니다.");
        self.responseJson = decodedMessage;
    } else if ([kycResponse.result isEqualToString:@"complete"]) {
        NSLog(@"KYC가 완료되었습니다.");
        if (self.responseJson == nil) self.responseJson = decodedMessage;
        [self loadReportView];
    } else if ([kycResponse.result isEqualToString:@"close"]) {
        NSLog(@"KYC가 완료되지 않았습니다.");
        if (self.responseJson == nil) self.responseJson = decodedMessage;
        [self loadReportView];
    } else {
        self.result = nil;
        self.responseJson = nil;
    }
}

/* Camera 권한 체크 */
- (void)checkCameraPermission {
    AVAuthorizationStatus permission = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
    switch (permission) {
        case AVAuthorizationStatusAuthorized: {
            dispatch_async(dispatch_get_main_queue(), ^{
                [self loadWebView];
            });
            break;
        }
        case AVAuthorizationStatusDenied: {
            UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"카메라 권한 필요"
                                                                           message:@"설정 > 개인 정보 보호 > 카메라에서 권한을 변경하실 수 있습니다."
                                                                    preferredStyle:UIAlertControllerStyleAlert];
            UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil];
            [alert addAction:okAction];
            [self presentViewController:alert animated:NO completion:nil];
            break;
        }
        case AVAuthorizationStatusNotDetermined: {
            // 권한 요청
            [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
                if (granted) {
                    dispatch_async(dispatch_get_main_queue(), ^{
                        [self loadWebView];
                    });
                } else {
                    NSLog(@"권한이 거부되었습니다.");
                    [self.navigationController popViewControllerAnimated:YES];
                }
            }];
            break;
        }
        default:
            NSLog(@"Permission = %ld", permission);
            break;
    }
}

/* PostMessage로 보낼 고객 정보를 생성합니다. */
- (nullable NSString *)encodedPostMessage {
    NSDictionary *jsonDictionary = @{
        @"customer_id": @"9",
        @"id": @"demoUser",
        @"key": @"demoUser0000!",
        @"name": @"손상균",
        @"birthday": @"1988-08-05",
        @"phone_number": @"01022521822",
        @"email": @"zoople@naver.com",
    };
    
    // JSON -> encodeURIComponent -> Base64Encoding
    NSError *error = nil;
    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:jsonDictionary options:NSJSONWritingPrettyPrinted error:&error];
    if (error != nil) {
        NSLog(@"고객 정보 생성에 실패했습니다. Error: %@", error.localizedDescription);
        return nil;
    }
    
    NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
    
    if (jsonString != nil) {
        NSString *uriEncoded = [jsonString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
        return [[uriEncoded dataUsingEncoding:NSUTF8StringEncoding] base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];
    }
    
    return nil;
}

/* KYC 수행 결과를 분석합니다. */
- (nullable NSString *)decodedPostMessage:(nonnull NSString *)encodedMessage {
    // Base64Decoding -> decodeURIComponent -> JSON
    NSData *base64DecodedData = [[NSData alloc] initWithBase64EncodedString:encodedMessage options:NSDataBase64DecodingIgnoreUnknownCharacters];
    if (base64DecodedData != nil) {
        NSString *base64DecodedString = [[NSString alloc] initWithData:base64DecodedData encoding:NSUTF8StringEncoding];
        if (base64DecodedData != nil) {
            NSString *jsonString = [base64DecodedString stringByRemovingPercentEncoding];
            return jsonString;
        }
    }
    
    return nil;
}

@end

// ekyc Response Parsing Class
@implementation Module

- (instancetype)initWithDictionary:(NSDictionary *)dictionary {
    if (self = [super init]) {
        if ([dictionary isKindOfClass:NSDictionary.class]) {
            self.id_card_ocr = [dictionary objectForKey:@"id_card_ocr"];
            self.id_card_verification = [dictionary objectForKey:@"id_card_verification"];
            self.face_authentication = [dictionary objectForKey:@"face_authentication"];
            self.account_verification = [dictionary objectForKey:@"account_verification"];
            self.liveness = [dictionary objectForKey:@"liveness"];
        }
    }
    return self;
}
@end

@implementation Id_card
- (instancetype)initWithDictionary:(NSDictionary *)dictionary {
    if (self = [super init]) {
        if ([dictionary isKindOfClass:NSDictionary.class]) {
            self.modified = [dictionary objectForKey:@"modified"];
            self.verified = [dictionary objectForKey:@"verified"];
            
            NSString *image_card_image_string = [dictionary objectForKey:@"id_card_image"];
            if ([image_card_image_string isKindOfClass:NSString.class]) {
                self.id_card_image = [[NSData alloc] initWithBase64EncodedString:image_card_image_string options:kNilOptions];
            }
            
            NSString *id_card_origin_string = [dictionary objectForKey:@"id_card_origin"];
            if ([id_card_origin_string isKindOfClass:NSString.class]) {
                self.id_card_origin = [[NSData alloc] initWithBase64EncodedString:id_card_origin_string options:kNilOptions];
            }
            
            NSString *id_crop_image_string = [dictionary objectForKey:@"id_crop_image"];
            if ([id_crop_image_string isKindOfClass:NSString.class]) {
                self.id_crop_image = [[NSData alloc] initWithBase64EncodedString:id_crop_image_string options:kNilOptions];
            }
        }
    }
    return self;
}
@end

@implementation Face_check
- (instancetype)initWithDictionary:(NSDictionary *)dictionary {
    if (self = [super init]) {
        if ([dictionary isKindOfClass:NSDictionary.class]) {
            self.is_same_person = [[dictionary valueForKey:@"is_same_person"] intValue];
            self.is_live = [[dictionary valueForKey:@"is_live"] intValue];
            
            NSString *selfie_image_string = [dictionary objectForKey:@"selfie_image"];
            if ([selfie_image_string isKindOfClass:NSString.class]) {
                self.selfie_image = [[NSData alloc] initWithBase64EncodedString:selfie_image_string options:kNilOptions];
            }
        }
    }
    return self;
}
@end

@implementation Account
- (instancetype)initWithDictionary:(NSDictionary *)dictionary {
    if (self = [super init]) {
        if ([dictionary isKindOfClass:NSDictionary.class]) {
            self.verified = [dictionary objectForKey:@"verified"];
            self.account_holder = [dictionary objectForKey:@"account_holder"];
            self.finance_company = [dictionary objectForKey:@"finance_company"];
            self.finance_code = [dictionary objectForKey:@"finance_code"];
            self.account_number = [dictionary objectForKey:@"account_number"];
        }
    }
    return self;
}
@end

@implementation Review_result
- (instancetype)initWithDictionary:(NSDictionary *)dictionary {
    if (self = [super init]) {
        if ([dictionary isKindOfClass:NSDictionary.class]) {
            self.name = [dictionary objectForKey:@"name"];
            self.phone_number = [dictionary objectForKey:@"phone_number"];
            self.birthday = [dictionary objectForKey:@"birthday"];
            self.module = [[Module alloc] initWithDictionary:[dictionary objectForKey:@"module"]];
            self.id_card = [[Id_card alloc] initWithDictionary:[dictionary objectForKey:@"id_card"]];
            self.face_check = [[Face_check alloc] initWithDictionary:[dictionary objectForKey:@"face_check"]];
            self.account = [[Account alloc] initWithDictionary:[dictionary objectForKey:@"account"]];
        }
    }
    return self;
}
@end

@implementation KycResponse
- (instancetype)initWithDictionary:(NSDictionary *)dictionary {
    if (self = [super init]) {
        if ([dictionary isKindOfClass:NSDictionary.class]) {
            self.result = [dictionary objectForKey:@"result"];
            self.review_result = [[Review_result alloc] initWithDictionary:[dictionary objectForKey:@"review_result"]];
        }
    }
    return self;
}

/* Json을 KycResponse로 변환합니다. */
+ (nullable KycResponse *)parsingJson:(NSString *)jsonString {
    NSData *uriDecodedData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
    NSError *error;
    
    if (uriDecodedData != nil) {
        NSDictionary *jsonDictionary = [NSJSONSerialization JSONObjectWithData:uriDecodedData options:NSJSONReadingMutableContainers error:&error];
        if (error == nil) {
            KycResponse *response = [[KycResponse alloc] initWithDictionary:jsonDictionary];
            return response;
        } else {
            NSLog(@"KYC 결과 정보 분석중 오류가 발생했습니다. Error: %@", error.localizedDescription);
        }
    }
    
    return nil;
}
@end
