import SwiftUI
import Photos
import PhotosUI
import Lottie

// MARK: - AttachmentPanelView

/// Figma-style bottom sheet for selecting photos and files to attach to a message.
///
/// Figma nodes: 3994:39103 (panel), 4758:50706 (tab bar).
///
/// Structure:
/// - Toolbar: X button (left) + "Recents" title (centered)
/// - Content: Photo grid (Gallery) or File picker (File)
/// - Tab bar: [Gallery] [File] [Avatar] — glass capsule background
/// - Send button: appears when items selected, shows count
///
/// Desktop parity: `DialogInput.tsx` attachment menu (paperclip) + file dialog.
struct AttachmentPanelView: View {

    let onSend: ([PendingAttachment], String) -> Void
    let onSendAvatar: () -> Void
    /// When false, tapping avatar tab offers to set an avatar instead of sending.
    var hasAvatar: Bool = true
    /// Called when user has no avatar and taps the avatar tab — navigate to profile.
    var onSetAvatar: (() -> Void)?

    @Environment(\.dismiss) private var dismiss

    @State private var selectedTab: AttachmentTab = .gallery
    @State private var selectedAssets: [PHAsset] = []
    @State private var showCamera = false
    @State private var showFilePicker = false
    @State private var capturedImage: UIImage?
    @State private var captionText: String = ""
    @State private var previewAsset: IdentifiableAsset?
    /// Tab widths/origins for sliding selection indicator (RosettaTabBar parity).
    @State private var tabWidths: [AttachmentTab: CGFloat] = [:]
    @State private var tabOrigins: [AttachmentTab: CGFloat] = [:]

    private var hasSelection: Bool { !selectedAssets.isEmpty }

    var body: some View {
        panelContent
            .sheet(isPresented: $showCamera) {
                CameraPickerView { image in
                    capturedImage = image
                    handleCapturedImage(image)
                }
                .ignoresSafeArea()
            }
            .sheet(isPresented: $showFilePicker) {
                DocumentPickerView { urls in
                    handlePickedFiles(urls)
                }
            }
            .fullScreenCover(item: $previewAsset) { item in
                PhotoPreviewView(
                    asset: item.asset,
                    isSelected: selectedAssets.contains(where: { $0.localIdentifier == item.id }),
                    selectionNumber: selectedAssets.firstIndex(where: { $0.localIdentifier == item.id }).map { $0 + 1 },
                    captionText: $captionText,
                    onSend: { image in
                        let caption = captionText
                        let attachment = PendingAttachment.fromImage(image)
                        onSend([attachment], caption)
                        dismiss()
                    },
                    onToggleSelect: {
                        if let idx = selectedAssets.firstIndex(where: { $0.localIdentifier == item.id }) {
                            selectedAssets.remove(at: idx)
                        } else if selectedAssets.count < PendingAttachment.maxAttachmentsPerMessage {
                            selectedAssets.append(item.asset)
                        }
                    }
                )
                .background(TransparentFullScreenBackground())
            }
            .onPreferenceChange(AttachTabWidthKey.self) { tabWidths.merge($0) { _, new in new } }
            .onPreferenceChange(AttachTabOriginKey.self) { tabOrigins.merge($0) { _, new in new } }
            .presentationDetents([.medium, .large])
            .presentationDragIndicator(.hidden)
            .attachmentCornerRadius(20)
            .attachmentSheetBackground()
    }

    // MARK: - Panel Content

    /// Figma: photos extend to bottom, glass tab bar pill floats over them.
    @ViewBuilder
    private var panelContent: some View {
        ZStack(alignment: .bottom) {
            RosettaColors.Adaptive.surface.ignoresSafeArea()
            VStack(spacing: 0) {
                toolbar
                tabContent
                Spacer(minLength: 0)
            }
            bottomBar
        }
    }

    /// Tab content for the selected tab — shared between iOS versions.
    @ViewBuilder
    private var tabContent: some View {
        switch selectedTab {
        case .gallery:
            PhotoGridView(
                selectedAssets: $selectedAssets,
                maxSelection: PendingAttachment.maxAttachmentsPerMessage,
                onCameraTap: { showCamera = true },
                onPhotoPreview: { asset in
                    previewAsset = IdentifiableAsset(asset: asset)
                }
            )
        case .file:
            fileTabContent
        case .avatar:
            avatarTabContent
        }
    }

