import APIClient
import ComposableArchitecture
import Foundation
import SwiftUI
import Utilities

public struct ClipListClient {
    public typealias GetClips = @Sendable (_ page: Int) async throws -> [Clip]
    public typealias GetClipsV2 = @Sendable (_ page: Int) async throws -> ClipsFeed

    public var getClips: GetClips
    public var getClipsV2: GetClipsV2
    public let isV2: Bool

    public init(getClips: @escaping GetClips) {
        self.getClips = getClips
        self.isV2 = false
        self.getClipsV2 = { _ in
            assertionFailure("Call init(getClipsV2:) instead")
            return .init(clips: [], currentPage: 0, totalResults: 0)
        }
    }

    public init(getClipsV2: @escaping GetClipsV2) {
        self.isV2 = true
        self.getClipsV2 = getClipsV2
        self.getClips = { _ in
            assertionFailure("Call init(getClips:) instead")
            return []
        }
    }
}

extension ClipListClient: DependencyKey {
    public static var liveValue: ClipListClient {
        .init(getClips: { _ in fatalError("Must be overridden by consuming Reducer") })
    }
}

public extension Reducer {
    func withClipListClient(_ factory: @escaping (State) -> ClipListClient) -> ReducerReader<State, Action, _DependencyKeyWritingReducer<Self>> {
        return .init { state, _ in
            self.transformDependency(\.self) { dependency in
                dependency[ClipListClient.self] = factory(state)
            }
        }
    }
}

public struct ProfileListClient {
    public typealias GetProfiles = @Sendable (_ page: Int) async throws -> [SimpleProfile]

    public var getProfiles: GetProfiles

    public init(getProfiles: @escaping GetProfiles) {
        self.getProfiles = getProfiles
    }
}

extension ProfileListClient: DependencyKey {
    public static var liveValue: ProfileListClient {
        .init(getProfiles: { _ in fatalError("Must be overridden by consuming Reducer") })
    }
}

public extension Reducer {
    func withProfileListClient(_ factory: @escaping (State) -> ProfileListClient) -> ReducerReader<State, Action, _DependencyKeyWritingReducer<Self>> {
        return .init { state, _ in
            self.transformDependency(\.self) { dependency in
                dependency[ProfileListClient.self] = factory(state)
            }
        }
    }
}

public struct PlaylistListClient {
    public typealias GetPlaylists = @Sendable (_ page: Int) async throws -> [Playlist]

    public var getPlaylists: GetPlaylists

    public init(getPlaylists: @escaping GetPlaylists) {
        self.getPlaylists = getPlaylists
    }
}

extension PlaylistListClient: DependencyKey {
    public static var liveValue: PlaylistListClient {
        .init(getPlaylists: { _ in fatalError("Must be overridden by consuming Reducer") })
    }
}

public extension Reducer {
    func withPlaylistListClient(_ factory: @escaping (State) -> PlaylistListClient) -> ReducerReader<State, Action, _DependencyKeyWritingReducer<Self>> {
        return .init { state, _ in
            self.transformDependency(\.self) { dependency in
                dependency[PlaylistListClient.self] = factory(state)
            }
        }
    }
}
