import APIClient
import ComponentLibrary
import ComposableArchitecture
import Errors
import FeatureBrandedAlert
import GenAPI
import Localization
import SwiftUI
import Utilities

public struct EditDisplayedLyricsView: View {
    @Bindable var store: StoreOf<EditDisplayedLyricsReducer>
    @FocusState var focusedField: EditDisplayedLyricsState.Field?
    private let characterLimit = 7500
    @State private var lyrics: String

    public init(store: StoreOf<EditDisplayedLyricsReducer>) {
        self.store = store
        self._lyrics = State(initialValue: store.lyricsField.currentValue)
    }

    public var body: some View {
        ZStack {
            TextEditor(text: $lyrics.limit(characterLimit))
                .lineSpacing(1.25)
                .contentMargins(.horizontal, 18)
                .focused($focusedField, equals: .lyrics)
                .typographyV1(.bodySmall.lineHeight(20).size { _ in 16.0 })
                .foregroundStyle(Color.SemanticV1.textPrimary)
                .multilineTextAlignment(.leading)
                .scrollContentBackground(.hidden)
                .accentColor(.SemanticV1.textLink)
                .background(Color.SemanticV1.backgroundPrimary)
                .scrollDismissesKeyboard(.interactively)
                .overlay(alignment: .topLeading) {
                    placeholder
                        .opacity(showPlaceholder ? 1 : 0)
                }
            CharCount(text: lyrics, limit: characterLimit, background: Material.ultraThin)
                .opacity(showCharacterCount ? 1 : 0)
                .animation(.easeInOut(duration: 0.5), value: showCharacterCount)
                .padding([.bottom, .trailing], 16)
                .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .bottomTrailing)
        }
        .padding(.top, 24)
        .background(Color.SemanticV1.backgroundPrimary)
        .navigationBarTitleDisplayMode(.inline)
        .toolbar {
            ToolbarItem(placement: .topBarLeading) {
                dismissButton
            }
            ToolbarItem(placement: .principal) {
                navigationTitle
            }
            ToolbarItem(placement: .topBarTrailing) {
                saveButton
            }
        }
        .onTapGesture {
            focusedField = nil
        }
        .bind($store.focusedField, to: $focusedField)
        .alert($store.scope(state: \.destination?.alert, action: \.destination.alert))
        .brandedAlert(error: $store.error) {
            store.send(.clearError)
        }
        .sensoryFeedbackIfEnabled(.success, trigger: store.toggleHapticSuccess)
        .sensoryFeedbackIfEnabled(.warning, trigger: store.toggleHapticError)
    }

    private var placeholder: some View {
        Text(L10n.FeatureManageClip.displayedLyricsPlaceholder.appending("..."))
            .typographyV1(.bodySmall.lineHeight(20).size { _ in 16.0 })
            .foregroundStyle(Color.SemanticV2.foregroundInactive)
            .lineSpacing(1.25)
            .padding(.horizontal, 18)
    }

    private var navigationTitle: some View {
        Text(L10n.FeatureManageClip.displayedLyrics)
            .typographyV1(.headline4.size { _ in 16.0 }.lineHeight(20.0))
            .foregroundStyle(Color.SemanticV2.foregroundPrimary)
    }

    private var isDisabled: Bool {
        return store.clip.prompt.ifNotEmpty == nil && lyrics.isEmpty
    }

    private var showCharacterCount: Bool {
        // Show character limit when we're at 6000 characters or more
        let characterLimitWarningAt = characterLimit - 1500
        guard characterLimitWarningAt > 0 else { return false }
        return lyrics.count >= characterLimitWarningAt
    }

    private var showPlaceholder: Bool {
        lyrics.isEmpty && focusedField == nil
    }

    private var hasUnsavedChanges: Bool {
        return lyrics != store.lyricsField.initialValue
    }

    @ViewBuilder
    private var dismissButton: some View {
        ToolbarButton(.chevronLeft, color: Color.SemanticV2.foregroundPrimary, background: Color.SemanticV1.backgroundQuaternary) {
            store.send(.updateLyrics(lyrics))
            store.send(.dismissTapped)
        }
        .allowsHitTesting(true)
    }

    @ViewBuilder
    private var saveButton: some View {
        let color = hasUnsavedChanges ? Color.SemanticV2.backgroundPrimary : Color.SemanticV2.foregroundInactive
        ToolbarButton(store.isSaving ? .loading : .checkmark,
            color: color,
            background: Color.SemanticV2.foregroundPrimary,
            prominent: hasUnsavedChanges
        ) {
            guard !store.isSaving, hasUnsavedChanges else { return }
            store.send(.updateLyrics(lyrics))
            store.send(.saveTapped)
            focusedField = nil
        }
        .disabled(!hasUnsavedChanges || store.isSaving)
    }
}