    // MARK: - Toolbar (Telegram-style: dark surface header)

    /// Dark surface header matching Telegram attachment panel.
    /// Custom grabber + 44pt close button (Figma: node 4764-50752) + centered title.
    private var toolbar: some View {
        VStack(spacing: 0) {
            // Custom drag indicator (replaces system .presentationDragIndicator)
            Capsule()
                .fill(RosettaColors.Adaptive.text.opacity(0.3))
                .frame(width: 36, height: 5)
                .padding(.top, 5)
                .padding(.bottom, 14)

            // Close button + centered title
            HStack {
                // Close button (same glass style as GlassBackButton, but with X icon)
                Button {
                    dismiss()
                } label: {
                    CloseIconShape()
                        .fill(RosettaColors.Adaptive.text)
                        .frame(width: 14, height: 14)
                        .frame(width: 44, height: 44)
                }
                .background { closeButtonGlass }
                .clipShape(Circle())

                Spacer()

                // Title with dropdown chevron (Telegram-style, ~20pt semibold)
                HStack(spacing: 5) {
                    Text(tabTitle)
                        .font(.system(size: 20, weight: .semibold))
                        .foregroundStyle(RosettaColors.Adaptive.text)
                    Image(systemName: "chevron.down")
                        .font(.system(size: 13, weight: .bold))
                        .foregroundStyle(RosettaColors.Adaptive.text.opacity(0.45))
                }

                Spacer()

                // Right side: selection badge (deselects all) or invisible spacer
                if hasSelection {
                    Button {
                        withAnimation(.easeInOut(duration: 0.25)) {
                            selectedAssets.removeAll()
                        }
                    } label: {
                        selectionBadge
                    }
                    .transition(.scale.combined(with: .opacity))
                } else {
                    // Invisible spacer to balance close button width (keeps title centered)
                    Color.clear
                        .frame(width: 44, height: 44)
                }
            }
            .padding(.horizontal, 8)
            .padding(.bottom, 10)
            .animation(.spring(response: 0.3, dampingFraction: 0.8), value: hasSelection)
        }
    }

    /// Selection count badge — blue capsule with ✓ + count. Tapping deselects all.
    private var selectionBadge: some View {
        HStack(spacing: 2) {
            Image(systemName: "checkmark")
                .font(.system(size: 11, weight: .bold))
            Text("\(selectedAssets.count)")
                .font(.system(size: 12, weight: .bold))
        }
        .foregroundStyle(.white) // White on blue badge is always correct
        .frame(width: 44, height: 28)
        .background(RosettaColors.primaryBlue, in: Capsule())
    }

    /// Glass circle background matching GlassBackButton (ButtonStyles.swift lines 22–34).
    private var closeButtonGlass: some View {
        TelegramGlassCircle()
    }

    /// Title text changes based on selected tab.
    private var tabTitle: String {
        switch selectedTab {
        case .gallery: return "Recents"
        case .file: return "File"
        case .avatar: return "Avatar"
        }
    }

    // MARK: - Avatar Tab Content (Android parity: AttachAlertAvatarLayout)

    /// Dedicated avatar tab with Lottie animation and "Send Avatar" button.
    /// Android: `AttachAlertAvatarLayout.kt` — looping Lottie + title + subtitle + button.
    private var avatarTabContent: some View {
        VStack(spacing: 16) {
            Spacer()

            // Lottie animation (Android: avatar.json, 100×100dp, infinite loop)
            LottieView(
                animationName: "avatar",
                loopMode: .loop,
                animationSpeed: 1.0
            )
            .frame(width: 100, height: 100)

            // Title
            Text("Send Avatar")
                .font(.system(size: 20, weight: .semibold))
                .foregroundStyle(RosettaColors.Adaptive.text)

            // Subtitle
            Text("Share your profile avatar\nwith this contact")
                .font(.system(size: 14))
                .foregroundStyle(RosettaColors.Adaptive.textSecondary)
                .multilineTextAlignment(.center)

            // Send button (capsule style matching File tab's "Browse Files" button)
            Button {
                if hasAvatar {
                    onSendAvatar()
                    dismiss()
                } else {
                    dismiss()
                    onSetAvatar?()
                }
            } label: {
                Text(hasAvatar ? "Send Avatar" : "Set Avatar")
                    .font(.system(size: 15, weight: .medium))
                    .foregroundStyle(.white) // White on blue button is always correct
                    .padding(.horizontal, 24)
                    .padding(.vertical, 10)
                    .background(RosettaColors.primaryBlue, in: Capsule())
            }

            Spacer()

            // Reserve space for tab bar so content doesn't get clipped
            Color.clear.frame(height: 70)
        }
        .frame(maxWidth: .infinity)
    }

