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

@Reducer
public struct EditClip {
    @ObservableState
    public struct State: Equatable {
        enum Field: String, Hashable {
            case title
        }

        var focusedField: Field? = .title
        var title: String = ""
        var isUpdating = false

        let clip: Clip

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

    public enum Action: BindableAction {
        case binding(BindingAction<State>)
        case updateTapped
        case delegate(Delegate)
        case `internal`(Internal)
        case dismiss

        public enum Delegate {
            case updatedClip(Clip)
        }

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

    @Dependency(\.apiClientV2) var api
    @Dependency(\.telemetryClient) var telemetry
    @Dependency(\.dismiss) var dismiss

    public init() {}

    public var body: some ReducerOf<Self> {
        BindingReducer()
        Reduce<State, Action> { state, action in
            switch action {
            case .binding:
                // Catch-all
                return .none

            case .updateTapped:
                state.isUpdating = true
                return .run { [clip = state.clip, title = state.title] send in
                    let update = ClipMetadataSpec(title: title)
                    let result = await Result { try await api.updateClip(clip.id.remoteId, update) }
                    await send(.internal(.updateClipResponse(result, clip)))
                }

            case .internal(.updateClipResponse(.success, var clip)):
                clip.title = state.title
                return .concatenate(
                    .send(.delegate(.updatedClip(clip))),
                    .send(.dismiss)
                )

            case .internal(.updateClipResponse(.failure(let error), _)):
                state.isUpdating = false
                log.telemetry.error(error)
                return .none

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

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

public struct EditClipScreen: View {
    @Bindable var store: StoreOf<EditClip>
    @FocusState var focusedField: EditClip.State.Field?
    private let nameLimit = 80

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

    public var body: some View {
        NavigationStack {
            VStack(spacing: 0) {
                Spacer()

                TextField(L10n.FeatureManageClip.titlePlaceholder, text: $store.title.limit(nameLimit), axis: .vertical)
                    .focused($focusedField, equals: .title)
                    .typographyV1(.headline1)
                    .foregroundStyle(Color.SemanticV1.textPrimary)
                    .multilineTextAlignment(.center)
                    .accentColor(.SemanticV1.textLink)
                    .padding(.horizontal, 24)

                Spacer()

                HStack {
                    Spacer()
                    CharCount(text: store.title, limit: nameLimit, background: Color.SemanticV1.backgroundQuaternary)
                }
                .padding(.bottom, 16)

                PrimaryButtonV1(
                    title: L10n.FeatureManageClip.save,
                    isLoading: store.isUpdating,
                    colorCombination: primaryButtonV1ColorCombinationDark,
                    preferredSize: .medium
                ) {
                    store.send(.updateTapped)
                }
                .disabled(store.title.isEmpty)
                .environment(\.colorScheme, .light)
            }
            .padding(.top, 24)
            .padding(.horizontal, 12)
            .padding(.bottom, 12)
            .sheetNavigationBar(
                leading: { EmptyView() },
                center: { ToolbarTitle(L10n.FeatureManageClip.navigationTitle) },
                trailing: {
                    ToolbarButton(.close, background: Color.SemanticV1.backgroundTertiary) {
                        store.send(.dismiss)
                    }
                }
            )
            .presentationCornerRadius(40, conditional: true)
            .background(Color.SemanticV1.backgroundPrimary)
            .bind($store.focusedField, to: $focusedField)
        }
    }
}
