//
//  UserAccountInfo.swift
//  UserAccounts
//
//  Created by Shadowfacts on 3/5/23.
//

import Foundation
import CryptoKit

public struct UserAccountInfo: Equatable, Hashable, Identifiable {
    public let id: String
    public let instanceURL: URL
    public let clientID: String
    public let clientSecret: String
    public private(set) var username: String!
    public let accessToken: String
    
    fileprivate static let tempAccountID = "temp"
    
    static func id(instanceURL: URL, username: String?) -> String {
        // We hash the instance host and username to form the account ID
        // so that account IDs will match across devices, allowing for data syncing and handoff.
        var hasher = SHA256()
        hasher.update(data: instanceURL.host!.data(using: .utf8)!)
        if let username {
            hasher.update(data: username.data(using: .utf8)!)
        }
        return Data(hasher.finalize()).base64EncodedString()
    }
    
    /// Only to be used for temporary MastodonController needed to fetch own account info and create final UserAccountInfo with real username
    public init(tempInstanceURL instanceURL: URL, clientID: String, clientSecret: String, accessToken: String) {
        self.id = UserAccountInfo.tempAccountID
        self.instanceURL = instanceURL
        self.clientID = clientID
        self.clientSecret = clientSecret
        self.accessToken = accessToken
    }
    
    init(instanceURL: URL, clientID: String, clientSecret: String, username: String? = nil, accessToken: String) {
        self.id = UserAccountInfo.id(instanceURL: instanceURL, username: username)
        self.instanceURL = instanceURL
        self.clientID = clientID
        self.clientSecret = clientSecret
        self.username = username
        self.accessToken = accessToken
    }
    
    init?(userDefaultsDict dict: [String: String]) {
        guard let id = dict["id"],
            let instanceURL = dict["instanceURL"],
            let url = URL(string: instanceURL),
            let clientID = dict["clientID"],
            let secret = dict["clientSecret"],
            let accessToken = dict["accessToken"] else {
                return nil
        }
        self.id = id
        self.instanceURL = url
        self.clientID = clientID
        self.clientSecret = secret
        self.username = dict["username"]
        self.accessToken = accessToken
    }
    
    /// A filename-safe string for this account
    public var persistenceKey: String {
        // slashes are not allowed in the persistent store coordinator name
        id.replacingOccurrences(of: "/", with: "_")
    }
    
    public func hash(into hasher: inout Hasher) {
        hasher.combine(id)
    }
    
    public static func ==(lhs: UserAccountInfo, rhs: UserAccountInfo) -> Bool {
        return lhs.id == rhs.id
    }
}