    // MARK: - File Tab Content

    private var fileTabContent: some View {
        VStack(spacing: 16) {
            Spacer()

            // Lottie animation (matching avatar tab layout)
            LottieView(
                animationName: "file_folder",
                loopMode: .loop,
                animationSpeed: 1.0
            )
            .frame(width: 100, height: 100)

            // Title
            Text("Send File")
                .font(.system(size: 20, weight: .semibold))
                .foregroundStyle(RosettaColors.Adaptive.text)

            // Subtitle
            Text("Select a file to send")
                .font(.system(size: 14))
                .foregroundStyle(RosettaColors.Adaptive.textSecondary)
                .multilineTextAlignment(.center)

            // Browse button (capsule style matching avatar tab)
            Button {
                showFilePicker = true
            } label: {
                Text("Browse Files")
                    .font(.system(size: 15, weight: .medium))
                    .foregroundStyle(.white) // White on blue button is always correct
                    .padding(.horizontal, 24)
                    .padding(.vertical, 10)
                    .background(RosettaColors.primaryBlue, in: Capsule())
            }

            Spacer()

            // Reserve space for tab bar so content doesn't get clipped
            Color.clear.frame(height: 70)
        }
        .frame(maxWidth: .infinity)
        .task {
            // Auto-open file picker when File tab is selected
            try? await Task.sleep(for: .milliseconds(300))
            showFilePicker = true
        }
    }

    // MARK: - Bottom Bar

    /// Figma: Tab Bar at absolute bottom with padding 25px horizontal, 25px bottom.
    /// Glass pill floats over photos — no footer, no dark strips.
    private var bottomBar: some View {
        VStack(spacing: 0) {
            if hasSelection {
                captionInputBar
                    .padding(.horizontal, 16)
                    .padding(.bottom, 12)
                    .transition(.opacity.combined(with: .move(edge: .bottom)))
            } else {
                tabBar
                    .padding(.horizontal, 25)
                    .padding(.bottom, 12)
                    .transition(.opacity.combined(with: .move(edge: .bottom)))
            }
        }
        .animation(.easeInOut(duration: 0.25), value: hasSelection)
        .background {
            LinearGradient(
                stops: [
                    .init(color: .clear, location: 0),
                    .init(color: RosettaColors.Adaptive.surface.opacity(0.85), location: 0.3),
                    .init(color: RosettaColors.Adaptive.surface, location: 0.8),
                ],
                startPoint: .top,
                endPoint: .bottom
            )
            .ignoresSafeArea(edges: .bottom)
        }
    }

    // MARK: - Caption Input Bar (matches ChatDetail composer style)

    /// Caption input bar shown when photos are selected.
    /// Matches ChatDetailView's composer capsule: `.thinMaterial` glass rounded rect.
    /// Layout: [text field] [emoji] [send button]
    private var captionInputBar: some View {
        HStack(spacing: 0) {
            // Caption text field
            TextField("Add a caption...", text: $captionText)
                .font(.system(size: 16))
                .foregroundStyle(RosettaColors.Adaptive.text)
                .tint(RosettaColors.primaryBlue)
                .padding(.leading, 6)

            // Emoji icon (exact ChatDetail match: TelegramVectorIcon emojiMoon)
            TelegramVectorIcon(
                pathData: TelegramIconPath.emojiMoon,
                viewBox: CGSize(width: 19, height: 19),
                color: RosettaColors.Adaptive.textSecondary
            )
            .frame(width: 19, height: 19)
            .frame(width: 20, height: 36)
            .padding(.trailing, 8)

            // Send button (exact ChatDetail match: 38×36 capsule with sendPlane icon)
            Button {
                sendSelectedPhotos()
            } label: {
                TelegramVectorIcon(
                    pathData: TelegramIconPath.sendPlane,
                    viewBox: CGSize(width: 22, height: 19),
                    color: .white
                )
                .frame(width: 22, height: 19)
                .frame(width: 38, height: 36)
                .background { Capsule().fill(RosettaColors.primaryBlue) }
            }
        }
        .padding(3)
        .frame(minHeight: 42, alignment: .bottom)
        .background { captionBarBackground }
    }

