//
//  DataModel.swift
//  Comedores Sociales
//
//  Created by Hector Carrion on 11/8/20.
//

import Foundation

let serverAddress: String = "http://161.35.60.201/"

class Authentication: Codable {
    var correo: String
    var password: String
    
    init(email: String, password: String) {
        self.correo = email
        self.password = password
    }
    
    func isComplete() -> Bool {
        if correo != "" && password != "" {
            return true
        } else {
            return false
        }
    }
}

class Registration: Codable {
    var username: String
    var password: String
    var nombre: String
    var urbanizacion: String
    var calle: String
    var pueblo: String
    var cpostal: String
    var telefono: String
    var correo: String
    var organizacion: String?
    var puesto: String?
    
    init(email: String, password: String, name: String, urb: String, street: String, city: String, zip: String, phone: String, org: String? = nil, position: String? = nil) {
        if org != "" {
            self.username = email
            self.password = password
            self.nombre = name
            self.urbanizacion = urb
            self.calle = street
            self.pueblo = city
            self.cpostal = zip
            self.telefono = phone
            self.correo = email
            self.organizacion = org
            self.puesto = position
            
        } else {
            self.username = email
            self.password = password
            self.nombre = name
            self.urbanizacion = urb
            self.calle = street
            self.pueblo = city
            self.cpostal = zip
            self.telefono = phone
            self.correo = email
            self.organizacion = nil
            self.puesto = nil
        }
    }
    
    func isComplete() -> Bool {
        if username != "" && password != "" && nombre != "" && urbanizacion != "" && calle != "" && pueblo != "" && cpostal != "" && telefono != "" && correo != "" {
            return true
        } else {
            return false
        }
    }
}

enum Response {
    case success
    case failure
    case loading
    case unfetched
}

struct UserToken: Codable {
    let token: String
}

func getToken(input: String) -> UserToken {
    let JSONData = input.data(using: .utf8)!
    let token: UserToken = try! JSONDecoder().decode(UserToken.self, from: JSONData)
    return token
}

struct UserDetails: Codable {
    let correo: String
    let nombre: String
    let organizacion: String?
    let puesto: String?
    let calle: String
    let pueblo: String
    let cpostal: String
    let telefono: String
    let membresia: String?
    let vigencia: String?
    let horas_trabajadas: String?
}

func getUserDetails(input: String) -> UserDetails {
    let JSONData = input.data(using: .utf8)!
    let info: UserDetails = try! JSONDecoder().decode(UserDetails.self, from: JSONData)
    return info
}

class LoginViewModel: ObservableObject {
    @Published var response: Response = .unfetched
    
    func changeResponse(response: Bool) {
        if response == true {
            self.response = .success
        } else {
            self.response = .failure
        }
    }
    
    func login(data: Authentication) {
        self.response = .loading
        
        let service = "api/login.php"
        guard let encodedData = try? JSONEncoder().encode(data)
        else {
            print("Failed to encode login request")
            return
        }
        
        //print("JSON to send:", String(data: encodedData, encoding: .utf8)!)
        
        let url = URL(string: serverAddress + service)!
        var request = URLRequest(url: url)
        request.setValue("applogin/json", forHTTPHeaderField: "Content-Type")
        request.httpMethod = "POST"
        request.httpBody = encodedData
        
        URLSession.shared.dataTask(with: request) {data, response, error in
            
            //handle result here
            guard let data = data
            else {
                print("No data in response: \(error?.localizedDescription ?? "Unknown error").")
                return
            }
            print(response ?? "No response")
            print("Recieved data:", data)
            print(error ?? "No error")
            
            if let httpResponse = response as? HTTPURLResponse {
                DispatchQueue.main.async {
                    if httpResponse.statusCode == 200 {
                        self.changeResponse(response: true)
                        // MARK: JSON Decoding
                        let dataString = NSString(data: data, encoding: String.Encoding.utf8.rawValue)! as String
                        let json = getToken(input: dataString)
                        
                        let defaults = UserDefaults.standard
                        defaults.set(json.token, forKey: "token")
                        defaults.set(true, forKey: "logged-in")
                    } else {
                        self.changeResponse(response: false)
                    }
                    
                }
            }
            
        }.resume()
    }
}

