import APIClient
import ComponentLibrary
import ComposableArchitecture
import Localization
import SwiftUI
import Utilities

@Reducer
public struct ReportOptions {
    public enum ReportOption: String, CaseIterable {
        case lowAudioQuality = "flag_audio_quality"
        case badLyrics = "flag_lyrics_following"
        case badInstructions = "flag_style_following"
        case poorStructure = "flag_song_structure"
        case other = "flag_other"

        var title: String {
            switch self {
            case .lowAudioQuality: L10n.FeatureClipDetail.reportAudioQuality
            case .badLyrics: L10n.FeatureClipDetail.reportFollowLyrics
            case .badInstructions: L10n.FeatureClipDetail.reportFollowStyle
            case .poorStructure: L10n.FeatureClipDetail.reportSongStructure
            case .other: L10n.FeatureClipDetail.reportOther
            }
        }
    }

    @ObservableState
    public struct State: Equatable {
        var options = ReportOption.allCases
        var selected: ReportOption = .lowAudioQuality
        var isReporting = false

        var clip: Clip
        public init(clip: Clip) {
            self.clip = clip
        }
    }

    public enum Action {
        case setSelection(ReportOption)
        case dismiss
        case reportTapped
        case `internal`(Internal)

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

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

    public init() {}

    public var body: some ReducerOf<Self> {
        Reduce { state, action in
            switch action {
            case let .setSelection(option):
                state.selected = option
                return .none

            case .reportTapped:
                state.isReporting = true
                return .run { [clip = state.clip, flag = state.selected.rawValue] send in
                    await send(.internal(.reportResponse(Result(catching: {
                        try await apiClient.updateFlag(clip, true, flag)
                    }))))
                }

            case .internal(.reportResponse(.success(()))):
                state.isReporting = false
                return .send(.dismiss)

            case let .internal(.reportResponse(.failure(error))):
                log.telemetry.error(error)
                return .none

            case .dismiss:
                return .run { _ in await dismiss() }

            case .internal:
                // Catch-All
                return .none
            }
        }
    }
}

public struct ReportOptionsScreen: View {
    @Bindable var store: StoreOf<ReportOptions>

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

    public var body: some View {
        NavigationStack {
            reportOptionsList
                .sheetNavigationBar(
                    leading: { EmptyView() },
                    center: { ToolbarTitle(L10n.FeatureClipDetail.reportQuality) },
                    trailing: {
                        ToolbarButton(.close, background: Color.SemanticV1.backgroundQuaternary) {
                            store.send(.dismiss)
                        }
                    }
                )
                .background(Color.SemanticV1.backgroundPrimary, ignoresSafeAreaEdges: .all)
                .presentationCornerRadius(40, conditional: true)
        }
    }

    private var reportOptionsList: some View {
        List(store.options, id: \.self) { option in
            Button {
                store.send(.setSelection(option))
            } label: {
                HStack {
                    Text(option.title)
                        .foregroundStyle(Color.SemanticV1.textBrand)

                    Spacer()

                    Circle()
                        .stroke(Color.SemanticV1.iconBrand, lineWidth: 0.5)
                        .fill(store.selected == option ? Color.SemanticV1.iconLink : Color.clear)
                        .frame(width: 24, height: 24)
                        .overlay {
                            if store.selected == option {
                                Image.Icon.checkV1
                                    .resizable()
                                    .scaledToFit()
                                    .frame(height: 16)
                                    .foregroundStyle(Color.SemanticV1.textOnDark)
                                    .transition(.scale.animation(.spring(duration: 0.3, bounce: 0.8)).combined(with: .opacity))
                            }
                        }
                        .animation(.bouncy, value: store.selected)
                        .sensoryFeedbackIfEnabled(.selection, trigger: store.selected)
                }
                .typographyV1(.body1)
            }
            .listRowBackground(Color.clear)
            .listRowSeparatorTint(Color.SemanticV1.backgroundTertiary)
        }
        .sensoryFeedbackIfEnabled(.selection, trigger: store.selected)
        .allowsHitTesting(!store.isReporting)
        .listStyle(.plain)
        .overlay(alignment: .bottom) {
            reportButton
        }
    }

    private var reportButton: some View {
        PrimaryButtonV1(title: L10n.FeatureClipDetail.report, isLoading: store.isReporting, colorCombination: .dark, preferredSize: .large) {
            store.send(.reportTapped)
        }
        .padding(12)
    }
}
