import SwiftUI
import Combine

public enum FABSize {
    case small
    case large
    
}

public enum FABPosition {
    case right
    case center
}

public struct FabProps {
    public let icon: String?
    public let iconColor: Color?
    public let label: String?
    public let onClick: (() -> Void)?
    public let containerColor: Color?
    public let size: FABSize?
    public let iconSize: CGFloat?
    public let scrollOffset: CGFloat?
    public let position: FABPosition?
    public let bottomPadding: CGFloat?
    public let renderComponent: (() -> AnyView)?
    
    public init(
        icon: String? = nil,
        iconColor: Color? = .white,
        label: String? = nil,
        onClick: (() -> Void)? = nil,
        containerColor: Color? = Colors.primary,
        size: FABSize? = .small,
        iconSize: CGFloat? = nil,
        scrollOffset: CGFloat? = nil,
        position: FABPosition? = .right,
        bottomPadding: CGFloat? = nil,
        renderComponent: (() -> AnyView)? = nil
    ) {
        self.icon = icon
        self.iconColor = iconColor
        self.label = label
        self.onClick = onClick
        self.containerColor = containerColor
        self.size = size
        self.iconSize = iconSize
        self.scrollOffset = scrollOffset
        self.position = position
        self.bottomPadding = bottomPadding
        self.renderComponent = renderComponent
    }
}

public struct FloatingButton: View {
    @State private var lastScrollOffset: CGFloat = 0
    @State private var isExpanded: Bool = false
    @State private var internalScrollOffset: CGFloat = 0
    @State private var showText: Bool = true
    @State private var fullWidth: CGFloat? = nil
    @State private var currentWidth: CGFloat = 0
    @State private var lastDirection: String? = nil
    
    private let props: FabProps
    private var keyboardOffset: CGFloat
    private var scrollOffset: CGFloat
    private var bottomPadding: CGFloat { props.bottomPadding ?? 12 + keyboardOffset}
    private var position: FABPosition? { props.position ?? .right }
    private var containerColor: Color? { props.containerColor ?? Colors.primary }
    private var iconColor: Color? { props.iconColor ?? .white }
    private var label: String? { props.label }
    private var icon: String? { props.icon }
    private var size: FABSize? { props.size }
    private var iconSize: CGFloat? { props.iconSize ?? defaultIconSize}
    private var onClick: (() -> Void)? { props.onClick }
    private var renderComponent: (() -> AnyView)? { props.renderComponent }
    
    public init(props: FabProps, keyboardOffset: CGFloat = 0, scrollOffset: CGFloat = 0) {
        self.props = props
        self.keyboardOffset = keyboardOffset
        self.scrollOffset = scrollOffset
    }
    
    private var height: CGFloat {
        if(iconSize == nil) {
            size == .small ? 36 : 48
        }
        else {
            iconSize!
        }
    }
    
    private var minWidth: CGFloat {
        size == .small ? 36 : 48
    }
    
    private var defaultIconSize: CGFloat {
        size == .small ? 12 : 24
    }
    
    public var body: some View {
        Group {
            if ((icon?.isEmpty) == nil), let render = renderComponent {
                render()
            } else {
                content
            }
        }
        .onTapGesture {
            onClick?()
        }
        .padding(Spacing.M)
        .frame(height: height + (Spacing.M * 2))
        .background(containerColor)
        .cornerRadius(100)
        .padding(.bottom, bottomPadding)
        .frame(alignment: position == .center ? .center : .trailing)
        .onAppear {
            internalScrollOffset = scrollOffset
            isExpanded = label != nil
        }
        .onReceive(Just(scrollOffset)) { newValue in
            let direction = newValue > internalScrollOffset ? "down" : "up"

            if direction != lastDirection {
                lastDirection = direction
                if direction == "down" {
                    withAnimation(.easeOut(duration: 0.1)) {
                        isExpanded = false
                    }
                    DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
                        showText = false
                    }
                } else {
                    showText = true
                    withAnimation(.easeIn(duration: 0.1)) {
                        isExpanded = true
                    }
                    
                }
            }
        }
    }
    
    private var content: some View {
        HStack(spacing: 0) {
            ImageView(icon ?? "")
                .scaledToFit()
                .frame(width: iconSize, height: iconSize)
                .foregroundColor(iconColor)
            
            if let label = label {
                if showText {
                    Spacer().frame(width: 8)
                    Text(label)
                        .foregroundColor(.white)
                        .font(.system(size: scaleSize(16), weight: .bold))
                        .lineLimit(1)
                        .background(
                            GeometryReader { geo in
                                Color.clear.onAppear {
                                    fullWidth = geo.size.width
                                }
                            }
                        )
                        .opacity(isExpanded ? 1 : 0)
                }
            }

        }
    }
}
