//
//  Login.swift
//  JJUNGTABLE
//
//  Created by Sean Kim on 6/11/24.
//

import SwiftUI
import Combine

import AuthenticationServices

import KakaoSDKCommon
import KakaoSDKAuth
import KakaoSDKUser

import Firebase
import FirebaseAuth

/*
 
 2024-06-11 01:26:08184 [ℹ️][Api.swift 136:41] -> response:
  Optional({
     "app_id" = 987284;
     "expires_in" = 43199;
     id = 3138117983;
 })
 ＿＿＿＿＿＿＿＿＿＿ ＿＿＿＿＿＿＿＿＿＿ ＿＿＿＿＿＿＿＿＿＿ ＿＿＿＿＿＿＿＿＿＿
*   LOCATION   : [ContentView.swift : 69] - body
|     TIME     : [2024/06/12 14:39:17:856]
>     NOTE     : 001273.49bfcb15b70d440a9666b4434336fc2c.0741
 ￣￣￣￣￣￣￣￣￣￣ ￣￣￣￣￣￣￣￣￣￣ ￣￣￣￣￣￣￣￣￣￣ ￣￣￣￣￣￣￣￣￣￣
 */



class Login: NSObject, ObservableObject{
    //    let appId = "987284"
    
    @State private var verificationCode: String = ""
    @State private var verificationID: String?
    
    private var cancellables = Set<AnyCancellable>()
    private var currentPromise: Future<String, LOGIN_ERROR>.Promise?
    
    func tryKakaoLogin() -> Future<String, LOGIN_ERROR> {
        return Future { promise in
            if UserApi.isKakaoTalkLoginAvailable() { // 카카오 간편로그인이 가능한지 확인
                UserApi.shared.loginWithKakaoTalk { (oauthToken, error) in
                    if let error = error {
                        promise(.failure(.init(caseType: .KAKAO_LOGIN,
                                               message: "\(error.localizedDescription)")))
                    } else {
                        printLog("Login success.: \(oauthToken)")
                        self.kakaoAccessUserInfo().sink(
                            receiveCompletion: { completion in
                                if case .failure(let error) = completion {
                                    promise(.failure(error))
                                }
                            },
                            receiveValue: { id in
                                promise(.success(id))
                            }
                        ).store(in: &self.cancellables)
                    }
                }
            } else {
                UserApi.shared.loginWithKakaoAccount { (oauthToken, error) in
                    if let error = error {
                        promise(.failure(.init(caseType: .KAKAO_LOGIN,
                                               message: "\(error.localizedDescription)")))
                    } else {
                        print("Login success.")
                        // AccessToken 저장 또는 다른 로그인 후 처리
                        self.kakaoAccessUserInfo().sink(
                            receiveCompletion: { completion in
                                if case .failure(let error) = completion {
                                    promise(.failure(error))
                                }
                            },
                            receiveValue: { id in
                                promise(.success(id))
                            }
                        ).store(in: &self.cancellables)
                    }
                }
            }
        }
    }
    
    func kakaoAccessUserInfo() -> Future<String, LOGIN_ERROR> {
        return Future { promise in
            UserApi.shared.me { user, error in
                if let error = error {
                    printLog("[ERROR] Kakao me: \(error)")
                    promise(.failure(.init(caseType: .KAKAO_ACC_USER,
                                           message: "\(error.localizedDescription)")))
                }
                else if let user = user, let id = user.id {
                    printLog("Access Kakao UserInfo")
                    promise(.success("\(id)"))
                }
                else {
                    promise(.failure(.init(caseType: .KAKAO_ACC_USER,
                                           message: "undefined ERROR")))
                }
            }
            
        }
    }
}
extension Login: ASAuthorizationControllerDelegate {
    func tryAppleLogin() -> Future<String, LOGIN_ERROR> {
        return Future { promise in
            let request = ASAuthorizationAppleIDProvider().createRequest()
//            request.requestedScopes = [.fullName, .email]
            
            let controller = ASAuthorizationController(authorizationRequests: [request])
            controller.delegate = self
            controller.presentationContextProvider = self
            // 이거를 써야지 로그인 창이 뜹니다
            controller.performRequests()
            
            self.currentPromise = promise
        }
    }
    
    func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) {
        printLog("APPLE success")
        if let credential = authorization.credential as? ASAuthorizationAppleIDCredential {
            let userId = credential.user
            currentPromise?(.success(userId))
        } else {
            currentPromise?(.failure(.init(caseType: .APPLE_LOGIN, message: "로그인 실패")))
        }
        currentPromise = nil
    }
    
    func authorizationController(controller: ASAuthorizationController, didCompleteWithError error: any Error) {
        currentPromise?(.failure(.init(caseType: .APPLE_LOGIN, message: "\(error.localizedDescription)")))
        currentPromise = nil
    }
}

extension Login: ASAuthorizationControllerPresentationContextProviding{
    func presentationAnchor(for controller: ASAuthorizationController) -> ASPresentationAnchor {
        
        guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene else {
            return ASPresentationAnchor()
        }
        
        // Return the first window of the window scene
        return windowScene.windows.first { $0.isKeyWindow } ?? ASPresentationAnchor()
    }
}

extension Login {
    
    
    func sendCodeToPhone() {
        PhoneAuthProvider.provider().verifyPhoneNumber("+821034523551", uiDelegate: nil) { verificationID, error in
            if let error = error {
                print("Error: \(error.localizedDescription)")
                return
            }
            
//            self.verificationID = verificationID
            UserDefaults.standard.set(verificationID, forKey: "authVerifyID")
            printLog(verificationID)
        }
    }
    
    func verifyCode(code: String) {
        printLog(code)
        //            let verificationID = UserDefaults.standard.string(forKey: "authVerifyID")
        guard let verificationID = UserDefaults.standard.string(forKey: "authVerifyID") else {
            printLog("Please request verification code first.")
            return
        }
        
        let credential = PhoneAuthProvider.provider().credential(
            withVerificationID: verificationID,
            verificationCode: code
        )
        
        
        printLog(credential)
    }
    
}
