import APIClient
import ComponentLibrary
import ComposableArchitecture
import FeatureClipList
import FeaturePlaylistDetail
import NavigationRouterClient
import StatsigClient
import SwiftUI
import Utilities

@Reducer
public struct Playlists {
    @Reducer(state: .equatable)
    public enum Destination {
        case playlistDetail(PlaylistDetail)
    }

    @ObservableState
    public struct State: Equatable {
        @Presents public var destination: Destination.State?
        @ObservationStateIgnored @ObservedBox var playlistList: PlaylistList.State

        let section: PlaylistListSection
        @Shared var me: Me

        public init(section: PlaylistListSection, me: Shared<Me>) {
            self.section = section
            self._me = me

            let items = section.items
                .enumerated()
                .map { PlaylistListItem.State(playlist: $1, position: $0) }

            self.playlistList = .init()
            self.playlistList.playlists = .init(uniqueElements: items)
            // Update with same loaded items so we don't try to load more on end of page
            self.playlistList.pages.update(items, hasAllResults: true)
        }
    }

    public enum Action {
        case destination(PresentationAction<Destination.Action>)
        case playlistList(PlaylistList.Action)
        case dismiss
    }

    public init() {}

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

    public var body: some ReducerOf<Self> {
        Scope(state: \.playlistList, action: \.playlistList) {
            PlaylistList()
        }
        .withPlaylistListClient { _ in
            .init(getPlaylists: { _ in [] })
        }

        Reduce { state, action in
            switch action {
            case .dismiss:
                return .run { _ in await self.dismiss() }

            case .playlistList(.playlists(.element(_, action: .playlistTapped(let playlist)))):
                navigationRouter.sendIfNavV2(route: .playlist(playlist), else: {
                    state.destination = .playlistDetail(.init(me: state.$me, source: .playlist(playlist)))
                })
                return .none

            case .playlistList, .destination:
                // Catch-all
                return .none
            }
        }
        .ifLet(\.$destination, action: \.destination)
    }
}

public struct PlaylistsScreen: View {
    @Bindable var store: StoreOf<Playlists>
    @State private var headerVisible = true

    public init(store: StoreOf<Playlists>) {
        self.store = store
    }

    public var body: some View {
        List {
            Section(header: header) {
                PlaylistListContent(store: store.scope(state: \.playlistList, action: \.playlistList)) { _, item in
                    item
                }
            }
            .listRowBackground(Color.clear)
            .listSectionSeparator(.hidden, edges: .top)
            .listSectionSpacing(.zero)
            .listRowInsets(.init())
            .textCase(nil)
        }
        .listStyle(.grouped)
        .scrollContentBackground(.hidden)
        .contentMargins(.horizontal, 12, for: .scrollContent)
        .background(Color.SemanticV1.backgroundPrimary)
        .navigationBarBackButtonHidden()
        .toolbar {
            ToolbarItem(placement: .principal) {
                ToolbarTitle(store.section.title, visibility: !headerVisible)
            }
        }
        .navigationDestination(item: $store.scope(state: \.destination?.playlistDetail, action: \.destination.playlistDetail)) { store in
            PlaylistDetailScreen(store: store)
                .toolbar {
                    ToolbarItem(placement: .topBarLeading) {
                        ToolbarButton(.back, background: Material.ultraThin, colorScheme: store.averageColors.colorScheme) {
                            store.send(.dismiss)
                        }
                    }
                }
        }
    }

    private var header: some View {
        VStack(alignment: .leading, spacing: 0) {
            Text(store.section.title)
                .typographyV1(.headline1)
                .foregroundStyle(Color.SemanticV1.textPrimary)

            if let description = store.section.description, !description.isEmpty {
                Text(description)
                    .typographyV1(.body1.neueMontrealRegular())
                    .foregroundStyle(Color.SemanticV1.textSecondary)
            }
        }
        .padding(.top, 32)
        .padding(.bottom, 24)
        .onAppear { headerVisible = true }
        .onDisappear { headerVisible = false }
    }
}
