//
//  LoginViewController.swift
//  Auth
//
//  Created by Adam Cseke on 2022. 02. 23..
//  Copyright (c) 2022. levivig. All rights reserved.
//
//  This file was generated by the 🐍 VIPER generator
//

import LocalAuthentication
import UIKit

final class LoginViewController: UIViewController {
    
    let localAuthenticationContext = LAContext()
    
    private var phoneNumber: String = "" {
        didSet {
            self.getData()
        }
    }
    private var password: String = ""
    
    private var titleLabel: UILabel!
    private var descriptionLabel: UILabel!
    private var loginTextfield: LoginTextField!
    private var loginButton: Button!
    private var biometricButton: UIButton!
    private var stackView: UIStackView!
    private var incorrectPasswordLabel: UILabel!
    private var forgotPasswordButton: UIButton!
    private var signOutButton: UIButton!
    private var changePhoneNumberButton: UIButton!
    
    // MARK: - Public properties -
    
    var presenter: LoginPresenterInterface!
    
    // MARK: - Lifecycle -
    
    override func viewDidLoad() {
        super.viewDidLoad()
        setup()
        presenter.viewDidLoad()
    }
    
    private func setup() {
        configureViewController()
        configureTitleLabel()
        configureDescriptionLabel()
        configureStackView()
        configureLoginTextfield()
        configureLoginButton()
        configureBiometricButton()
        configureIncorrectPassword()
        configureForgotPasswordButton()
        configureSignOutButton()
        hideKeyboardWhenTappedAround()
        configurePushUpView()
        getData()
        configureChangePhoneNumberButton()
    }
    
    private func configureViewController() {
        view.backgroundColor = Colors.background
    }
    
