import BackendEnvironmentClient
import Foundation
import GenAPI
import SwiftData

public struct Profile: Equatable, Identifiable {
    public var id: String
    public var displayName: String?
    public var handle: String
    public var profileDescription: String?
    public var avatarImageUrl: String?
    public var clips: [Clip]
    public var stats: ProfileStats
    public var totalSongs: Int
    public var isFollowing: Bool
    public var hooks: [Hook] = []
    public var isBlocked: Bool
    public var hooksHiddenByUser: Bool

    public var shareURL: URL {
        let baseUrl = BackendEnvironmentProvider.currentConfiguration().webEndpointHost
        return URL(string: "https://\(baseUrl)/@\(handle)")!
    }

    init(_ remote: GenAPI.ProfileInfoSchema) throws {
        self.id = remote.userId
        self.displayName = remote.displayName
        self.handle = remote.handle ?? ""
        self.profileDescription = remote.profileDescription
        self.avatarImageUrl = remote.avatarImageUrl
        self.clips = try remote.clips.map { try Clip($0) }
        self.hooks = remote.hooks?.compactMap { try? Hook($0) } ?? []

        let statsDict: [String: Int]
        if case .object(let remoteStats) = remote.stats {
            statsDict = remoteStats.compactMapValues(\.intValue)
        } else {
            statsDict = [:]
            assertionFailure("Unexpeced ProfileInfoStats schema")
        }

        self.stats = ProfileStats(
            songs: remote.numTotalClips,
            statsDictionary: statsDict
        )
        self.totalSongs = remote.numTotalClips
        self.isFollowing = remote.isFollowing
        self.isBlocked = remote.viewerIsBlockingProfile ?? false
        self.hooksHiddenByUser = remote.viewerIsHidingCreatorHook ?? false
    }
}

public struct SimpleProfile: Equatable, Identifiable, Hashable {
    public var id: String
    public var externalUserId: String
    public var displayName: String
    public var handle: String
    public var avatarImageUrl: String?
    public var stats: SimpleProfileStats
    public var isFollowing: Bool

    init(_ remote: GenAPI.SimpleProfileInfoSchema) throws {
        self.id = remote.handle ?? UUID().uuidString
        self.externalUserId = remote.externalUserId
        self.displayName = remote.displayName ?? ""
        self.avatarImageUrl = remote.avatarImageUrl
        self.handle = remote.handle ?? ""
        self.stats = .init(
            clipsCount: remote.stats.clipsCount ?? 0,
            followersCount: remote.stats.followersCount ?? 0,
            likesCount: remote.stats.likesCount ?? 0,
            lastLogin: remote.stats.lastLogin ?? ""
        )
        self.isFollowing = remote.isFollowing
    }
}

public extension SimpleProfile {
    /// Create a SimpleProfile from a User with default stats
    init(from user: User, isFollowing: Bool = false) {
        self.id = user.id
        self.externalUserId = user.id
        self.displayName = user.displayName ?? ""
        self.handle = user.handle
        self.avatarImageUrl = user.avatarImageUrl
        self.stats = SimpleProfileStats(
            clipsCount: 0,
            followersCount: 0,
            likesCount: 0,
            lastLogin: ""
        )
        self.isFollowing = isFollowing
    }

    init(from profile: Profile) {
        self.id = profile.id
        self.externalUserId = profile.id
        self.displayName = profile.displayName ?? profile.handle
        self.handle = profile.handle
        self.avatarImageUrl = profile.avatarImageUrl
        self.stats = SimpleProfileStats(
            clipsCount: profile.stats.songs,
            followersCount: profile.stats.followersCount,
            likesCount: profile.stats.likes,
            lastLogin: ""
        )
        self.isFollowing = profile.isFollowing
    }

    init(
        id: String? = nil,
        displayName: String? = nil,
        handle: String,
        avatarImageUrl: String? = nil,
        stats: SimpleProfileStats = SimpleProfileStats(clipsCount: 0, followersCount: 0, likesCount: 0, lastLogin: ""),
        isFollowing: Bool = false
    ) {
        self.id = id ?? handle
        self.externalUserId = id ?? handle
        self.displayName = displayName ?? ""
        self.handle = handle
        self.avatarImageUrl = avatarImageUrl
        self.stats = stats
        self.isFollowing = isFollowing
    }
}

public struct SimpleProfileStats: Codable, Equatable, Hashable {
    public let clipsCount: Int?
    public let followersCount: Int?
    public let likesCount: Int?
    public let lastLogin: String?

    public init(clipsCount: Int?, followersCount: Int?, likesCount: Int?, lastLogin: String?) {
        self.clipsCount = clipsCount
        self.followersCount = followersCount
        self.likesCount = likesCount
        self.lastLogin = lastLogin
    }
}

public struct SimpleProfileWithPhoneNumber: Equatable {
    public var phoneNumber: String
    public var user: SimpleProfile

    init(_ remote: GenAPI.UserMobileProfileSchema) throws {
        self.phoneNumber = remote.phone
        self.user = try SimpleProfile(remote.profile)
    }
}
