import APIClient
import ComponentLibrary
import ComposableArchitecture
import Localization
import SwiftUI

public typealias SortBy = Paths.Playlist.WithPlaylistId.GetParameters.SortBy
public typealias SortOrder = Paths.Playlist.WithPlaylistId.GetParameters.SortOrder

@Reducer
public struct PlaylistSortingMenu {
    @ObservableState
    public struct State: Equatable {
        var sortBy: SortBy?
        var sortOrder: SortOrder

        public init(sortBy: SortBy? = nil, sortOrder: SortOrder = SortOrder.desc) {
            self.sortBy = sortBy
            self.sortOrder = sortOrder
        }
    }

    public enum Action {
        case sortBySelected(SortBy?)
        case sortOrderSelected(SortOrder)
        case delegate(Delegate)

        public enum Delegate: Equatable {
            case onAppear
            case sortByChanged(SortBy?)
            case sortOrderChanged(SortOrder)
        }
    }

    public init() {}

    public var body: some ReducerOf<Self> {
        Reduce { state, action in
            switch action {
            case let .sortBySelected(sortBy):
                state.sortBy = sortBy
                return .send(.delegate(.sortByChanged(sortBy)))

            case let .sortOrderSelected(sortOrder):
                state.sortOrder = sortOrder
                return .send(.delegate(.sortOrderChanged(sortOrder)))

            case .delegate:
                return .none
            }
        }
    }
}

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

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

    public var body: some View {
        Menu {
            // Looks weird on iOS 18.0 and below
            if #available(iOS 26.0, *) {
                Label(title: {
                    Text(L10n.FeaturePlaylistMoreMenu.sortBy)
                }, icon: {
                    Image.Icon.sort
                })
                
                Divider()
            }

            sortByMenu
                .onAppear {
                    store.send(.delegate(.onAppear))
                }

            if store.sortBy != nil {
                Divider()
                sortOrderMenu
            }
        } label: {
            label
        }
        .menuActionDismissBehavior(.disabled)
    }

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

    @ViewBuilder
    private var sortByMenu: some View {
        sortByButton(nil)
        sortByButton(SortBy.createdAt)
        sortByButton(SortBy.upvoteCount)
        sortByButton(SortBy.playCount)
        sortByButton(SortBy.title)
    }

    @ViewBuilder
    private var sortOrderMenu: some View {
        sortOrderButton(SortOrder.asc)
        sortOrderButton(SortOrder.desc)
    }

    private func sortByButton(_ sortBy: SortBy?) -> some View {
        Toggle(isOn: .init(get: {
            store.sortBy == sortBy
        }, set: { isOn in
            if isOn {
                store.send(.sortBySelected(sortBy))
            }
        }), label: {
            if let sortBy {
                Text(sortBy.sortByDisplayName)
            } else {
                Text(L10n.FeaturePlaylistMoreMenu.sortDefault)
            }
        })
    }

    private func sortOrderButton(_ sortOrder: SortOrder) -> some View {
        Toggle(isOn: .init(get: {
            store.sortOrder == sortOrder
        }, set: { isOn in
            if isOn {
                store.send(.sortOrderSelected(sortOrder))
            }
        }), label: {
            Text(sortOrder.sortOrderDisplayName(for: store.sortBy))
        })
    }

    private var sortOrderTitle: String {
        store.sortOrder.sortOrderDisplayName(for: store.sortBy)
    }
}

#Preview {
    PlaylistSortingMenuView(
        store: Store(
            initialState: PlaylistSortingMenu.State(sortBy: SortBy.createdAt, sortOrder: SortOrder.desc)
        ) {
            PlaylistSortingMenu()
        }
    )
}