    private func configurePushUpView() {
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil)
    }
    
    private func configureTitleLabel() {
        titleLabel = UILabel()
        titleLabel.text = "LoginViewController.Title.Login".localized
        titleLabel.textColor = Colors.blackLabel
        titleLabel.textAlignment = .center
        titleLabel.font = UIFont(name: "Hind-Bold", size: 24)
        view.addSubview(titleLabel)
        
        titleLabel.snp.makeConstraints { make in
            if UIDevice.Devices.iPhoneSE1stGen {
                make.centerY.equalToSuperview().multipliedBy(0.35)
            } else {
                make.centerY.equalToSuperview().multipliedBy(0.5)
            }
            make.leading.equalToSuperview()
            make.centerX.equalToSuperview()
        }
    }
    
    private func configureDescriptionLabel() {
        descriptionLabel = UILabel()
        descriptionLabel.textColor = Colors.blackLabel
        descriptionLabel.numberOfLines = 5
        descriptionLabel.textAlignment = .center
        descriptionLabel.font = UIFont(name: "Hind-Regular", size: 15)
        view.addSubview(descriptionLabel)
        
        descriptionLabel.snp.makeConstraints { make in
            make.top.equalTo(titleLabel.snp.bottom).offset(10)
            make.leading.equalToSuperview().offset(32)
            make.centerX.equalToSuperview()
        }
    }
    
    private func configureStackView() {
        stackView = UIStackView()
        stackView.alignment = .center
        stackView.axis = .vertical
        stackView.spacing = 15
        stackView.distribution = .fill
        
        view.addSubview(stackView)
        
        stackView.snp.makeConstraints { make in
            
            make.leading.equalToSuperview()
            make.centerX.equalToSuperview()
        }
    }
    
    private func configureLoginTextfield() {
        loginTextfield = LoginTextField()
        loginTextfield.customDelegate = self
        loginTextfield.font = UIFont(name: "Hind-Regular", size: 20)
        loginTextfield.addTarget(self, action: #selector(textFieldEdidtingDidChange(_ :)), for: UIControl.Event.editingChanged)
        
        let placeholderAttributes: [NSAttributedString.Key: Any] = [
            NSAttributedString.Key.font: UIFont(name: "Hind-Regular", size: 16) ?? UIFont(),
            NSAttributedString.Key.foregroundColor: Colors.placeholder
        ]
        let attributedPlaceholder = NSMutableAttributedString(string: "LoginViewController.TextField.Placeholder".localized, attributes: placeholderAttributes)
        loginTextfield.attributedPlaceholder = attributedPlaceholder
        
        stackView.addArrangedSubview(loginTextfield)
        
        loginTextfield.snp.makeConstraints { make in
            make.top.equalTo(descriptionLabel.snp.bottom).offset(32)
            make.centerX.equalToSuperview()
            make.leading.equalToSuperview().offset(15)
            make.height.equalTo(50)
        }
    }
    
    @objc func textFieldEdidtingDidChange(_ textField :UITextField) {
        let textAttributes: [NSAttributedString.Key: Any] = [
            NSAttributedString.Key.font: UIFont(name: "Hind-Bold", size: 25) ?? UIFont(),
            NSAttributedString.Key.foregroundColor: Colors.button
        ]
        let attributedString = NSMutableAttributedString(string: loginTextfield.text ?? "", attributes: textAttributes)
        attributedString.addAttribute(NSAttributedString.Key.kern, value: CGFloat(5.0), range: NSRange(location: 0, length: attributedString.length))
        loginTextfield.attributedText = attributedString
    }
    
    private func configureLoginButton() {
        loginButton = Button()
        loginButton.bind( buttonLabelText: "LoginViewController.ButtonTitle".localized,
                          font: UIFont(name: "Hind-Bold", size: 16) ?? UIFont(),
                          textColor: .white)
        loginButton.addTarget(self, action: #selector(loginButtonTapped), for: .touchUpInside)
        
        stackView.addArrangedSubview(loginButton)
        
        loginButton.snp.makeConstraints { make in
            
            make.centerX.equalToSuperview()
            make.leading.equalToSuperview().offset(15)
            make.height.equalTo(50)
        }
    }
    
    @objc private func loginButtonTapped() {
        if loginTextfield.text == self.password {
            incorrectPasswordLabel.isHidden = true
            presenter.presentAlert(title: "Successfully logged in", description: "", buttonText: "Yay", alertImage: UIImage(named: "log-in")?.withTintColor(Colors.button) ?? UIImage())
            self.titleLabel.text = "LoginViewController.Title.LoggedIn".localized
            self.signOutButton.isHidden = false
            self.loginButton.isHidden = true
            self.biometricButton.isHidden = true
            self.loginButton.isHidden = true
            self.loginTextfield.isHidden = true
            self.forgotPasswordButton.isHidden = true
            print("Login was successful")
        } else {
            incorrectPasswordLabel.isHidden = false
            print("Login was unsuccessful")
        }
    }
    
    private func configureBiometricButton() {
        biometricButton = UIButton()
        biometricButton.backgroundColor = Colors.button
        biometricButton.layer.cornerRadius = 11
        
        let attributes: [NSAttributedString.Key: Any] = [
            NSAttributedString.Key.font: UIFont(name: "Hind-Regular", size: 16) ?? UIFont(),
            NSAttributedString.Key.foregroundColor: UIColor.white
        ]
        
        let touchID = NSTextAttachment()
        touchID.image = UIImage(systemName: "touchid")?.withTintColor(.white)
        let touchIdImageString = NSMutableAttributedString(attachment: touchID)
        
        let faceID = NSTextAttachment()
        faceID.image = UIImage(systemName: "faceid")?.withTintColor(.white)
        let faceIdImageString = NSMutableAttributedString(attachment: faceID)
        
        var textString = NSAttributedString()
        
        localAuthenticationContext.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: nil)
        
        let biometricType = localAuthenticationContext.biometryType == LABiometryType.faceID ? "Face ID" : "Touch ID"
        print("Supported Biometric type is: \( biometricType )")
        
        if biometricType == "Touch ID" {
            textString = NSAttributedString(string: "LoginViewController.BiometricButton.TouchID".localized, attributes: attributes)
            touchIdImageString.append(textString)
            biometricButton.setAttributedTitle(touchIdImageString, for: .normal)
        } else if biometricType == "Face ID" {
            textString = NSAttributedString(string: "LoginViewController.BiometricButton.FaceID".localized, attributes: attributes)
            faceIdImageString.append(textString)
            biometricButton.setAttributedTitle(faceIdImageString, for: .normal)
        }
        
        biometricButton.addTarget(self, action: #selector(biometricButtonTapped), for: .touchUpInside)
        
        stackView.addArrangedSubview(biometricButton)
        
        biometricButton.snp.makeConstraints { make in
            make.centerX.equalToSuperview()
            make.leading.equalToSuperview().offset(15)
            make.height.equalTo(50)
        }
    }
    
    @objc private func biometricButtonTapped() {
        startAuthentication()
    }
    
    private func configureIncorrectPassword() {
        incorrectPasswordLabel = UILabel()
        incorrectPasswordLabel.text = "LoginViewController.IncorrectPassword".localized
        incorrectPasswordLabel.textAlignment = .center
        incorrectPasswordLabel.textColor = Colors.incorrectPassword
        incorrectPasswordLabel.numberOfLines = 2
        incorrectPasswordLabel.isHidden = true
        incorrectPasswordLabel.font = UIFont(name: "Hind-Regular", size: 16)
        
        stackView.addArrangedSubview(incorrectPasswordLabel)
        
        incorrectPasswordLabel.snp.makeConstraints { make in
            make.leading.equalToSuperview().offset(32)
            make.centerX.equalToSuperview()
        }
    }
    
    private func configureForgotPasswordButton() {
        forgotPasswordButton = UIButton()
        forgotPasswordButton.backgroundColor = .clear
        forgotPasswordButton.addTarget(self, action: #selector(forgotPasswordButtonTapped), for: .touchUpInside)
        stackView.addArrangedSubview(forgotPasswordButton)
        
        let attributes: [NSAttributedString.Key: Any] = [
            NSAttributedString.Key.font: UIFont(name: "Hind-Regular", size: 16) ?? UIFont(),
            NSAttributedString.Key.foregroundColor: UIColor.blue,
            NSAttributedString.Key.underlineStyle: NSUnderlineStyle.single.rawValue
        ]
        
        let attributeString = NSMutableAttributedString(
            string: "LoginViewController.ForgotPassword".localized,
            attributes: attributes
        )
        forgotPasswordButton.setAttributedTitle(attributeString, for: .normal)
        forgotPasswordButton.snp.makeConstraints { make in
            make.leading.equalToSuperview().offset(32)
            make.centerX.equalToSuperview()
        }
    }
    
    @objc private func forgotPasswordButtonTapped() {
        presenter.presentAlert(title: "LoginViewController.ForgotPasswordButton.Title".localized,
                               description: "LoginViewController.ForgotPasswordButton.Description".localized,
                               buttonText: "LoginViewController.ForgotPasswordButton.ButtonTitle".localized,
                               alertImage: UIImage(named: "sad")?.withTintColor(Colors.button) ?? UIImage())
        
    }
    
    @objc func keyboardWillShow(notification: NSNotification) {
        if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
            if self.view.frame.origin.y == 0 {
                self.view.frame.origin.y -= keyboardSize.height * 0.30
            }
        }
    }
    
    @objc func keyboardWillHide(notification: NSNotification) {
        if self.view.frame.origin.y != 0 {
            self.view.frame.origin.y = 0
        }
    }
    
    private func configureSignOutButton() {
        signOutButton = UIButton()
        signOutButton.isHidden = true
        signOutButton.addTarget(self, action: #selector(signOutButtonTapped), for: .touchUpInside)
        
        let attributes: [NSAttributedString.Key: Any] = [
            NSAttributedString.Key.font: UIFont(name: "Hind-Regular", size: 16) ?? UIFont(),
            NSAttributedString.Key.foregroundColor: UIColor.blue,
            NSAttributedString.Key.underlineStyle: NSUnderlineStyle.single.rawValue
        ]
        
        signOutButton.tintColor = Colors.button
        let attributeString = NSMutableAttributedString(
            string: "LoginViewController.SignOut".localized,
            attributes: attributes
        )
        signOutButton.backgroundColor = .clear
        signOutButton.setAttributedTitle(attributeString, for: .normal)
        stackView.addArrangedSubview(signOutButton)
        
        signOutButton.snp.makeConstraints { make in
            make.leading.equalToSuperview().offset(32)
            make.centerX.equalToSuperview()
        }
    }
    
    @objc private func signOutButtonTapped() {
        self.loginTextfield.text = ""
        self.titleLabel.text = "LoginViewController.Title.Login".localized
        self.signOutButton.isHidden = true
        self.loginButton.isHidden = false
        self.biometricButton.isHidden = false
        self.loginButton.isHidden = false
        self.loginTextfield.isHidden = false
        self.forgotPasswordButton.isHidden = false
        self.loginButton.isEnabled = false
    }
    
    private func getData() {
        guard let data = KeychainManager.shared.get(account: self.phoneNumber) else {
            print("Failed to read pawwsord")
            return
        }
        let password = String(decoding: data, as: UTF8.self)
        self.password = password
        print("Read password: \(password)")
    }
}

// MARK: - Extensions -

extension LoginViewController: LoginViewInterface {
    func setButton(enable: Bool) {
        if enable {
            loginButton.isEnabled = true
            loginButton.backgroundColor = Colors.button
        } else {
            loginButton.isEnabled = false
            loginButton.backgroundColor = Colors.button.withAlphaComponent(0.5)
        }
    }
    
    func pushPhoneNumber(phoneNumber: String) {
        if let savedUserData = UserDefaults.standard.object(forKey: "user") as? Data {
            let decoder = JSONDecoder()
            if let savedUser = try? decoder.decode(UserInfo.self, from: savedUserData) {
                self.phoneNumber = savedUser.phoneNumber
                print("Saved user: \(self.phoneNumber)")
                self.descriptionLabel.text = "\(savedUser.phoneNumber)"
            }
        }
        self.getData()
    }
    
    private func configureChangePhoneNumberButton() {
        changePhoneNumberButton = UIButton()
        changePhoneNumberButton.addTarget(self, action: #selector(changePhoneNumberButtonTapped), for: .touchUpInside)
        
        let attributes: [NSAttributedString.Key: Any] = [
            NSAttributedString.Key.font: UIFont(name: "Hind-Regular", size: 16) ?? UIFont(),
            NSAttributedString.Key.foregroundColor: UIColor.blue,
            NSAttributedString.Key.underlineStyle: NSUnderlineStyle.single.rawValue
        ]
        
        changePhoneNumberButton.tintColor = Colors.button
        let attributeString = NSMutableAttributedString(
            string: "Reset",
            attributes: attributes
        )
        changePhoneNumberButton.backgroundColor = .clear
        changePhoneNumberButton.setAttributedTitle(attributeString, for: .normal)
        view.addSubview(changePhoneNumberButton)
        
        changePhoneNumberButton.snp.makeConstraints { make in
            make.leading.equalToSuperview().offset(10)
            make.bottom.equalToSuperview().offset(-10)
        }
    }
    
    @objc private func changePhoneNumberButtonTapped() {
        presenter.signOutButtonTapped()
    }
}

extension LoginViewController: LoginTextFieldDelegate {
    func textfieldValueDidChange(text: String) {
        let text = loginTextfield.text ?? ""
        presenter.inputChanged(text: text)
    }
}

extension LoginViewController {
    func startAuthentication() {
        let context = LAContext()
        var error: NSError?
        if context.canEvaluatePolicy(.deviceOwnerAuthentication, error: &error) {
            let reason = "Please authorize!"
            context.evaluatePolicy(.deviceOwnerAuthentication, localizedReason: reason) { [weak self] success, error in
                DispatchQueue.main.async {
                    guard success, error == nil else {
                        return
                    }
                    self?.loginTextfield.text = self?.password
                    self?.loginButtonTapped()
                    print("Login was successful")
                }
            }
        } else {
            self.presenter.presentAlert(title: "LoginViewController.AlertViewController.Fingerprint.Title".localized,
                                        description: "LoginViewController.AlertViewController.BiometricAuth.Description.NotEnrolled".localized,
                                        buttonText: "Ok",
                                        alertImage: UIImage(named: "sad")?.withTintColor(Colors.button) ?? UIImage())
        }
    }
}