    /// Glass background matching ChatDetailView's composer (`.thinMaterial` + stroke + shadow).
    private var captionBarBackground: some View {
        TelegramGlassRoundedRect(cornerRadius: 21)
    }

    // MARK: - Tab Bar

    /// Glass capsule pill floating over photos (Figma: node 6413:9562).
    /// Uses TelegramGlassCapsule for all iOS — renders UIGlassEffect on iOS 26+.
    /// TabView(.tabBarOnly) removed: expands greedily, blocks touches, adds dark strips.
    private var tabBar: some View {
        legacyTabBar
    }

    // MARK: - Glass Capsule Tab Bar (all iOS versions)

    private var legacyTabBar: some View {
        HStack(spacing: 0) {
            legacyTabButton(.gallery, icon: "photo.fill", unselectedIcon: "photo", label: "Gallery")
                .background(tabWidthReader(.gallery))
            legacyTabButton(.file, icon: "doc.fill", unselectedIcon: "doc", label: "File")
                .background(tabWidthReader(.file))
            legacyTabButton(.avatar, icon: "person.crop.circle.fill", unselectedIcon: "person.crop.circle", label: "Avatar")
                .background(tabWidthReader(.avatar))
        }
        .padding(4)
        .coordinateSpace(name: "attachTabBar")
        .background(alignment: .leading) {
            legacySelectionIndicator
        }
        .background { TelegramGlassCapsule() }
        .contentShape(Capsule())
        .tabBarShadow()
    }

    private func tabWidthReader(_ tab: AttachmentTab) -> some View {
        GeometryReader { geo in
            Color.clear.preference(
                key: AttachTabOriginKey.self,
                value: [tab: geo.frame(in: .named("attachTabBar")).origin.x]
            )
            .preference(
                key: AttachTabWidthKey.self,
                value: [tab: geo.size.width]
            )
        }
    }

    private var legacySelectionIndicator: some View {
        let width = tabWidths[selectedTab] ?? 0
        let xOffset = tabOrigins[selectedTab] ?? 0
        return Capsule().fill(.clear)
            .background { TelegramGlassCapsule() }
            .frame(width: max(0, width - 4))
            .padding(.vertical, 4)
            .offset(x: xOffset + 2)
            .animation(.spring(response: 0.34, dampingFraction: 0.82), value: selectedTab)
    }

    private func legacyTabButton(_ tab: AttachmentTab, icon: String, unselectedIcon: String, label: String) -> some View {
        let isSelected = selectedTab == tab
        let tint = isSelected ? RosettaColors.primaryBlue : RosettaColors.Adaptive.text

        return Button {
            UIImpactFeedbackGenerator(style: .light).impactOccurred()
            withAnimation(.spring(response: 0.34, dampingFraction: 0.82)) {
                selectedTab = tab
            }
        } label: {
            VStack(spacing: 2) {
                Image(systemName: isSelected ? icon : unselectedIcon)
                    .font(.system(size: 22, weight: .regular))
                    .foregroundStyle(tint)
                    .frame(height: 28)
                Text(label)
                    .font(.system(size: 10, weight: isSelected ? .bold : .medium))
                    .foregroundStyle(tint)
            }
            .frame(minWidth: 66, maxWidth: .infinity)
            .padding(.vertical, 6)
        }
        .buttonStyle(.plain)
    }

    // MARK: - Actions

    private func sendSelectedPhotos() {
        let assets = selectedAssets
        let caption = captionText
        let manager = PHImageManager.default()

        Task {
            var attachments: [PendingAttachment] = []
            for asset in assets {
                if let image = await loadFullImage(asset: asset, manager: manager) {
                    attachments.append(PendingAttachment.fromImage(image))
                }
            }
            await MainActor.run {
                onSend(attachments, caption)
                dismiss()
            }
        }
    }

    private func handleCapturedImage(_ image: UIImage) {
        let attachment = PendingAttachment.fromImage(image)
        onSend([attachment], "")
        dismiss()
    }

