//
//  ShareMastodonContext.swift
//  ShareExtension
//
//  Created by Shadowfacts on 4/17/23.
//  Copyright © 2023 Shadowfacts. All rights reserved.
//

import Pachyderm
import ComposeUI
import UserAccounts
import InstanceFeatures
import Combine

class ShareMastodonContext: ComposeMastodonContext, ObservableObject {
    let accountInfo: UserAccountInfo?
    let client: Client
    let instanceFeatures: InstanceFeatures
    
    @MainActor
    private var customEmojis: [Emoji]?
    
    @Published var ownAccount: Account?
    
    init(accountInfo: UserAccountInfo) {
        self.accountInfo = accountInfo
        self.client = Client(baseURL: accountInfo.instanceURL, accessToken: accountInfo.accessToken)
        self.instanceFeatures = InstanceFeatures()
        
        Task { @MainActor in
            async let instance = try? await run(Client.getInstance()).0
            async let nodeInfo: NodeInfo? = await withCheckedContinuation({ continuation in
                self.client.nodeInfo { response in
                    switch response {
                    case .success(let nodeInfo, _):
                        continuation.resume(returning: nodeInfo)
                    case .failure(_):
                        continuation.resume(returning: nil)
                    }
                }
            })
            guard let instance = await instance else { return }
            self.instanceFeatures.update(instance: InstanceInfo(instance: instance), nodeInfo: await nodeInfo)
        }
        
        Task { @MainActor in
            if let account = try? await run(Client.getSelfAccount()).0 {
                self.ownAccount = account
            }
        }
    }
    
    // MARK: ComposeMastodonContext
    
    func run<Result: Decodable & Sendable>(_ request: Request<Result>) async throws -> (Result, Pagination?) {
        return try await withCheckedThrowingContinuation({ continuation in
            client.run(request) { response in
                switch response {
                case .success(let result, let pagination):
                    continuation.resume(returning: (result, pagination))
                case .failure(let error):
                    continuation.resume(throwing: error)
                }
            }
        })
    }
    
    @MainActor
    func getCustomEmojis(completion: @escaping ([Emoji]) -> Void) {
        if let customEmojis {
            completion(customEmojis)
        } else {
            Task.detached { @MainActor in
                let emojis = (try? await self.run(Client.getCustomEmoji()).0) ?? []
                self.customEmojis = emojis
                completion(emojis)
            }
        }
    }
    
    func searchCachedAccounts(query: String) -> [AccountProtocol] {
        return []
    }
    
    func cachedRelationship(for accountID: String) -> RelationshipProtocol? {
        return nil
    }
    
    func searchCachedHashtags(query: String) -> [Hashtag] {
        return []
    }
    
    func storeCreatedStatus(_ status: Status) {
    }
}
