import APIClient
import ComponentLibrary
import ComposableArchitecture
import Foundation
import Localization
import SunoModelClient
import SwiftUI

@Reducer
public struct ClipImageReducer {
    @ObservableState
    public struct State: Equatable {
        public enum ImageSource: Equatable {
            public enum LocalSourceType {
                case imported
                case takenByCamera
            }

            case local(image: UIImage, sourceType: LocalSourceType)
            case remote(uploadIds: [String], uploadURLs: [String])
        }

        public var image: ImageSource
        public var caption = ""
        public var captionFocused = false
        public var isCreating = false

        // Used to read modelMajorVersion in Analytics
        @Shared(.inMemory(.selectedSunoModel)) var selectedSunoModel: SunoModelMetaData = .modelDefault

        init(reusePrompt: Prompt? = nil, image: ImageSource) {
            self.image = image
            if let reusePrompt {
                self.caption = reusePrompt.text
            }
        }
    }

    public enum Action: BindableAction {
        case binding(BindingAction<State>)
        case didTapCreate
        case complete(uploadIds: [String], uploadURLs: [String])
        case setIsCreating(Bool)
        case hCaptchaTokenGenerationFailed

        case createImageFileResponse(UIImage, Result<UploadRequest, Error>)
        case uploadImageResponse([UploadRequest], Result<APIClient.UploadEvent, Error>)
    }

    public var body: some ReducerOf<Self> {
        BindingReducer()

        Reduce { state, action in
            switch action {
            case .didTapCreate: // Handled in parent
                return .send(.setIsCreating(true))

            case .complete:
                // Catch-all
                return .none

            case .binding:
                return .none

            case .setIsCreating(let isCreating):
                state.isCreating = isCreating
                return .none

            case .createImageFileResponse, .uploadImageResponse:
                // Handled in parent reducer
                return .none

            case .hCaptchaTokenGenerationFailed:
                state.isCreating = false
                return .none
            }
        }

        Analytics()
    }
}

struct CreateClipCameraImageView: View {
    @FocusState private var focused: Bool
    @State private var animateAppear = false

    var namespace: Namespace.ID
    @Bindable var store: StoreOf<ClipImageReducer>

    var body: some View {
        VStack(spacing: 0) {
            Color.clear
                .overlay {
                    switch store.image {
                    case let .local(uiImage, _):
                        Image(uiImage: uiImage)
                            .resizable()
                            .aspectRatio(contentMode: .fill)

                    case let .remote(_, uploadURLs):
                        RemoteImage(url: uploadURLs.first, fallbackId: nil)
                    }
                }
                .aspectRatio(0.75, contentMode: .fit)
                .clipShape(.rect(cornerRadius: 16))
                .matchedGeometryEffect(id: media, in: namespace)
                .rotationEffect(.degrees(focused ? 11.33 : 0))
                .padding(.horizontal, focused ? 50 : 28)
                .padding(.bottom, focused ? -24 : 24)
                .padding(.top, focused ? 15 : 26)
                .zIndex(focused ? -1 : 0)

            VStack(spacing: 0) {
                TextField("", text: $store.caption, axis: .vertical)
                    .focused($focused)
                    .textFieldStyle(
                        CyclePlaceholderTextFieldStyle(
                            placeholders: [
                                L10n.FeatureCreateClip.mediaCaptionPlaceholder1,
                                L10n.FeatureCreateClip.mediaCaptionPlaceholder2,
                                L10n.FeatureCreateClip.mediaCaptionPlaceholder3,
                                L10n.FeatureCreateClip.mediaCaptionPlaceholder4,
                            ],
                            typography: .body3,
                            maxWidth: nil,
                            maxHeight: nil
                        )
                    )
                    .lineLimit(2 ... 3)
                    .typographyV1(.body3)
                    .foregroundStyle(Color.SemanticV1.textPrimary)
                    .clearButton(value: $store.caption)
                    .padding(.horizontal, 16)
                    .padding(.vertical, focused ? 16 : 24)
                    .background(Color.SemanticV1.backgroundSecondary)
                    .cornerRadius(16)
                    .onTapGesture { focused = true }
                    .padding(.bottom, focused ? 12 : 44)
                    .zIndex(1)

                AuraButton(
                    title: L10n.FeatureCreateClip.create,
                    isLoading: store.isCreating,
                    auraStyle: .orangeAura,
                    leadingView: { Image.Icon.create },
                    action: {
                        UIImpactFeedbackGenerator(style: .light).impactOccurred()
                        focused = false
                        store.send(.didTapCreate)
                    }
                )
                .padding(.bottom, 12)
            }
            .opacity(animateAppear ? 1 : 0)
            .animation(.default, value: animateAppear)
        }
        .animation(.snappy(duration: 0.3), value: focused)
        .bind($store.captionFocused, to: $focused)
        .padding(12)
        .onAppear { animateAppear = true }
        .onTapGesture { focused = false }
    }
}