    private func handlePickedFiles(_ urls: [URL]) {
        var attachments: [PendingAttachment] = []
        for url in urls.prefix(PendingAttachment.maxAttachmentsPerMessage) {
            guard url.startAccessingSecurityScopedResource() else { continue }
            defer { url.stopAccessingSecurityScopedResource() }

            if let data = try? Data(contentsOf: url) {
                attachments.append(PendingAttachment.fromFile(
                    data: data,
                    fileName: url.lastPathComponent
                ))
            }
        }
        if !attachments.isEmpty {
            onSend(attachments, "")
            dismiss()
        }
    }

    private func loadFullImage(asset: PHAsset, manager: PHImageManager) async -> UIImage? {
        await withCheckedContinuation { continuation in
            let options = PHImageRequestOptions()
            options.deliveryMode = .highQualityFormat
            options.isNetworkAccessAllowed = true
            options.isSynchronous = false

            manager.requestImage(
                for: asset,
                targetSize: PHImageManagerMaximumSize,
                contentMode: .default,
                options: options
            ) { image, info in
                let isDegraded = (info?[PHImageResultIsDegradedKey] as? Bool) ?? false
                if !isDegraded {
                    continuation.resume(returning: image)
                }
            }
        }
    }
}

// MARK: - AttachmentTab

private enum AttachmentTab: Hashable {
    case gallery
    case file
    case avatar
}

// MARK: - Tab Bar Preference Keys (selection indicator positioning)

private struct AttachTabWidthKey: PreferenceKey {
    static var defaultValue: [AttachmentTab: CGFloat] = [:]
    static func reduce(value: inout [AttachmentTab: CGFloat], nextValue: () -> [AttachmentTab: CGFloat]) {
        value.merge(nextValue()) { _, new in new }
    }
}

private struct AttachTabOriginKey: PreferenceKey {
    static var defaultValue: [AttachmentTab: CGFloat] = [:]
    static func reduce(value: inout [AttachmentTab: CGFloat], nextValue: () -> [AttachmentTab: CGFloat]) {
        value.merge(nextValue()) { _, new in new }
    }
}

// MARK: - IdentifiableAsset

/// Wrapper to make PHAsset usable with SwiftUI `.fullScreenCover(item:)`.
struct IdentifiableAsset: Identifiable {
    let id: String
    let asset: PHAsset

    init(asset: PHAsset) {
        self.id = asset.localIdentifier
        self.asset = asset
    }
}

// MARK: - Close Icon (Figma SVG: node 4764-50752)

