import APIClient
import ComponentLibrary
import ComposableArchitecture
import SwiftUI
import Utilities

@Reducer
public struct PlaylistRow {
    @ObservableState
    public struct State: Identifiable, Equatable {
        public var playlist: Playlist
        public let image: ImageSource

        public var id: Playlist.ID { playlist.id }

        var playlistImage: ImageSource {
            return playlist.isLikedPlaylist ? .likedPlaylist : image
        }

        public init(playlist: Playlist, image: ImageSource) {
            self.playlist = playlist
            self.image = image
        }
    }

    public enum Action {
        case deletePlaylist(Playlist)
        case delegate(Delegate)
        case `internal`(Internal)

        public enum Delegate {
            case selectPlaylist(Playlist)
            case moreTapped(Playlist)
        }

        public enum Internal {
            case deletePlaylistResponse(Playlist, Result<Void, Error>)
        }
    }

    @Dependency(APIClient.self) var apiClient
    @Dependency(\.telemetryClient) var telemetry

    public init() {}

    public var body: some ReducerOf<Self> {
        Reduce { state, action in
            switch action {
            case .deletePlaylist:
                return .run { [playlist = state.playlist] send in
                    await send(.internal(.deletePlaylistResponse(playlist, Result(catching: { try await apiClient.deletePlaylist(playlist.id) }))))
                }

            case .internal(.deletePlaylistResponse(_, .success)):
                return .none

            case .internal(.deletePlaylistResponse(_, .failure(let error))):
                log.telemetry.error(error)
                return .none

            case .delegate:
                // handled in parent
                return .none
            }
        }
    }
}

public struct PlaylistRowItem<TrailingView: View>: View {
    @Bindable var store: StoreOf<PlaylistRow>
    let trailingView: TrailingView
    let onLikedPlaylistTapped: (() -> Void)?

    public init(store: StoreOf<PlaylistRow>, @ViewBuilder trailingView: () -> TrailingView, onLikedPlaylistTapped: (() -> Void)? = nil) {
        self.store = store
        self.trailingView = trailingView()
        self.onLikedPlaylistTapped = onLikedPlaylistTapped
    }

    public var body: some View {
        PlaylistView(
            image: store.playlistImage,
            name: store.playlist.name,
            playlistId: store.playlist.id,
            clipCount: store.playlist.totalResults,
            trailingView: trailingView,
            isLikedPlaylist: store.playlist.isLikedPlaylist
        )
        .listRowInsets(.init(top: 0, leading: 0, bottom: 0, trailing: 0))
        .listRowBackground(Color.SemanticV1.backgroundPrimary)
        .alignmentGuide(.listRowSeparatorLeading) { d in
            d[.leading] + 24
        }
        .onTapGesture {
            if store.playlist.isLikedPlaylist {
                onLikedPlaylistTapped?()
            } else {
                store.send(.delegate(.selectPlaylist(store.playlist)))
            }
        }
        .swipeActions {
            Button(role: .destructive) {
                store.send(.deletePlaylist(store.playlist))
            } label: {
                Image.Icon.trashV1
            }
            .tint(.SemanticV1.iconWarning)
        }
    }
}
