import APIClient
import ComponentLibrary
import ComposableArchitecture
import Localization
import SwiftUI

@Reducer
public struct PlaylistMoreMenu {
    @ObservableState
    public struct State: Equatable {
        @Presents var alert: AlertState<Action.Alert>?
        var playlistId: String
        var isPublic: Bool

        public init(playlistId: String, isPublic: Bool) {
            self.playlistId = playlistId
            self.isPublic = isPublic
        }
    }

    public enum Action {
        case alert(PresentationAction<Alert>)
        case deletePlaylistTapped
        case renamePlaylistTapped
        case changeCoverImageTapped
        case changeVisibilityTapped
        case delegate(Delegate)
        case `internal`(Internal)

        public enum Alert: Equatable {
            case confirmDeletion
        }

        public enum Delegate {
            case onAppear
            case confirmDeletion
            case renamePlaylist
            case toggleVisibility
        }

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

    @Dependency(APIClient.self) private var apiClient
    @Dependency(\.dismiss) private var dismiss

    public init() {}

    public var body: some ReducerOf<Self> {
        Reduce { state, action in
            switch action {
            case .changeVisibilityTapped:
                return .run { [playlistId = state.playlistId, isPublic = state.isPublic] send in
                    await send(.internal(.toggleVisibilityResponse(Result(catching: {
                        try await apiClient.setPlaylistVisibility(playlistId, !isPublic)
                    }))))
                }

            case .internal(.toggleVisibilityResponse(.success)):
                state.isPublic.toggle()
                return .run { send in
                    await send(.delegate(.toggleVisibility))
                }

            case .deletePlaylistTapped:
                state.alert = .confirmDeletion
                return .none

            case .renamePlaylistTapped:
                return .send(.delegate(.renamePlaylist))

            case .changeCoverImageTapped:
                return .none

            case .alert(.presented(.confirmDeletion)):
                return .send(.delegate(.confirmDeletion))

            case .alert, .delegate, .internal:
                return .none
            }
        }
        .ifLet(\.$alert, action: \.alert)
    }
}

extension AlertState where Action == PlaylistMoreMenu.Action.Alert {
    static let confirmDeletion = Self {
        TextState(L10n.FeaturePlaylistMoreMenu.deleteTitle)
    } actions: {
        ButtonState(role: .destructive, action: .confirmDeletion) {
            TextState(L10n.FeaturePlaylistMoreMenu.delete)
        }
    } message: {
        TextState(L10n.FeaturePlaylistMoreMenu.deleteMessage)
    }
}

public struct PlaylistMoreMenuView: View {
    @Bindable var store: StoreOf<PlaylistMoreMenu>
    let showHeader: Bool
    let colorScheme: ColorScheme?

    public init(store: StoreOf<PlaylistMoreMenu>, showHeader: Bool = true, colorScheme: ColorScheme? = nil) {
        self.store = store
        self.showHeader = showHeader
        self.colorScheme = colorScheme
    }

    public var body: some View {
        Menu {
            Group {
                renamePlaylistRow
                changeVisibilityRow
                deletePlaylistRow
            }
            .onAppear {
                store.send(.delegate(.onAppear))
            }
        } label: {
            label
        }
        .alert($store.scope(state: \.alert, action: \.alert))
    }

    @ViewBuilder
    private var label: some View {
        if #available(iOS 26.0, *) {
            Image.Icon.moreHorizontal
        } else {
            let background = showHeader ? AnyShapeStyle(.ultraThinMaterial) : AnyShapeStyle(.clear)
            ToolbarButton(.moreHorizontal, background: background, colorScheme: colorScheme) {
                // No action needed, handled by Menu
            }
        }
    }

    private var renamePlaylistRow: some View {
        menuRow(title: L10n.FeaturePlaylistMoreMenu.renamePlaylist, icon: Image.Icon.penField) {
            store.send(.renamePlaylistTapped)
        }
    }

    private var changeCoverRow: some View {
        menuRow(title: L10n.FeaturePlaylistMoreMenu.changeCover, icon: Image.Icon.images) {
            store.send(.changeCoverImageTapped)
        }
    }

    @ViewBuilder
    private var changeVisibilityRow: some View {
        if store.isPublic {
            menuRow(title: L10n.FeaturePlaylistMoreMenu.makePrivate, icon: Image.Icon.lockKeyhole) {
                store.send(.changeVisibilityTapped)
            }
        } else {
            menuRow(title: L10n.FeaturePlaylistMoreMenu.makePublic, icon: Image.Icon.globe) {
                store.send(.changeVisibilityTapped)
            }
        }
    }

    private var deletePlaylistRow: some View {
        menuRow(title: L10n.FeaturePlaylistMoreMenu.deletePlaylist, icon: .Icon.trashV1, role: .destructive) {
            store.send(.deletePlaylistTapped)
        }
    }

    func menuRow(title: String, icon: Image, role: ButtonRole? = nil, action: @escaping () -> Void) -> some View {
        Button(role: role, action: action) {
            Label(title: {
                Text(title)
            }, icon: {
                icon
            })
        }
    }
}