/// Custom X icon matching Figma close button design.
/// SVG source: 20×20 viewport, fill path. Rendered at ~14pt inside 44pt circle.
private struct CloseIconShape: Shape {
    func path(in rect: CGRect) -> Path {
        let sx = rect.width / 19.6289
        let sy = rect.height / 19.6289

        func pt(_ x: CGFloat, _ y: CGFloat) -> CGPoint {
            CGPoint(x: x * sx, y: y * sy)
        }

        var p = Path()
        p.move(to: pt(17.7734, 0.3174))
        p.addCurve(to: pt(18.1396, 0.0732), control1: pt(17.8711, 0.2035), control2: pt(17.9932, 0.1221))
        p.addCurve(to: pt(18.5547, 0), control1: pt(18.2699, 0.0244), control2: pt(18.4082, 0))
        p.addCurve(to: pt(18.9453, 0.0732), control1: pt(18.6849, 0), control2: pt(18.8151, 0.0244))
        p.addCurve(to: pt(19.3115, 0.3174), control1: pt(19.0918, 0.1221), control2: pt(19.2139, 0.2035))
        p.addCurve(to: pt(19.5557, 0.6836), control1: pt(19.4255, 0.415), control2: pt(19.5068, 0.5371))
        p.addCurve(to: pt(19.6289, 1.0742), control1: pt(19.6045, 0.8138), control2: pt(19.6289, 0.944))
        p.addCurve(to: pt(19.5557, 1.4893), control1: pt(19.6289, 1.2207), control2: pt(19.6045, 1.3591))
        p.addCurve(to: pt(19.3115, 1.8555), control1: pt(19.5068, 1.6357), control2: pt(19.4255, 1.7578))
        p.addLine(to: pt(11.3525, 9.8145))
        p.addLine(to: pt(19.3115, 17.7734))
        p.addCurve(to: pt(19.5557, 18.1396), control1: pt(19.4255, 17.8711), control2: pt(19.5068, 17.9932))
        p.addCurve(to: pt(19.6289, 18.5547), control1: pt(19.6045, 18.2699), control2: pt(19.6289, 18.4082))
        p.addCurve(to: pt(19.5557, 18.9453), control1: pt(19.6289, 18.6849), control2: pt(19.6045, 18.8151))
        p.addCurve(to: pt(19.3115, 19.3115), control1: pt(19.5068, 19.0918), control2: pt(19.4255, 19.2139))
        p.addCurve(to: pt(18.9453, 19.5557), control1: pt(19.2139, 19.4255), control2: pt(19.0918, 19.5068))
        p.addCurve(to: pt(18.5547, 19.6289), control1: pt(18.8151, 19.6045), control2: pt(18.6849, 19.6289))
        p.addCurve(to: pt(18.1396, 19.5557), control1: pt(18.4082, 19.6289), control2: pt(18.2699, 19.6045))
        p.addCurve(to: pt(17.7734, 19.3115), control1: pt(17.9932, 19.5068), control2: pt(17.8711, 19.4255))
        p.addLine(to: pt(9.8145, 11.3525))
        p.addLine(to: pt(1.8555, 19.3115))
        p.addCurve(to: pt(1.4893, 19.5557), control1: pt(1.7578, 19.4255), control2: pt(1.6357, 19.5068))
        p.addCurve(to: pt(1.0742, 19.6289), control1: pt(1.3591, 19.6045), control2: pt(1.2207, 19.6289))
        p.addCurve(to: pt(0.6836, 19.5557), control1: pt(0.944, 19.6289), control2: pt(0.8138, 19.6045))
        p.addCurve(to: pt(0.3174, 19.3115), control1: pt(0.5371, 19.5068), control2: pt(0.415, 19.4255))
        p.addCurve(to: pt(0.0732, 18.9453), control1: pt(0.2035, 19.2139), control2: pt(0.1221, 19.0918))
        p.addCurve(to: pt(0, 18.5547), control1: pt(0.0244, 18.8151), control2: pt(0, 18.6849))
        p.addCurve(to: pt(0.0732, 18.1396), control1: pt(0, 18.4082), control2: pt(0.0244, 18.2699))
        p.addCurve(to: pt(0.3174, 17.7734), control1: pt(0.1221, 17.9932), control2: pt(0.2035, 17.8711))
        p.addLine(to: pt(8.2764, 9.8145))
        p.addLine(to: pt(0.3174, 1.8555))
        p.addCurve(to: pt(0.0732, 1.4893), control1: pt(0.2035, 1.7578), control2: pt(0.1221, 1.6357))
        p.addCurve(to: pt(0, 1.0742), control1: pt(0.0244, 1.3591), control2: pt(0, 1.2207))
        p.addCurve(to: pt(0.0732, 0.6836), control1: pt(0, 0.944), control2: pt(0.0244, 0.8138))
        p.addCurve(to: pt(0.3174, 0.3174), control1: pt(0.1221, 0.5371), control2: pt(0.2035, 0.415))
        p.addCurve(to: pt(0.6836, 0.0732), control1: pt(0.415, 0.2035), control2: pt(0.5371, 0.1221))
        p.addCurve(to: pt(1.0742, 0), control1: pt(0.8138, 0.0244), control2: pt(0.944, 0))
        p.addCurve(to: pt(1.4893, 0.0732), control1: pt(1.2207, 0), control2: pt(1.3591, 0.0244))
        p.addCurve(to: pt(1.8555, 0.3174), control1: pt(1.6357, 0.1221), control2: pt(1.7578, 0.2035))
        p.addLine(to: pt(9.8145, 8.2764))
        p.addLine(to: pt(17.7734, 0.3174))
        p.closeSubpath()

        return p
    }
}

// MARK: - Presentation Corner Radius (iOS 16.4+)

/// Sets a custom corner radius on the sheet presentation.
/// `.presentationCornerRadius` is iOS 16.4+, so this modifier guards availability.
private struct AttachmentCornerRadiusModifier: ViewModifier {
    let radius: CGFloat
    func body(content: Content) -> some View {
        if #available(iOS 16.4, *) {
            content.presentationCornerRadius(radius)
        } else {
            content
        }
    }
}

private extension View {
    func attachmentCornerRadius(_ radius: CGFloat) -> some View {
        modifier(AttachmentCornerRadiusModifier(radius: radius))
    }
}