class RegisterViewModel: ObservableObject {
    @Published var response: Response = .unfetched
    
    func changeResponse(response: Bool) {
        if response == true {
            self.response = .success
        } else {
            self.response = .failure
        }
    }
    
    func register(data: Registration) {
        self.response = .loading
        
        let service = "signup.php"
        guard let encodedData = try? JSONEncoder().encode(data)
        else {
            print("Failed to encode register request")
            return
        }
        
        //print("Reg JSON to send:", String(data: encodedData, encoding: .utf8)!)
        
        let url = URL(string: serverAddress + service)!
        var request = URLRequest(url: url)
        request.setValue("appregister/json", forHTTPHeaderField: "Content-Type")
        request.httpMethod = "POST"
        request.httpBody = encodedData
        
        URLSession.shared.dataTask(with: request) {data, response, error in
            
            //handle result here
            guard let data = data
            else {
                print("No data in response: \(error?.localizedDescription ?? "Unknown error").")
                return
            }
            print(response ?? "No response")
            print("Recieved data:", data)
            print(error ?? "No error")
            
            if let httpResponse = response as? HTTPURLResponse {
                DispatchQueue.main.async {
                    if httpResponse.statusCode == 200 {
                        self.changeResponse(response: true)
                    } else {
                        self.changeResponse(response: false)
                    }
                }
            }
        }.resume()
    }
}


class ProfileViewModel: ObservableObject {
    @Published var profile: Profile = .default
    @Published var response: Response = .unfetched
    
    func changeResponse(response: Bool) {
        if response == true {
            self.response = .success
        } else {
            self.response = .failure
        }
    }
    
    func changeProfile(data: UserDetails) {
        self.profile.name = data.nombre
        self.profile.email = data.correo
        self.profile.phone = addDashes(phone: data.telefono)
        
        if data.membresia != "" {
            self.profile.membership = data.membresia ?? "No memebership recieved from server"
        }
        if (data.vigencia != nil) {
            self.profile.membershipStatus = .valid
        } else {
            self.profile.membershipStatus = .expired
        }
        
        if let hours = data.horas_trabajadas {
            self.profile.hoursWorked = Int(hours) ?? 0
        }
        
    }
    
    func fetchMember(token: UserToken) {
        self.response = .loading
        
        let service = "api/member.php"
        guard let encodedData = try? JSONEncoder().encode(token)
        else {
            print("Failed to encode login request")
            return
        }
        
        //print("JSON to send:", String(data: encodedData, encoding: .utf8)!)
        
        let url = URL(string: serverAddress + service)!
        var request = URLRequest(url: url)
        request.setValue("appmember/json", forHTTPHeaderField: "Content-Type")
        request.httpMethod = "POST"
        request.httpBody = encodedData
        
        URLSession.shared.dataTask(with: request) {data, response, error in
            
            //handle result here
            guard let data = data
            else {
                print("No data in response: \(error?.localizedDescription ?? "Unknown error").")
                return
            }
            print(response ?? "No response")
            print("Recieved data:", data)
            print(error ?? "No error")
            
            
            if let httpResponse = response as? HTTPURLResponse {
                DispatchQueue.main.async {
                    if httpResponse.statusCode == 200 {
                        // MARK: JSON Decoding
                        let dataString = NSString(data: data, encoding: String.Encoding.utf8.rawValue)! as String
                        let json = getUserDetails(input: dataString)
                        //print(json)
                        self.changeResponse(response: true)
                        self.changeProfile(data: json)
                    } else {
                        self.changeResponse(response: false)
                    }
                    
                }
            }
            
        }.resume()
    }
}

func addDashes(phone: String) -> String {
    var prettyPhone: String = ""
    var i = 0
    for number in phone {
        prettyPhone.append(number)
        if i == 2 || i == 5 {
            prettyPhone.append("-")
        }
        i += 1
    }
    return prettyPhone
}