// MARK: - Tab Bar Shadow Modifier

/// Shadow for iOS < 26 tab bar (matches RosettaTabBar's TabBarShadowModifier).
private struct AttachmentTabBarShadowModifier: ViewModifier {
    func body(content: Content) -> some View {
        content
            .shadow(color: .black.opacity(0.12), radius: 20, y: 8)
    }
}

private extension View {
    func tabBarShadow() -> some View {
        modifier(AttachmentTabBarShadowModifier())
    }
}

// MARK: - Preview Background Modifier (iOS 16.4+)

/// Sets a custom background on the sheet presentation.
/// `.presentationBackground` is iOS 16.4+, so this modifier guards availability.
private struct PreviewBackgroundModifier<S: ShapeStyle>: ViewModifier {
    let style: S
    func body(content: Content) -> some View {
        if #available(iOS 16.4, *) {
            content.presentationBackground(style)
        } else {
            content
        }
    }
}

private extension View {
    func previewBackground<S: ShapeStyle>(_ style: S) -> some View {
        modifier(PreviewBackgroundModifier(style: style))
    }
}

// MARK: - Sheet Background (iOS < 26 only; iOS 26+ uses default Liquid Glass)

private struct AttachmentSheetBackgroundModifier: ViewModifier {
    func body(content: Content) -> some View {
        if #available(iOS 16.4, *) {
            content.presentationBackground(RosettaColors.Adaptive.surface)
        } else {
            content
        }
    }
}

private extension View {
    func attachmentSheetBackground() -> some View {
        modifier(AttachmentSheetBackgroundModifier())
    }
}

// MARK: - CameraPickerView

/// UIKit camera wrapper for taking photos.
struct CameraPickerView: UIViewControllerRepresentable {
    let onCapture: (UIImage) -> Void

    func makeUIViewController(context: Context) -> UIImagePickerController {
        let picker = UIImagePickerController()
        picker.sourceType = .camera
        picker.delegate = context.coordinator
        return picker
    }

    func updateUIViewController(_ uiViewController: UIImagePickerController, context: Context) {}

    func makeCoordinator() -> Coordinator {
        Coordinator(onCapture: onCapture)
    }

    final class Coordinator: NSObject, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
        let onCapture: (UIImage) -> Void

        init(onCapture: @escaping (UIImage) -> Void) {
            self.onCapture = onCapture
        }

        func imagePickerController(
            _ picker: UIImagePickerController,
            didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]
        ) {
            if let image = info[.originalImage] as? UIImage {
                onCapture(image)
            }
            picker.dismiss(animated: true)
        }

        func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
            picker.dismiss(animated: true)
        }
    }
}

// MARK: - DocumentPickerView

/// UIKit document picker wrapper for selecting files.
struct DocumentPickerView: UIViewControllerRepresentable {
    let onPick: ([URL]) -> Void

    func makeUIViewController(context: Context) -> UIDocumentPickerViewController {
        let picker = UIDocumentPickerViewController(forOpeningContentTypes: [.item])
        picker.allowsMultipleSelection = true
        picker.delegate = context.coordinator
        return picker
    }

    func updateUIViewController(_ uiViewController: UIDocumentPickerViewController, context: Context) {}

    func makeCoordinator() -> Coordinator {
        Coordinator(onPick: onPick)
    }

    final class Coordinator: NSObject, UIDocumentPickerDelegate {
        let onPick: ([URL]) -> Void

        init(onPick: @escaping ([URL]) -> Void) {
            self.onPick = onPick
        }

        func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
            onPick(urls)
        }

        func documentPickerWasCancelled(_ controller: UIDocumentPickerViewController) {
            // No-op — user cancelled
        }
    }
}

// MARK: - Transparent FullScreen Background

/// UIKit hack to make `.fullScreenCover` background transparent.
/// Walks the view hierarchy to find the presentation container and sets
/// its background to clear, allowing the presenting view to show through.
struct TransparentFullScreenBackground: UIViewRepresentable {
    func makeUIView(context: Context) -> UIView {
        let view = UIView()
        view.backgroundColor = .clear
        DispatchQueue.main.async {
            view.superview?.superview?.backgroundColor = .clear
        }
        return view
    }

    func updateUIView(_ uiView: UIView, context: Context) {}
}

