package com.wisp.app.ui.screen

import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.ui.draw.clip
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ExperimentalLayoutApi
import androidx.compose.foundation.layout.FlowRow
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.filled.Block
import androidx.compose.material.icons.outlined.Lock
import androidx.compose.material.icons.automirrored.filled.Send
import androidx.compose.material.icons.filled.CheckCircle
import androidx.compose.material.icons.filled.Refresh
import androidx.compose.material.icons.filled.ArrowDropDown
import androidx.compose.material.icons.filled.Check
import androidx.compose.material.icons.filled.MoreVert

import androidx.compose.material.icons.filled.PlayArrow
import androidx.compose.material.icons.filled.QrCodeScanner
import androidx.compose.material.icons.filled.Search
import androidx.compose.material.icons.filled.Close
import androidx.compose.material.icons.outlined.CurrencyBitcoin
import com.wisp.app.nostr.Nip30
import com.wisp.app.ui.component.Nip05Badge
import com.wisp.app.ui.component.RichContent
import com.wisp.app.ui.component.parseImetaTags
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Surface
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Tab
import androidx.compose.material3.ScrollableTabRow
import androidx.compose.material3.TabRow
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberUpdatedState
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.runtime.snapshotFlow
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import coil3.compose.AsyncImage
import com.wisp.app.R
import com.wisp.app.nostr.FollowSet
import com.wisp.app.nostr.Nip02
import com.wisp.app.nostr.Nip69
import com.wisp.app.nostr.NostrEvent
import com.wisp.app.nostr.ProfileData
import com.wisp.app.relay.RelayConfig
import com.wisp.app.relay.RelayPool
import com.wisp.app.repo.ContactRepository
import com.wisp.app.repo.EventRepository
import com.wisp.app.repo.Nip05Repository
import com.wisp.app.repo.Nip05Status
import com.wisp.app.repo.RelayInfoRepository
import com.wisp.app.repo.TranslationRepository
import com.wisp.app.ui.component.FollowButton
import com.wisp.app.ui.component.ContentSegment
import com.wisp.app.ui.component.FullScreenImageViewer
import com.wisp.app.ui.component.GalleryCard
import com.wisp.app.ui.component.isGalleryEvent
import com.wisp.app.ui.component.PostCard
import com.wisp.app.ui.component.parseContent
import com.wisp.app.ui.component.parseImetaTags
import com.wisp.app.ui.component.ProfileQrSheet
import com.wisp.app.ui.component.ProfilePicture
import com.wisp.app.ui.component.RichContent
import com.wisp.app.ui.component.ZapDialog
import com.wisp.app.viewmodel.ProfileSortMode
import com.wisp.app.viewmodel.UserProfileViewModel
import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
import android.widget.Toast
import androidx.compose.ui.platform.LocalContext
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.SharedFlow
import kotlinx.serialization.json.buildJsonObject
import kotlinx.serialization.json.put

private sealed class ProfileZapStatus {
    object Idle : ProfileZapStatus()
    data class InProgress(val msats: Long) : ProfileZapStatus()
    data class Success(val sats: Long) : ProfileZapStatus()
    data class Failure(val message: String) : ProfileZapStatus()
}

@OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class)
@Composable
fun UserProfileScreen(
    viewModel: UserProfileViewModel,
    contactRepo: ContactRepository,
    relayPool: RelayPool,
    onBack: () -> Unit,
    onReply: (NostrEvent) -> Unit = {},
    onRepost: (NostrEvent) -> Unit = {},
    onQuote: (NostrEvent) -> Unit = {},
    eventRepo: EventRepository? = null,
    onNavigateToProfile: ((String) -> Unit)? = null,
    onToggleFollow: ((String) -> Unit)? = null,
    isOwnProfile: Boolean = false,
    onEditProfile: () -> Unit = {},
    isBlocked: Boolean = false,
    onBlockUser: (() -> Unit)? = null,
    onUnblockUser: (() -> Unit)? = null,
    onNoteClick: (NostrEvent) -> Unit = {},
    onQuotedNoteClick: ((String) -> Unit)? = null,
    onReact: (NostrEvent, String) -> Unit = { _, _ -> },
    onZap: (NostrEvent, Long, String, Boolean, Boolean) -> Unit = { _, _, _, _, _ -> },
    userPubkey: String? = null,
    isWalletConnected: Boolean = false,
    onWallet: () -> Unit = {},
    zapSuccess: SharedFlow<String>? = null,
    zapError: SharedFlow<String>? = null,
    zapInProgressIds: Set<String> = emptySet(),
    canPrivateZap: Boolean = false,
    fetchDmRelays: (suspend (String) -> Boolean)? = null,
    ownLists: List<FollowSet> = emptyList(),
    onAddToList: ((String, String) -> Unit)? = null,
    onRemoveFromList: ((String, String) -> Unit)? = null,
    onCreateList: ((String, Boolean) -> Unit)? = null,
    profilePubkey: String = "",
    relayInfoRepo: RelayInfoRepository? = null,
    nip05Repo: Nip05Repository? = null,
    listedIds: Set<String> = emptySet(),
    pinnedIds: Set<String> = emptySet(),
    onTogglePin: (String) -> Unit = {},
    onDeleteEvent: (String, Int) -> Unit = { _, _ -> },
    onAddNoteToList: (String) -> Unit = {},
    onSendDm: (() -> Unit)? = null,
    onZapProfile: ((amountMsats: Long, message: String, isAnonymous: Boolean) -> Unit)? = null,
    signer: com.wisp.app.nostr.NostrSigner? = null,
    translationRepo: TranslationRepository? = null,
    onArticleClick: ((Int, String, String) -> Unit)? = null,
    onPollVote: (String, List<String>) -> Unit = { _, _ -> },
    onZapPollVote: (String, Int) -> Unit = { _, _ -> },
    resolvedEmojis: Map<String, String> = emptyMap(),
    unicodeEmojis: List<String> = emptyList(),
    onOpenEmojiLibrary: (() -> Unit)? = null,
    onSearchAuthor: (() -> Unit)? = null,
    onPayInvoice: (suspend (String) -> Boolean)? = null,
    onGroupRoom: ((String, String) -> Unit)? = null,
    onLiveStreamClick: ((String, String, String?) -> Unit)? = null,
    fetchGroupPreview: (suspend (String, String) -> com.wisp.app.repo.GroupPreview?)? = null,
    onAddEmojiSet: ((String, String) -> Unit)? = null,
    onRemoveEmojiSet: ((String, String) -> Unit)? = null,
    isEmojiSetAdded: ((String, String) -> Boolean)? = null
) {
    val resolvedEmojisState = rememberUpdatedState(resolvedEmojis)
    val unicodeEmojisState = rememberUpdatedState(unicodeEmojis)
    val invoiceNoteActions = remember(onPayInvoice, onGroupRoom, onLiveStreamClick, fetchGroupPreview, onAddEmojiSet, onOpenEmojiLibrary) {
        if (onPayInvoice != null || onGroupRoom != null || fetchGroupPreview != null || onAddEmojiSet != null || onLiveStreamClick != null || onOpenEmojiLibrary != null) {
            com.wisp.app.ui.component.NoteActions(
            onPayInvoice = onPayInvoice,
            onGroupRoom = onGroupRoom,
            onLiveStreamClick = onLiveStreamClick,
            fetchGroupPreview = fetchGroupPreview,
            onAddEmojiSet = onAddEmojiSet,
            onRemoveEmojiSet = onRemoveEmojiSet,
            isEmojiSetAdded = isEmojiSetAdded,
            onPollVote = onPollVote,
            nip05Repo = nip05Repo,
            resolvedEmojisProvider = { resolvedEmojisState.value },
            unicodeEmojisProvider = { unicodeEmojisState.value },
            onOpenEmojiLibrary = onOpenEmojiLibrary
        )
        } else null
    }
    val profile by viewModel.profile.collectAsState()
    val isFollowing by viewModel.isFollowing.collectAsState()
    val rootNotes by viewModel.rootNotes.collectAsState()
    val replies by viewModel.replies.collectAsState()
    val followList by viewModel.followList.collectAsState()
    val relayList by viewModel.relayList.collectAsState()
    val relayHints by viewModel.relayHints.collectAsState()
    val followedBy by viewModel.followedBy.collectAsState()
    val followProfileVersion by viewModel.followProfileVersion.collectAsState()
    val myFollowList by contactRepo.followList.collectAsState()

    val nip05Version by nip05Repo?.version?.collectAsState() ?: remember { mutableIntStateOf(0) }
    val reactionVersion by eventRepo?.reactionVersion?.collectAsState() ?: remember { mutableIntStateOf(0) }
    val replyCountVersion by eventRepo?.replyCountVersion?.collectAsState() ?: remember { mutableIntStateOf(0) }
    val repostVersion by eventRepo?.repostVersion?.collectAsState() ?: remember { mutableIntStateOf(0) }
    val zapVersion by eventRepo?.zapVersion?.collectAsState() ?: remember { mutableIntStateOf(0) }
    val translationVersion by translationRepo?.version?.collectAsState() ?: remember { mutableIntStateOf(0) }
    val relaySourceVersion by eventRepo?.relaySourceVersion?.collectAsState() ?: remember { mutableIntStateOf(0) }
    val pollVoteVersion by eventRepo?.pollVoteVersion?.collectAsState() ?: remember { mutableIntStateOf(0) }

    var zapTargetEvent by remember { mutableStateOf<NostrEvent?>(null) }
    var zapAnimatingIds by remember { mutableStateOf(emptySet<String>()) }
    var zapErrorMessage by remember { mutableStateOf<String?>(null) }

    var showProfileZapDialog by remember { mutableStateOf(false) }
    var profileZapStatus by remember { mutableStateOf<ProfileZapStatus>(ProfileZapStatus.Idle) }

    LaunchedEffect(Unit) {
        zapSuccess?.collect { id ->
            if (id == profilePubkey) {
                val msats = (profileZapStatus as? ProfileZapStatus.InProgress)?.msats ?: 0L
                profileZapStatus = ProfileZapStatus.Success(msats / 1000)
            } else {
                zapAnimatingIds = zapAnimatingIds + id
                delay(1500)
                zapAnimatingIds = zapAnimatingIds - id
            }
        }
    }

    LaunchedEffect(Unit) {
        zapError?.collect { error ->
            if (profileZapStatus is ProfileZapStatus.InProgress) {
                profileZapStatus = ProfileZapStatus.Failure(error)
            } else {
                zapErrorMessage = error
            }
        }
    }

    if (zapTargetEvent != null) {
        val zapRecipient = zapTargetEvent!!.pubkey
        var resolvedCanPrivateZap by remember(zapRecipient) { mutableStateOf(canPrivateZap) }
        if (!canPrivateZap && fetchDmRelays != null) {
            LaunchedEffect(zapRecipient) {
                val result = fetchDmRelays(zapRecipient)
                if (result) resolvedCanPrivateZap = true
            }
        }
        ZapDialog(
            isWalletConnected = isWalletConnected,
            onDismiss = { zapTargetEvent = null },
            onZap = { amountMsats, message, isAnonymous, isPrivate ->
                val event = zapTargetEvent ?: return@ZapDialog
                zapTargetEvent = null
                onZap(event, amountMsats, message, isAnonymous, isPrivate)
            },
            onGoToWallet = onWallet,
            canPrivateZap = resolvedCanPrivateZap
        )
    }

    if (showProfileZapDialog) {
        ZapDialog(
            isWalletConnected = isWalletConnected,
            onDismiss = { showProfileZapDialog = false },
            onZap = { amountMsats, message, isAnonymous, _ ->
                showProfileZapDialog = false
                profileZapStatus = ProfileZapStatus.InProgress(amountMsats)
                onZapProfile?.invoke(amountMsats, message, isAnonymous)
            },
            onGoToWallet = onWallet,
            canPrivateZap = false
        )
    }

    when (val s = profileZapStatus) {
        is ProfileZapStatus.Idle -> {}
        is ProfileZapStatus.InProgress -> {
            AlertDialog(
                onDismissRequest = {},
                title = { Text("Sending zap...") },
                text = { CircularProgressIndicator() },
                confirmButton = {}
            )
        }
        is ProfileZapStatus.Success -> {
            AlertDialog(
                onDismissRequest = { profileZapStatus = ProfileZapStatus.Idle },
                title = { Text("\u26A1 Zap sent!") },
                text = { Text("${s.sats} sats sent") },
                confirmButton = {
                    TextButton(onClick = { profileZapStatus = ProfileZapStatus.Idle }) { Text(stringResource(R.string.btn_ok)) }
                }
            )
        }
        is ProfileZapStatus.Failure -> {
            AlertDialog(
                onDismissRequest = { profileZapStatus = ProfileZapStatus.Idle },
                title = { Text(stringResource(R.string.zap_failed)) },
                text = { Text(s.message) },
                confirmButton = {
                    TextButton(onClick = { profileZapStatus = ProfileZapStatus.Idle }) { Text(stringResource(R.string.btn_ok)) }
                }
            )
        }
    }

    if (zapErrorMessage != null) {
        AlertDialog(
            onDismissRequest = { zapErrorMessage = null },
            title = { Text(stringResource(R.string.zap_failed)) },
            text = { Text(zapErrorMessage ?: "") },
            confirmButton = {
                TextButton(onClick = { zapErrorMessage = null }) { Text(stringResource(R.string.btn_ok)) }
            }
        )
    }

    var showQrDialog by remember { mutableStateOf(false) }
    var showAddToListDialog by remember { mutableStateOf(false) }

    if (showQrDialog) {
        ProfileQrSheet(
            pubkeyHex = profilePubkey,
            avatarUrl = profile?.picture,
            lud16 = profile?.lud16,
            onDismiss = { showQrDialog = false }
        )
    }

    if (showAddToListDialog && !isOwnProfile) {
        AddToListDialog(
            pubkey = profilePubkey,
            ownLists = ownLists,
            onAddToList = { dTag -> onAddToList?.invoke(dTag, profilePubkey) },
            onRemoveFromList = { dTag -> onRemoveFromList?.invoke(dTag, profilePubkey) },
            onCreateList = onCreateList,
            onDismiss = { showAddToListDialog = false }
        )
    }

    val notesSortMode by viewModel.notesSortMode.collectAsState()
    val repliesSortMode by viewModel.repliesSortMode.collectAsState()
    val sortedNotes by viewModel.sortedNotes.collectAsState()
    val sortedNotesLoading by viewModel.sortedNotesLoading.collectAsState()
    val sortedReplies by viewModel.sortedReplies.collectAsState()
    val sortedRepliesLoading by viewModel.sortedRepliesLoading.collectAsState()
    val followers by viewModel.followers.collectAsState()
    val followersLoading by viewModel.followersLoading.collectAsState()
    val groups by viewModel.groups.collectAsState()
    val groupsLoading by viewModel.groupsLoading.collectAsState()

    var selectedTab by rememberSaveable { mutableIntStateOf(0) }
    var showSortDropdown by remember { mutableStateOf(false) }

    if (selectedTab == 5) {
        LaunchedEffect(Unit) { viewModel.loadFollowers() }
    }

    var blockedContentRevealed by remember { mutableStateOf(false) }
    var fullScreenMediaImageUrl by remember { mutableStateOf<String?>(null) }
    var fullScreenMediaVideoUrl by remember { mutableStateOf<String?>(null) }
    val tabTitles = listOf(
        stringResource(R.string.profile_tab_notes),
        stringResource(R.string.profile_tab_replies),
        stringResource(R.string.profile_tab_gallery),
        stringResource(R.string.profile_tab_media),
        stringResource(R.string.profile_tab_following),
        stringResource(R.string.profile_tab_followers),
        stringResource(R.string.profile_tab_groups),
        stringResource(R.string.profile_tab_relays)
    )

    if (fullScreenMediaImageUrl != null) {
        FullScreenImageViewer(
            imageUrl = fullScreenMediaImageUrl!!,
            onDismiss = { fullScreenMediaImageUrl = null }
        )
    }

    if (fullScreenMediaVideoUrl != null) {
        com.wisp.app.ui.component.FullScreenVideoPlayer(
            videoUrl = fullScreenMediaVideoUrl!!,
            onDismiss = { fullScreenMediaVideoUrl = null }
        )
    }

    Scaffold(
        contentWindowInsets = androidx.compose.foundation.layout.WindowInsets(0, 0, 0, 0),
        topBar = {
            TopAppBar(
                title = {
                    Text(
                        profile?.displayString ?: "Profile",
                        maxLines = 1,
                        overflow = TextOverflow.Ellipsis
                    )
                },
                navigationIcon = {
                    IconButton(onClick = onBack) {
                        Icon(Icons.AutoMirrored.Filled.ArrowBack, "Back")
                    }
                },
                actions = {
                    val context = LocalContext.current
                    if (onSearchAuthor != null) {
                        IconButton(onClick = onSearchAuthor) {
                            Icon(Icons.Default.Search, stringResource(R.string.profile_search_notes))
                        }
                    }
                    IconButton(onClick = { showQrDialog = true }) {
                        Icon(Icons.Default.QrCodeScanner, stringResource(R.string.cd_show_qr_code))
                    }
                    var menuExpanded by remember { mutableStateOf(false) }
                    IconButton(onClick = { menuExpanded = true }) {
                        Icon(Icons.Default.MoreVert, stringResource(R.string.cd_more_options))
                    }
                    DropdownMenu(
                        expanded = menuExpanded,
                        onDismissRequest = { menuExpanded = false }
                    ) {
                        DropdownMenuItem(
                            text = { Text(stringResource(R.string.profile_copy_json)) },
                            onClick = {
                                menuExpanded = false
                                profile?.let { p ->
                                    val json = buildJsonObject {
                                        p.name?.let { put("name", it) }
                                        p.displayName?.let { put("display_name", it) }
                                        p.about?.let { put("about", it) }
                                        p.picture?.let { put("picture", it) }
                                        p.banner?.let { put("banner", it) }
                                        p.nip05?.let { put("nip05", it) }
                                        p.lud16?.let { put("lud16", it) }
                                    }.toString()
                                    val clipboard = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
                                    clipboard.setPrimaryClip(ClipData.newPlainText("Profile JSON", json))
                                    Toast.makeText(context, context.getString(R.string.profile_json_copied), Toast.LENGTH_SHORT).show()
                                }
                            }
                        )
                        if (!isOwnProfile) {
                            DropdownMenuItem(
                                text = { Text(stringResource(R.string.profile_add_to_list)) },
                                onClick = {
                                    menuExpanded = false
                                    showAddToListDialog = true
                                }
                            )
                            if (isBlocked) {
                                DropdownMenuItem(
                                    text = { Text(stringResource(R.string.profile_unblock)) },
                                    onClick = {
                                        menuExpanded = false
                                        onUnblockUser?.invoke()
                                    }
                                )
                            } else {
                                DropdownMenuItem(
                                    text = { Text(stringResource(R.string.profile_block)) },
                                    onClick = {
                                        menuExpanded = false
                                        onBlockUser?.invoke()
                                    }
                                )
                            }
                        }
                    }
                },
                colors = TopAppBarDefaults.topAppBarColors(
                    containerColor = MaterialTheme.colorScheme.surface
                )
            )
        }
    ) { padding ->
        val galleryPosts by viewModel.galleryPosts.collectAsState()
        val mediaItems = remember(rootNotes.size, replies.size, selectedTab) {
            if (selectedTab != 3) emptyList()
            else (rootNotes + replies)
                .sortedByDescending { it.created_at }
                .flatMap { event ->
                    val imeta = parseImetaTags(event.tags)
                    parseContent(event.content, imetaMap = imeta).mapNotNull { segment ->
                        when (segment) {
                            is ContentSegment.ImageSegment -> MediaItem(segment.meta.url, MediaType.IMAGE)
                            is ContentSegment.VideoSegment -> MediaItem(segment.meta.url, MediaType.VIDEO)
                            is ContentSegment.UnknownMediaSegment -> MediaItem(segment.meta.url, MediaType.IMAGE)
                            else -> null
                        }
                    }
                }
                .distinctBy { it.url }
        }

        val listState = rememberLazyListState()

        // Auto-load more media when scrolling near the bottom of the grid
        if (selectedTab == 3 && mediaItems.isNotEmpty()) {
            LaunchedEffect(listState) {
                snapshotFlow {
                    val lastVisible = listState.layoutInfo.visibleItemsInfo.lastOrNull()?.index ?: 0
                    val totalItems = listState.layoutInfo.totalItemsCount
                    lastVisible to totalItems
                }.collect { (lastVisible, totalItems) ->
                    if (totalItems > 0 && lastVisible >= totalItems - 3) {
                        viewModel.loadMoreNotes()
                        viewModel.loadMoreReplies()
                    }
                }
            }
        }

        LazyColumn(
            state = listState,
            modifier = Modifier
                .fillMaxSize()
                .padding(padding)
        ) {
            item {
                @Suppress("UNUSED_EXPRESSION")
                nip05Version
                ProfileHeader(
                    profile = profile,
                    isOwnProfile = isOwnProfile,
                    isFollowing = isFollowing,
                    onEditProfile = onEditProfile,
                    onToggleFollow = { viewModel.toggleFollow(contactRepo, relayPool, signer) },
                    nip05Repo = nip05Repo,
                    pubkey = profilePubkey,
                    eventRepo = eventRepo,
                    onNavigateToProfile = onNavigateToProfile,
                    onSendDm = onSendDm,
                    onZapClick = if (onZapProfile != null) { { showProfileZapDialog = true } } else null,
                    followingCount = followList.size,
                    followedBy = followedBy,
                    followsYou = !isOwnProfile && userPubkey != null && followList.any { it.pubkey == userPubkey },
                    isBlocked = isBlocked
                )
            }

            stickyHeader {
                ScrollableTabRow(
                    selectedTabIndex = selectedTab,
                    containerColor = MaterialTheme.colorScheme.surface,
                    edgePadding = 16.dp
                ) {
                    tabTitles.forEachIndexed { index, title ->
                        Tab(
                            selected = selectedTab == index,
                            onClick = { selectedTab = index },
                            text = { Text(title) }
                        )
                    }
                }
            }

            if (selectedTab == 0 || selectedTab == 1) {
                item {
                    val currentSortMode = if (selectedTab == 0) notesSortMode else repliesSortMode
                    Box(
                        modifier = Modifier
                            .fillMaxWidth()
                            .background(MaterialTheme.colorScheme.surface)
                            .padding(vertical = 6.dp),
                        contentAlignment = Alignment.Center
                    ) {
                        Box {
                            Surface(
                                onClick = { showSortDropdown = true },
                                shape = RoundedCornerShape(20.dp),
                                color = MaterialTheme.colorScheme.surfaceVariant
                            ) {
                                Row(
                                    modifier = Modifier.padding(horizontal = 10.dp, vertical = 4.dp),
                                    verticalAlignment = Alignment.CenterVertically
                                ) {
                                    Text(stringResource(currentSortMode.labelResId), style = MaterialTheme.typography.labelLarge)
                                    Spacer(Modifier.width(2.dp))
                                    Icon(Icons.Default.ArrowDropDown, contentDescription = "Sort", modifier = Modifier.size(16.dp))
                                }
                            }
                            DropdownMenu(
                                expanded = showSortDropdown,
                                onDismissRequest = { showSortDropdown = false }
                            ) {
                                ProfileSortMode.entries.forEach { mode ->
                                    DropdownMenuItem(
                                        text = { Text(stringResource(mode.labelResId)) },
                                        onClick = {
                                            showSortDropdown = false
                                            if (selectedTab == 0) viewModel.setNotesSortMode(mode)
                                            else viewModel.setRepliesSortMode(mode)
                                        },
                                        trailingIcon = if (currentSortMode == mode) {{
                                            Icon(Icons.Default.Check, contentDescription = null, modifier = Modifier.size(18.dp))
                                        }} else null
                                    )
                                }
                            }
                        }
                    }
                }
            }

            when (selectedTab) {
                0 -> if (isBlocked && !blockedContentRevealed) {
                    item { BlockedContentOverlay(onReveal = { blockedContentRevealed = true }) }
                } else {
                    // Pinned notes at the top of the Notes tab
                    val pinnedEvents = pinnedIds.mapNotNull { id -> eventRepo?.getEvent(id) }
                        .sortedByDescending { it.created_at }
                    if (pinnedEvents.isNotEmpty()) {
                        item {
                            Text(
                                stringResource(R.string.profile_pinned),
                                style = MaterialTheme.typography.labelMedium,
                                color = MaterialTheme.colorScheme.onSurfaceVariant,
                                modifier = Modifier.padding(horizontal = 16.dp, vertical = 6.dp)
                            )
                        }
                        items(items = pinnedEvents, key = { "pinned-${it.id}" }) { event ->
                            val eventProfile = eventRepo?.getProfileData(event.pubkey)
                            val pinnedTranslationState = remember(translationVersion, event.id) {
                                translationRepo?.getState(event.id) ?: com.wisp.app.repo.TranslationState()
                            }
                            val pinnedPollVoteCounts = remember(pollVoteVersion, event.id) {
                                if (event.kind == 1068) eventRepo?.getPollVoteCounts(event.id) ?: emptyMap() else emptyMap()
                            }
                            val pinnedPollTotalVotes = remember(pollVoteVersion, event.id) {
                                if (event.kind == 1068) eventRepo?.getPollTotalVotes(event.id) ?: 0 else 0
                            }
                            val pinnedUserPollVotes = remember(pollVoteVersion, event.id) {
                                if (event.kind == 1068) eventRepo?.getUserPollVotes(event.id) ?: emptyList() else emptyList()
                            }
                            val pinnedZapPollSatsCounts = remember(pollVoteVersion, event.id) {
                                if (event.kind == 6969) eventRepo?.getZapPollSatsCounts(event.id) ?: emptyMap() else emptyMap()
                            }
                            val pinnedZapPollTotalSats = remember(pollVoteVersion, event.id) {
                                if (event.kind == 6969) eventRepo?.getZapPollTotalSats(event.id) ?: 0L else 0L
                            }
                            val pinnedUserZapPollVote = remember(pollVoteVersion, event.id) {
                                if (event.kind == 6969) eventRepo?.getUserZapPollVote(event.id) else null
                            }
                            PostCard(
                                event = event,
                                profile = eventProfile,
                                onReply = { onReply(event) },
                                onNavigateToProfile = onNavigateToProfile,
                                onNoteClick = { onNoteClick(event) },
                                onQuotedNoteClick = onQuotedNoteClick,
                                onReact = { emoji -> onReact(event, emoji) },
                                onRepost = { onRepost(event) },
                                onQuote = { onQuote(event) },
                                eventRepo = eventRepo,
                                onAddToList = { onAddNoteToList(event.id) },
                                isInList = event.id in listedIds,
                                onPin = { onTogglePin(event.id) },
                                isPinned = true,
                                onDelete = { onDeleteEvent(event.id, event.kind) },
                                isOwnEvent = event.pubkey == userPubkey,
                                translationState = pinnedTranslationState,
                                onTranslate = { translationRepo?.translate(event.id, event.content) },
                                pollVoteCounts = pinnedPollVoteCounts,
                                pollTotalVotes = pinnedPollTotalVotes,
                                userPollVotes = pinnedUserPollVotes,
                                onPollVote = { optionIds -> onPollVote(event.id, optionIds) },
                                zapPollSatsCounts = pinnedZapPollSatsCounts,
                                zapPollTotalSats = pinnedZapPollTotalSats,
                                userZapPollVote = pinnedUserZapPollVote,
                                onZapPollVote = { idx -> onZapPollVote(event.id, idx) },
                                resolvedEmojis = resolvedEmojis,
                                unicodeEmojis = unicodeEmojis,
                                onOpenEmojiLibrary = onOpenEmojiLibrary,
                                noteActions = invoiceNoteActions
                            )
                        }
                    }

                    val displayNotes = if (notesSortMode == ProfileSortMode.RECENCY) rootNotes else sortedNotes
                    if (notesSortMode != ProfileSortMode.RECENCY && sortedNotes.isEmpty() && sortedNotesLoading) {
                        item {
                            Box(contentAlignment = Alignment.Center, modifier = Modifier.fillMaxWidth().padding(32.dp)) {
                                CircularProgressIndicator()
                            }
                        }
                    } else if (notesSortMode != ProfileSortMode.RECENCY && sortedNotes.isEmpty() && !sortedNotesLoading) {
                        item { FeedCrawlingMessage() }
                    } else if (displayNotes.isEmpty() && pinnedEvents.isEmpty()) {
                        item { EmptyTabContent(stringResource(R.string.profile_no_notes)) }
                    } else {
                        items(items = displayNotes, key = { it.id }) { event ->
                            if (event.kind == 30023) {
                                ProfileArticleCard(
                                    event = event,
                                    profile = profile,
                                    eventRepo = eventRepo,
                                    onArticleClick = onArticleClick,
                                    onProfileClick = onNavigateToProfile
                                )
                                return@items
                            }
                            val likeCount = reactionVersion.let { eventRepo?.getReactionCount(event.id) ?: 0 }
                            val replyCount = replyCountVersion.let { eventRepo?.getReplyCount(event.id) ?: 0 }
                            val repostCount = repostVersion.let { eventRepo?.getRepostCount(event.id) ?: 0 }
                            val zapSats = zapVersion.let { eventRepo?.getZapSats(event.id) ?: 0L }
                            val userEmojis = reactionVersion.let { userPubkey?.let { eventRepo?.getUserReactionEmojis(event.id, it) } ?: emptySet() }
                            val reactionDetails = remember(reactionVersion, event.id) {
                                eventRepo?.getReactionDetails(event.id) ?: emptyMap()
                            }
                            val zapDetails = remember(zapVersion, event.id) {
                                eventRepo?.getZapDetails(event.id) ?: emptyList()
                            }
                            val relayIcons = remember(relaySourceVersion, event.id) {
                                eventRepo?.getEventRelays(event.id)?.map { url ->
                                    url to relayInfoRepo?.getIconUrl(url)
                                } ?: emptyList()
                            }
                            val repostPubkey = viewModel.repostAuthors[event.id]
                            val profileRepostPubkeys = remember(repostPubkey) {
                                if (repostPubkey != null) listOf(repostPubkey) else emptyList()
                            }
                            val hasUserReposted = eventRepo?.hasUserReposted(event.id) == true
                            val hasUserZapped = zapVersion.let { eventRepo?.hasUserZapped(event.id) == true }
                            val eventReactionEmojiUrls = reactionVersion.let { eventRepo?.getReactionEmojiUrls(event.id) ?: emptyMap() }
                            val rootTranslationState = remember(translationVersion, event.id) {
                                translationRepo?.getState(event.id) ?: com.wisp.app.repo.TranslationState()
                            }
                            val rootPollVoteCounts = remember(pollVoteVersion, event.id) {
                                if (event.kind == 1068) eventRepo?.getPollVoteCounts(event.id) ?: emptyMap() else emptyMap()
                            }
                            val rootPollTotalVotes = remember(pollVoteVersion, event.id) {
                                if (event.kind == 1068) eventRepo?.getPollTotalVotes(event.id) ?: 0 else 0
                            }
                            val rootUserPollVotes = remember(pollVoteVersion, event.id) {
                                if (event.kind == 1068) eventRepo?.getUserPollVotes(event.id) ?: emptyList() else emptyList()
                            }
                            val rootZapPollSatsCounts = remember(pollVoteVersion, event.id) {
                                if (event.kind == 6969) eventRepo?.getZapPollSatsCounts(event.id) ?: emptyMap() else emptyMap()
                            }
                            val rootZapPollTotalSats = remember(pollVoteVersion, event.id) {
                                if (event.kind == 6969) eventRepo?.getZapPollTotalSats(event.id) ?: 0L else 0L
                            }
                            val rootUserZapPollVote = remember(pollVoteVersion, event.id) {
                                if (event.kind == 6969) eventRepo?.getUserZapPollVote(event.id) else null
                            }
                            PostCard(
                                event = event,
                                profile = if (repostPubkey != null) eventRepo?.getProfileData(event.pubkey) else profile,
                                onReply = { onReply(event) },
                                onNavigateToProfile = onNavigateToProfile,
                                onNoteClick = { onNoteClick(event) },
                                onQuotedNoteClick = onQuotedNoteClick,
                                onReact = { emoji -> onReact(event, emoji) },
                                onRepost = { onRepost(event) },
                                onQuote = { onQuote(event) },
                                userReactionEmojis = userEmojis,
                                hasUserReposted = hasUserReposted,
                                onZap = { zapTargetEvent = event },
                                hasUserZapped = hasUserZapped,
                                likeCount = likeCount,
                                replyCount = replyCount,
                                repostCount = repostCount,
                                zapSats = zapSats,
                                isZapAnimating = event.id in zapAnimatingIds,
                                isZapInProgress = event.id in zapInProgressIds,
                                eventRepo = eventRepo,
                                repostPubkeys = profileRepostPubkeys,
                                reactionDetails = reactionDetails,
                                zapDetails = zapDetails,
                                reactionEmojiUrls = eventReactionEmojiUrls,
                                relayIcons = relayIcons,
                                onNavigateToProfileFromDetails = onNavigateToProfile,
                                onFollowAuthor = { onToggleFollow?.invoke(event.pubkey) },
                                onBlockAuthor = { onBlockUser?.invoke() },
                                isFollowingAuthor = contactRepo.isFollowing(event.pubkey),
                                isOwnEvent = event.pubkey == userPubkey,
                                nip05Repo = nip05Repo,
                                onAddToList = { onAddNoteToList(event.id) },
                                isInList = event.id in listedIds,
                                onPin = { onTogglePin(event.id) },
                                isPinned = event.id in pinnedIds,
                                onDelete = { onDeleteEvent(event.id, event.kind) },
                                translationState = rootTranslationState,
                                onTranslate = { translationRepo?.translate(event.id, event.content) },
                                pollVoteCounts = rootPollVoteCounts,
                                pollTotalVotes = rootPollTotalVotes,
                                userPollVotes = rootUserPollVotes,
                                onPollVote = { optionIds -> onPollVote(event.id, optionIds) },
                                zapPollSatsCounts = rootZapPollSatsCounts,
                                zapPollTotalSats = rootZapPollTotalSats,
                                userZapPollVote = rootUserZapPollVote,
                                onZapPollVote = { idx -> onZapPollVote(event.id, idx) },
                                resolvedEmojis = resolvedEmojis,
                                unicodeEmojis = unicodeEmojis,
                                onOpenEmojiLibrary = onOpenEmojiLibrary,
                                noteActions = invoiceNoteActions
                            )
                        }
                        if (rootNotes.isNotEmpty() && notesSortMode == ProfileSortMode.RECENCY) {
                            item {
                                LoadMoreButton(onClick = { viewModel.loadMoreNotes() })
                            }
                        }
                    }
                }
                2 -> {
                    // Gallery tab — 2-column grid of gallery posts
                    if (galleryPosts.isEmpty()) {
                        item { EmptyTabContent(stringResource(R.string.profile_no_gallery)) }
                    } else {
                        items(items = galleryPosts.chunked(2), key = { row -> row.first().id }) { row ->
                            Row(
                                modifier = Modifier
                                    .fillMaxWidth()
                                    .padding(horizontal = 2.dp),
                                horizontalArrangement = Arrangement.spacedBy(2.dp)
                            ) {
                                for (event in row) {
                                    val firstMedia = remember(event.id) {
                                        val img = com.wisp.app.nostr.Nip68.parseImetaEntries(event).firstOrNull()
                                        val vid = com.wisp.app.nostr.Nip71.parseVideoMeta(event).firstOrNull()
                                        Triple(img?.url ?: vid?.thumbnailUrl, vid != null && img == null, event)
                                    }
                                    Box(
                                        modifier = Modifier
                                            .weight(1f)
                                            .aspectRatio(1f)
                                            .padding(1.dp)
                                            .clip(RoundedCornerShape(4.dp))
                                            .clickable { onNoteClick(event) }
                                    ) {
                                        if (firstMedia.first != null) {
                                            coil3.compose.AsyncImage(
                                                model = firstMedia.first,
                                                contentDescription = null,
                                                contentScale = androidx.compose.ui.layout.ContentScale.Crop,
                                                modifier = Modifier.fillMaxSize()
                                            )
                                        } else {
                                            Box(
                                                modifier = Modifier
                                                    .fillMaxSize()
                                                    .background(MaterialTheme.colorScheme.surfaceVariant)
                                            )
                                        }
                                        // Play icon overlay for video posts
                                        if (firstMedia.second) {
                                            Box(
                                                modifier = Modifier
                                                    .align(Alignment.Center)
                                                    .size(32.dp)
                                                    .clip(androidx.compose.foundation.shape.CircleShape)
                                                    .background(Color.Black.copy(alpha = 0.5f)),
                                                contentAlignment = Alignment.Center
                                            ) {
                                                Icon(
                                                    Icons.Default.PlayArrow,
                                                    contentDescription = "Video",
                                                    tint = Color.White,
                                                    modifier = Modifier.size(20.dp)
                                                )
                                            }
                                        }
                                    }
                                }
                                // Fill remaining space if odd number
                                if (row.size == 1) {
                                    Spacer(Modifier.weight(1f))
                                }
                            }
                        }
                    }
                }
                1 -> if (isBlocked && !blockedContentRevealed) {
                    item { BlockedContentOverlay(onReveal = { blockedContentRevealed = true }) }
                } else {
                    val displayReplies = if (repliesSortMode == ProfileSortMode.RECENCY) replies else sortedReplies
                    if (repliesSortMode != ProfileSortMode.RECENCY && sortedReplies.isEmpty() && sortedRepliesLoading) {
                        item {
                            Box(contentAlignment = Alignment.Center, modifier = Modifier.fillMaxWidth().padding(32.dp)) {
                                CircularProgressIndicator()
                            }
                        }
                    } else if (repliesSortMode != ProfileSortMode.RECENCY && sortedReplies.isEmpty() && !sortedRepliesLoading) {
                        item { FeedCrawlingMessage() }
                    } else if (displayReplies.isEmpty()) {
                        item { EmptyTabContent(stringResource(R.string.profile_no_replies)) }
                    } else {
                        items(items = displayReplies, key = { it.id }) { event ->
                            val likeCount = reactionVersion.let { eventRepo?.getReactionCount(event.id) ?: 0 }
                            val replyCount = replyCountVersion.let { eventRepo?.getReplyCount(event.id) ?: 0 }
                            val repostCount2 = repostVersion.let { eventRepo?.getRepostCount(event.id) ?: 0 }
                            val zapSats = zapVersion.let { eventRepo?.getZapSats(event.id) ?: 0L }
                            val userEmojis = reactionVersion.let { userPubkey?.let { eventRepo?.getUserReactionEmojis(event.id, it) } ?: emptySet() }
                            val reactionDetails = remember(reactionVersion, event.id) {
                                eventRepo?.getReactionDetails(event.id) ?: emptyMap()
                            }
                            val zapDetails = remember(zapVersion, event.id) {
                                eventRepo?.getZapDetails(event.id) ?: emptyList()
                            }
                            val relayIcons = remember(relaySourceVersion, event.id) {
                                eventRepo?.getEventRelays(event.id)?.map { url ->
                                    url to relayInfoRepo?.getIconUrl(url)
                                } ?: emptyList()
                            }
                            val hasUserReposted2 = eventRepo?.hasUserReposted(event.id) == true
                            val hasUserZapped2 = zapVersion.let { eventRepo?.hasUserZapped(event.id) == true }
                            val eventReactionEmojiUrls2 = reactionVersion.let { eventRepo?.getReactionEmojiUrls(event.id) ?: emptyMap() }
                            val replyTranslationState = remember(translationVersion, event.id) {
                                translationRepo?.getState(event.id) ?: com.wisp.app.repo.TranslationState()
                            }
                            val replyPollVoteCounts = remember(pollVoteVersion, event.id) {
                                if (event.kind == 1068) eventRepo?.getPollVoteCounts(event.id) ?: emptyMap() else emptyMap()
                            }
                            val replyPollTotalVotes = remember(pollVoteVersion, event.id) {
                                if (event.kind == 1068) eventRepo?.getPollTotalVotes(event.id) ?: 0 else 0
                            }
                            val replyUserPollVotes = remember(pollVoteVersion, event.id) {
                                if (event.kind == 1068) eventRepo?.getUserPollVotes(event.id) ?: emptyList() else emptyList()
                            }
                            val replyZapPollSatsCounts = remember(pollVoteVersion, event.id) {
                                if (event.kind == 6969) eventRepo?.getZapPollSatsCounts(event.id) ?: emptyMap() else emptyMap()
                            }
                            val replyZapPollTotalSats = remember(pollVoteVersion, event.id) {
                                if (event.kind == 6969) eventRepo?.getZapPollTotalSats(event.id) ?: 0L else 0L
                            }
                            val replyUserZapPollVote = remember(pollVoteVersion, event.id) {
                                if (event.kind == 6969) eventRepo?.getUserZapPollVote(event.id) else null
                            }
                            PostCard(
                                event = event,
                                profile = profile,
                                onReply = { onReply(event) },
                                onNavigateToProfile = onNavigateToProfile,
                                onNoteClick = { onNoteClick(event) },
                                onQuotedNoteClick = onQuotedNoteClick,
                                onReact = { emoji -> onReact(event, emoji) },
                                onRepost = { onRepost(event) },
                                onQuote = { onQuote(event) },
                                userReactionEmojis = userEmojis,
                                hasUserReposted = hasUserReposted2,
                                onZap = { zapTargetEvent = event },
                                hasUserZapped = hasUserZapped2,
                                likeCount = likeCount,
                                replyCount = replyCount,
                                repostCount = repostCount2,
                                zapSats = zapSats,
                                isZapAnimating = event.id in zapAnimatingIds,
                                isZapInProgress = event.id in zapInProgressIds,
                                eventRepo = eventRepo,
                                reactionDetails = reactionDetails,
                                zapDetails = zapDetails,
                                reactionEmojiUrls = eventReactionEmojiUrls2,
                                relayIcons = relayIcons,
                                onNavigateToProfileFromDetails = onNavigateToProfile,
                                onFollowAuthor = { onToggleFollow?.invoke(event.pubkey) },
                                onBlockAuthor = { onBlockUser?.invoke() },
                                isFollowingAuthor = contactRepo.isFollowing(event.pubkey),
                                isOwnEvent = event.pubkey == userPubkey,
                                nip05Repo = nip05Repo,
                                onAddToList = { onAddNoteToList(event.id) },
                                isInList = event.id in listedIds,
                                onPin = { onTogglePin(event.id) },
                                isPinned = event.id in pinnedIds,
                                onDelete = { onDeleteEvent(event.id, event.kind) },
                                translationState = replyTranslationState,
                                onTranslate = { translationRepo?.translate(event.id, event.content) },
                                pollVoteCounts = replyPollVoteCounts,
                                pollTotalVotes = replyPollTotalVotes,
                                userPollVotes = replyUserPollVotes,
                                onPollVote = { optionIds -> onPollVote(event.id, optionIds) },
                                zapPollSatsCounts = replyZapPollSatsCounts,
                                zapPollTotalSats = replyZapPollTotalSats,
                                userZapPollVote = replyUserZapPollVote,
                                onZapPollVote = { idx -> onZapPollVote(event.id, idx) },
                                resolvedEmojis = resolvedEmojis,
                                unicodeEmojis = unicodeEmojis,
                                onOpenEmojiLibrary = onOpenEmojiLibrary,
                                noteActions = invoiceNoteActions
                            )
                        }
                        if (repliesSortMode == ProfileSortMode.RECENCY) {
                            item {
                                LoadMoreButton(onClick = { viewModel.loadMoreReplies() })
                            }
                        }
                    }
                }
                3 -> {
                    if (mediaItems.isEmpty()) {
                        item { EmptyTabContent(stringResource(R.string.profile_no_media)) }
                    } else {
                        items(items = mediaItems.chunked(3), key = { row -> row.first().url }) { row ->
                            MediaGridRow(
                                items = row,
                                onImageClick = { url -> fullScreenMediaImageUrl = url },
                                onVideoClick = { url -> fullScreenMediaVideoUrl = url }
                            )
                        }
                    }
                }
                4 -> {
                    if (followList.isEmpty()) {
                        item { EmptyTabContent(stringResource(R.string.profile_not_following)) }
                    } else {
                        @Suppress("UNUSED_EXPRESSION")
                        followProfileVersion
                        items(items = followList, key = { it.pubkey }) { entry ->
                            val isEntryFollowed = myFollowList.any { it.pubkey == entry.pubkey }
                            FollowEntryRow(
                                entry = entry,
                                eventRepo = eventRepo,
                                isFollowing = isEntryFollowed,
                                isOwnProfile = isOwnProfile,
                                onToggleFollow = { onToggleFollow?.invoke(entry.pubkey) },
                                onClick = { onNavigateToProfile?.invoke(entry.pubkey) }
                            )
                        }
                    }
                }
                5 -> {
                    if (followersLoading && followers.isEmpty()) {
                        item {
                            Box(contentAlignment = Alignment.Center, modifier = Modifier.fillMaxWidth().padding(32.dp)) {
                                CircularProgressIndicator()
                            }
                        }
                    } else if (followers.isEmpty()) {
                        item { EmptyTabContent(stringResource(R.string.profile_no_followers)) }
                    } else {
                        items(items = followers, key = { it.pubkey }) { followerProfile ->
                            FollowerRow(
                                profile = followerProfile,
                                isFollowing = myFollowList.any { it.pubkey == followerProfile.pubkey },
                                onToggleFollow = { onToggleFollow?.invoke(followerProfile.pubkey) },
                                onClick = { onNavigateToProfile?.invoke(followerProfile.pubkey) }
                            )
                        }
                    }
                }
                6 -> {
                    if (groupsLoading && groups.isEmpty()) {
                        item {
                            Box(contentAlignment = Alignment.Center, modifier = Modifier.fillMaxWidth().padding(32.dp)) {
                                CircularProgressIndicator()
                            }
                        }
                    } else if (groups.isEmpty()) {
                        item { EmptyTabContent(stringResource(R.string.profile_no_groups)) }
                    } else {
                        items(items = groups, key = { "${it.relayUrl}|${it.groupId}" }) { entry ->
                            Box(modifier = Modifier.padding(horizontal = 12.dp)) {
                                com.wisp.app.ui.component.GroupCard(
                                    relayUrl = entry.relayUrl,
                                    groupId = entry.groupId,
                                    onClick = if (onGroupRoom != null) {
                                        { onGroupRoom.invoke(entry.relayUrl, entry.groupId) }
                                    } else null,
                                    onFetchPreview = fetchGroupPreview,
                                    eventRepo = eventRepo
                                )
                            }
                        }
                    }
                }
                7 -> {
                    if (relayList.isEmpty() && relayHints.isEmpty()) {
                        item { EmptyTabContent(stringResource(R.string.profile_no_relays)) }
                    } else {
                        if (relayList.isNotEmpty()) {
                            item {
                                SectionLabel(stringResource(R.string.profile_relay_list))
                            }
                            items(items = relayList.distinctBy { it.url }, key = { it.url }) { relay ->
                                RelayRow(relay)
                            }
                        }
                        // Show relay hints (discovered from events) that aren't already in the relay list
                        val relayListUrls = relayList.map { it.url }.toSet()
                        val extraHints = relayHints.filter { it !in relayListUrls }.sorted()
                        if (extraHints.isNotEmpty()) {
                            item {
                                SectionLabel(stringResource(if (relayList.isEmpty()) R.string.profile_discovered_relays else R.string.profile_other_discovered_relays))
                            }
                            items(items = extraHints, key = { it }) { url ->
                                HintRelayRow(url)
                            }
                        }
                    }
                }
            }
        }
    }
}

@Composable
private fun ProfileHeader(
    profile: ProfileData?,
    isOwnProfile: Boolean,
    isFollowing: Boolean,
    onEditProfile: () -> Unit,
    onToggleFollow: () -> Unit,
    nip05Repo: Nip05Repository? = null,
    pubkey: String = "",
    eventRepo: EventRepository? = null,
    onNavigateToProfile: ((String) -> Unit)? = null,
    onSendDm: (() -> Unit)? = null,
    onZapClick: (() -> Unit)? = null,
    followingCount: Int = 0,
    followedBy: List<String> = emptyList(),
    followsYou: Boolean = false,
    isBlocked: Boolean = false
) {
    var fullScreenImageUrl by remember { mutableStateOf<String?>(null) }

    if (fullScreenImageUrl != null) {
        FullScreenImageViewer(
            imageUrl = fullScreenImageUrl!!,
            onDismiss = { fullScreenImageUrl = null }
        )
    }

    // Banner
    Box(
        modifier = Modifier
            .fillMaxWidth()
            .height(150.dp)
            .background(MaterialTheme.colorScheme.surfaceVariant)
    ) {
        profile?.banner?.let { bannerUrl ->
            AsyncImage(
                model = bannerUrl,
                contentDescription = "Banner",
                contentScale = ContentScale.Crop,
                modifier = Modifier
                    .fillMaxSize()
                    .clickable { fullScreenImageUrl = bannerUrl }
            )
        }
    }

    // Profile info overlapping banner
    Column(
        modifier = Modifier
            .fillMaxWidth()
            .padding(horizontal = 16.dp)
    ) {
        Row(
            verticalAlignment = Alignment.Bottom,
            modifier = Modifier.offset(y = (-16).dp)
        ) {
            ProfilePicture(
                url = profile?.picture,
                size = 72,
                showBlockedBadge = isBlocked,
                onClick = profile?.picture?.let { url -> { fullScreenImageUrl = url } }
            )
            Spacer(Modifier.weight(1f))
            if (isOwnProfile) {
                OutlinedButton(onClick = onEditProfile) {
                    Text(stringResource(R.string.profile_edit))
                }
            } else {
                Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
                    if (onSendDm != null) {
                        IconButton(onClick = onSendDm) {
                            Icon(
                                Icons.AutoMirrored.Filled.Send,
                                contentDescription = stringResource(R.string.profile_send_message),
                                tint = MaterialTheme.colorScheme.primary
                            )
                        }
                    }
                    if (profile?.lud16 != null && onZapClick != null) {
                        val useZapBolt = com.wisp.app.ui.util.useBoltIcon()
                        IconButton(onClick = onZapClick) {
                            if (useZapBolt) {
                                Icon(
                                    painter = painterResource(R.drawable.ic_bolt),
                                    contentDescription = "Zap",
                                    tint = Color(0xFFFFC107),
                                    modifier = Modifier.size(22.dp)
                                )
                            } else {
                                Icon(
                                    Icons.Outlined.CurrencyBitcoin,
                                    contentDescription = "Zap",
                                    tint = Color(0xFFFFC107),
                                    modifier = Modifier.size(22.dp)
                                )
                            }
                        }
                    }
                    FollowButton(
                        isFollowing = isFollowing,
                        onClick = onToggleFollow
                    )
                }
            }
        }

        Row(
            verticalAlignment = Alignment.CenterVertically,
            horizontalArrangement = Arrangement.spacedBy(8.dp)
        ) {
            Text(
                text = profile?.displayString ?: "",
                style = MaterialTheme.typography.titleLarge,
                color = MaterialTheme.colorScheme.onSurface
            )
            if (followsYou) {
                Text(
                    text = stringResource(R.string.profile_follows_you),
                    style = MaterialTheme.typography.labelSmall,
                    color = MaterialTheme.colorScheme.onSurfaceVariant,
                    modifier = Modifier
                        .background(
                            MaterialTheme.colorScheme.surfaceVariant,
                            RoundedCornerShape(4.dp)
                        )
                        .padding(horizontal = 6.dp, vertical = 2.dp)
                )
            }
        }

        profile?.nip05?.let { nip05 ->
            Nip05Badge(
                nip05 = nip05,
                pubkey = pubkey,
                nip05Repo = nip05Repo,
                verifiedTint = Color(0xFFFF8C00)
            )
        }

        profile?.about?.let { about ->
            val emojiMap = remember(pubkey) { Nip30.parseEmojiTags(emptyList()) } // Profiles use inline or alternate tags usually not available here easily without event
            val imetaMap = remember(pubkey) { parseImetaTags(emptyList()) }
            Spacer(Modifier.height(8.dp))
            RichContent(
                content = about,
                style = MaterialTheme.typography.bodyMedium,
                color = MaterialTheme.colorScheme.onSurface,
                plainLinks = true,
                emojiMap = emojiMap,
                imetaMap = imetaMap,
                eventRepo = eventRepo,
                onProfileClick = onNavigateToProfile
            )
        }

        profile?.lud16?.let { lightning ->
            val context = LocalContext.current
            Spacer(Modifier.height(6.dp))
            Row(
                verticalAlignment = Alignment.CenterVertically,
                modifier = Modifier.clickable {
                    val clipboard = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
                    clipboard.setPrimaryClip(ClipData.newPlainText("Lightning address", lightning))
                    Toast.makeText(context, "Copied to clipboard", Toast.LENGTH_SHORT).show()
                }
            ) {
                val useBoltIcon = com.wisp.app.ui.util.useBoltIcon()
                if (useBoltIcon) {
                    Icon(
                        painter = painterResource(R.drawable.ic_bolt),
                        contentDescription = "Lightning address",
                        tint = Color(0xFFFFC107),
                        modifier = Modifier.size(16.dp)
                    )
                } else {
                    Icon(
                        Icons.Outlined.CurrencyBitcoin,
                        contentDescription = "Lightning address",
                        tint = Color(0xFFFFC107),
                        modifier = Modifier.size(16.dp)
                    )
                }
                Spacer(Modifier.width(4.dp))
                Text(
                    text = lightning,
                    style = MaterialTheme.typography.bodyMedium,
                    color = MaterialTheme.colorScheme.onSurfaceVariant
                )
            }
        }

        // Following / Followers in your network counts
        if (followingCount > 0 || followedBy.isNotEmpty()) {
            Spacer(Modifier.height(10.dp))
            Row(verticalAlignment = Alignment.CenterVertically) {
                if (followingCount > 0) {
                    Text(
                        text = "$followingCount",
                        style = MaterialTheme.typography.titleSmall,
                        color = MaterialTheme.colorScheme.onSurface
                    )
                    Spacer(Modifier.width(3.dp))
                    Text(
                        text = "Following",
                        style = MaterialTheme.typography.bodySmall,
                        color = MaterialTheme.colorScheme.onSurfaceVariant
                    )
                }
                if (followingCount > 0 && followedBy.isNotEmpty()) {
                    Spacer(Modifier.width(16.dp))
                }
                if (followedBy.isNotEmpty()) {
                    Text(
                        text = "${followedBy.size}",
                        style = MaterialTheme.typography.titleSmall,
                        color = MaterialTheme.colorScheme.onSurface
                    )
                    Spacer(Modifier.width(3.dp))
                    Text(
                        text = "Followers in your network",
                        style = MaterialTheme.typography.bodySmall,
                        color = MaterialTheme.colorScheme.onSurfaceVariant
                    )
                }
            }
        }

        // Followed-by avatars row
        if (followedBy.isNotEmpty()) {
            Spacer(Modifier.height(8.dp))
            val displayPubkeys = followedBy.take(10)
            val othersCount = followedBy.size - displayPubkeys.size
            val avatarSize = 22
            val overlap = 16
            val boxWidth = (avatarSize + (displayPubkeys.size - 1) * overlap).dp
            Row(verticalAlignment = Alignment.CenterVertically) {
                Box(modifier = Modifier.width(boxWidth).height(avatarSize.dp)) {
                    displayPubkeys.forEachIndexed { index, pk ->
                        Box(modifier = Modifier.offset(x = (index * overlap).dp)) {
                            ProfilePicture(
                                url = eventRepo?.getProfileData(pk)?.picture,
                                size = avatarSize,
                                onClick = { onNavigateToProfile?.invoke(pk) }
                            )
                        }
                    }
                }
                Spacer(Modifier.width(8.dp))
                if (othersCount > 0) {
                    Text(
                        text = "+$othersCount others in your network",
                        style = MaterialTheme.typography.bodySmall,
                        color = MaterialTheme.colorScheme.onSurfaceVariant
                    )
                }
            }
        }

        Spacer(Modifier.height(16.dp))
    }
}

@Composable
private fun FollowEntryRow(
    entry: Nip02.FollowEntry,
    eventRepo: EventRepository?,
    isFollowing: Boolean,
    isOwnProfile: Boolean,
    onToggleFollow: () -> Unit,
    onClick: () -> Unit
) {
    val profile = eventRepo?.getProfileData(entry.pubkey)
    val displayName = profile?.displayString
        ?: entry.pubkey.take(8) + "..." + entry.pubkey.takeLast(4)

    Row(
        verticalAlignment = Alignment.CenterVertically,
        modifier = Modifier
            .fillMaxWidth()
            .clickable(onClick = onClick)
            .padding(horizontal = 16.dp, vertical = 10.dp)
    ) {
        ProfilePicture(url = profile?.picture, size = 40)
        Spacer(Modifier.width(12.dp))
        Column(modifier = Modifier.weight(1f)) {
            Text(
                text = displayName,
                style = MaterialTheme.typography.bodyLarge,
                color = MaterialTheme.colorScheme.onSurface,
                maxLines = 1,
                overflow = TextOverflow.Ellipsis
            )
            if (entry.petname != null) {
                Text(
                    text = entry.petname,
                    style = MaterialTheme.typography.bodySmall,
                    color = MaterialTheme.colorScheme.onSurfaceVariant,
                    maxLines = 1,
                    overflow = TextOverflow.Ellipsis
                )
            }
        }
        if (!isOwnProfile) {
            Spacer(Modifier.width(8.dp))
            FollowButton(
                isFollowing = isFollowing,
                onClick = onToggleFollow
            )
        }
    }
}

@OptIn(ExperimentalLayoutApi::class)
@Composable
private fun RelayRow(relay: RelayConfig) {
    val displayUrl = relay.url
        .removePrefix("wss://")
        .removePrefix("ws://")

    Row(
        verticalAlignment = Alignment.CenterVertically,
        modifier = Modifier
            .fillMaxWidth()
            .padding(horizontal = 16.dp, vertical = 10.dp)
    ) {
        Text(
            text = displayUrl,
            style = MaterialTheme.typography.bodyLarge,
            color = MaterialTheme.colorScheme.onSurface,
            maxLines = 1,
            overflow = TextOverflow.Ellipsis,
            modifier = Modifier.weight(1f)
        )
        Spacer(Modifier.width(8.dp))
        FlowRow(horizontalArrangement = Arrangement.spacedBy(4.dp)) {
            if (relay.read) {
                Text(
                    text = "R",
                    style = MaterialTheme.typography.labelSmall,
                    color = MaterialTheme.colorScheme.onSecondaryContainer,
                    modifier = Modifier
                        .background(
                            MaterialTheme.colorScheme.secondaryContainer,
                            RoundedCornerShape(4.dp)
                        )
                        .padding(horizontal = 6.dp, vertical = 2.dp)
                )
            }
            if (relay.write) {
                Text(
                    text = "W",
                    style = MaterialTheme.typography.labelSmall,
                    color = MaterialTheme.colorScheme.onTertiaryContainer,
                    modifier = Modifier
                        .background(
                            MaterialTheme.colorScheme.tertiaryContainer,
                            RoundedCornerShape(4.dp)
                        )
                        .padding(horizontal = 6.dp, vertical = 2.dp)
                )
            }
        }
    }
}

@Composable
private fun SectionLabel(text: String) {
    Text(
        text = text,
        style = MaterialTheme.typography.labelMedium,
        color = MaterialTheme.colorScheme.onSurfaceVariant,
        modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp)
    )
}

@Composable
private fun HintRelayRow(url: String) {
    val displayUrl = url
        .removePrefix("wss://")
        .removePrefix("ws://")

    Row(
        verticalAlignment = Alignment.CenterVertically,
        modifier = Modifier
            .fillMaxWidth()
            .padding(horizontal = 16.dp, vertical = 10.dp)
    ) {
        Text(
            text = displayUrl,
            style = MaterialTheme.typography.bodyLarge,
            color = MaterialTheme.colorScheme.onSurfaceVariant,
            maxLines = 1,
            overflow = TextOverflow.Ellipsis,
            modifier = Modifier.weight(1f)
        )
        Spacer(Modifier.width(8.dp))
        Text(
            text = "hint",
            style = MaterialTheme.typography.labelSmall,
            color = MaterialTheme.colorScheme.onSurfaceVariant,
            modifier = Modifier
                .background(
                    MaterialTheme.colorScheme.surfaceVariant,
                    RoundedCornerShape(4.dp)
                )
                .padding(horizontal = 6.dp, vertical = 2.dp)
        )
    }
}

@Composable
private fun AddToListDialog(
    pubkey: String,
    ownLists: List<FollowSet>,
    onAddToList: (String) -> Unit,
    onRemoveFromList: (String) -> Unit,
    onCreateList: ((String, Boolean) -> Unit)?,
    onDismiss: () -> Unit
) {
    var newListName by remember { mutableStateOf("") }
    var newListPrivate by remember { mutableStateOf(false) }

    AlertDialog(
        onDismissRequest = onDismiss,
        title = { Text("Add to List") },
        text = {
            Column {
                if (ownLists.isEmpty()) {
                    Text(
                        "No lists yet. Create one below.",
                        color = MaterialTheme.colorScheme.onSurfaceVariant,
                        modifier = Modifier.padding(bottom = 8.dp)
                    )
                } else {
                    ownLists.forEach { list ->
                        val isMember = pubkey in list.members
                        Row(
                            verticalAlignment = Alignment.CenterVertically,
                            modifier = Modifier
                                .fillMaxWidth()
                                .clickable {
                                    if (isMember) onRemoveFromList(list.dTag)
                                    else onAddToList(list.dTag)
                                }
                                .padding(vertical = 8.dp)
                        ) {
                            androidx.compose.material3.Checkbox(
                                checked = isMember,
                                onCheckedChange = {
                                    if (isMember) onRemoveFromList(list.dTag)
                                    else onAddToList(list.dTag)
                                }
                            )
                            Spacer(Modifier.width(8.dp))
                            Text(
                                list.name,
                                style = MaterialTheme.typography.bodyLarge,
                                modifier = Modifier.weight(1f)
                            )
                            if (list.isPrivate) {
                                androidx.compose.material3.Icon(
                                    Icons.Outlined.Lock,
                                    contentDescription = "Private",
                                    tint = MaterialTheme.colorScheme.onSurfaceVariant,
                                    modifier = Modifier.size(14.dp)
                                )
                                Spacer(Modifier.width(4.dp))
                            }
                            Text(
                                "${list.members.size}",
                                style = MaterialTheme.typography.bodySmall,
                                color = MaterialTheme.colorScheme.onSurfaceVariant
                            )
                        }
                    }
                }
                Spacer(Modifier.height(12.dp))
                Row(
                    verticalAlignment = Alignment.CenterVertically,
                    modifier = Modifier.fillMaxWidth()
                ) {
                    androidx.compose.material3.OutlinedTextField(
                        value = newListName,
                        onValueChange = { newListName = it },
                        placeholder = { Text("New list name") },
                        singleLine = true,
                        modifier = Modifier.weight(1f)
                    )
                    Spacer(Modifier.width(8.dp))
                    TextButton(
                        onClick = {
                            if (newListName.isNotBlank()) {
                                onCreateList?.invoke(newListName.trim(), newListPrivate)
                                newListName = ""
                                newListPrivate = false
                            }
                        },
                        enabled = newListName.isNotBlank()
                    ) {
                        Text("Create")
                    }
                }
                Row(
                    verticalAlignment = Alignment.CenterVertically,
                    modifier = Modifier.padding(top = 4.dp)
                ) {
                    androidx.compose.material3.Icon(
                        Icons.Outlined.Lock,
                        contentDescription = null,
                        tint = MaterialTheme.colorScheme.onSurfaceVariant,
                        modifier = Modifier.size(16.dp)
                    )
                    Spacer(Modifier.width(4.dp))
                    Text(
                        "Private",
                        style = MaterialTheme.typography.bodySmall,
                        color = MaterialTheme.colorScheme.onSurfaceVariant
                    )
                    Spacer(Modifier.width(4.dp))
                    androidx.compose.material3.Switch(
                        checked = newListPrivate,
                        onCheckedChange = { newListPrivate = it },
                        modifier = Modifier.height(24.dp)
                    )
                }
            }
        },
        confirmButton = {
            TextButton(onClick = onDismiss) { Text("Done") }
        },
        dismissButton = {}
    )
}

@Composable
private fun LoadMoreButton(onClick: () -> Unit) {
    Box(
        contentAlignment = Alignment.Center,
        modifier = Modifier
            .fillMaxWidth()
            .padding(vertical = 16.dp)
    ) {
        OutlinedButton(onClick = onClick) {
            Text("Load More")
        }
    }
}

@Composable
private fun FollowerRow(
    profile: ProfileData,
    isFollowing: Boolean,
    onToggleFollow: () -> Unit,
    onClick: () -> Unit
) {
    Row(
        verticalAlignment = Alignment.CenterVertically,
        modifier = Modifier
            .fillMaxWidth()
            .clickable(onClick = onClick)
            .padding(horizontal = 16.dp, vertical = 10.dp)
    ) {
        ProfilePicture(url = profile.picture, size = 40)
        Spacer(Modifier.width(12.dp))
        Text(
            text = profile.displayString,
            style = MaterialTheme.typography.bodyLarge,
            color = MaterialTheme.colorScheme.onSurface,
            maxLines = 1,
            overflow = TextOverflow.Ellipsis,
            modifier = Modifier.weight(1f)
        )
        Spacer(Modifier.width(8.dp))
        FollowButton(isFollowing = isFollowing, onClick = onToggleFollow)
    }
}

@Composable
private fun FeedCrawlingMessage() {
    Column(
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.spacedBy(8.dp),
        modifier = Modifier
            .fillMaxWidth()
            .padding(horizontal = 32.dp, vertical = 40.dp)
    ) {
        Text(
            text = stringResource(R.string.profile_crawling_still),
            style = MaterialTheme.typography.bodyLarge,
            color = MaterialTheme.colorScheme.onSurface
        )
        Text(
            text = stringResource(R.string.profile_crawling_no_results),
            style = MaterialTheme.typography.bodyMedium,
            color = MaterialTheme.colorScheme.onSurfaceVariant
        )
    }
}

@Composable
private fun EmptyTabContent(message: String) {
    Box(
        contentAlignment = Alignment.Center,
        modifier = Modifier
            .fillMaxWidth()
            .height(200.dp)
    ) {
        Text(
            text = message,
            style = MaterialTheme.typography.bodyLarge,
            color = MaterialTheme.colorScheme.onSurfaceVariant
        )
    }
}

private enum class MediaType { IMAGE, VIDEO }

private data class MediaItem(val url: String, val type: MediaType)

@Composable
private fun MediaGridRow(
    items: List<MediaItem>,
    onImageClick: (String) -> Unit,
    onVideoClick: (String) -> Unit
) {
    Row(
        horizontalArrangement = Arrangement.spacedBy(2.dp),
        modifier = Modifier
            .fillMaxWidth()
            .padding(bottom = 2.dp)
    ) {
        items.forEach { item ->
            Box(
                modifier = Modifier
                    .weight(1f)
                    .aspectRatio(1f)
                    .clickable {
                        when (item.type) {
                            MediaType.IMAGE -> onImageClick(item.url)
                            MediaType.VIDEO -> onVideoClick(item.url)
                        }
                    }
            ) {
                AsyncImage(
                    model = item.url,
                    contentDescription = null,
                    contentScale = ContentScale.Crop,
                    modifier = Modifier.fillMaxSize()
                )
                if (item.type == MediaType.VIDEO) {
                    Box(
                        contentAlignment = Alignment.Center,
                        modifier = Modifier
                            .fillMaxSize()
                            .background(Color.Black.copy(alpha = 0.3f))
                    ) {
                        Icon(
                            imageVector = Icons.Default.PlayArrow,
                            contentDescription = "Play video",
                            tint = Color.White,
                            modifier = Modifier.size(36.dp)
                        )
                    }
                }
            }
        }
        // Fill remaining cells in incomplete rows
        repeat(3 - items.size) {
            Spacer(modifier = Modifier.weight(1f))
        }
    }
}

@Composable
private fun BlockedContentOverlay(onReveal: () -> Unit) {
    Box(
        contentAlignment = Alignment.Center,
        modifier = Modifier
            .fillMaxWidth()
            .height(200.dp)
            .padding(16.dp)
            .background(
                MaterialTheme.colorScheme.errorContainer,
                RoundedCornerShape(12.dp)
            )
            .clickable(onClick = onReveal)
    ) {
        Column(horizontalAlignment = Alignment.CenterHorizontally) {
            Icon(
                Icons.Default.Block,
                contentDescription = null,
                tint = MaterialTheme.colorScheme.onErrorContainer,
                modifier = Modifier.size(32.dp)
            )
            Spacer(Modifier.height(8.dp))
            Text(
                text = "This user is blocked",
                style = MaterialTheme.typography.bodyLarge,
                color = MaterialTheme.colorScheme.onErrorContainer
            )
            Spacer(Modifier.height(4.dp))
            Text(
                text = "Tap to reveal content",
                style = MaterialTheme.typography.bodySmall,
                color = MaterialTheme.colorScheme.onErrorContainer.copy(alpha = 0.7f)
            )
        }
    }
}

@Composable
private fun ProfileArticleCard(
    event: NostrEvent,
    profile: ProfileData?,
    eventRepo: EventRepository?,
    onArticleClick: ((Int, String, String) -> Unit)?,
    onProfileClick: ((String) -> Unit)?
) {
    val title = remember(event) { event.tags.firstOrNull { it.size >= 2 && it[0] == "title" }?.get(1) }
    val summary = remember(event) { event.tags.firstOrNull { it.size >= 2 && it[0] == "summary" }?.get(1) }
    val image = remember(event) { event.tags.firstOrNull { it.size >= 2 && it[0] == "image" }?.get(1) }
    val dTag = remember(event) { event.tags.firstOrNull { it.size >= 2 && it[0] == "d" }?.get(1) ?: "" }
    val publishedAt = remember(event) {
        event.tags.firstOrNull { it.size >= 2 && it[0] == "published_at" }?.get(1)?.toLongOrNull()
    }

    androidx.compose.material3.Surface(
        shape = RoundedCornerShape(12.dp),
        color = MaterialTheme.colorScheme.surface,
        modifier = Modifier
            .fillMaxWidth()
            .padding(horizontal = 12.dp, vertical = 6.dp)
            .then(
                if (onArticleClick != null) Modifier.clickable { onArticleClick(30023, event.pubkey, dTag) }
                else Modifier
            )
    ) {
        Column {
            if (image != null) {
                coil3.compose.AsyncImage(
                    model = image,
                    contentDescription = title,
                    contentScale = androidx.compose.ui.layout.ContentScale.Crop,
                    modifier = Modifier
                        .fillMaxWidth()
                        .height(180.dp)
                )
            }
            Column(modifier = Modifier.padding(horizontal = 14.dp, vertical = 10.dp)) {
                Row(verticalAlignment = Alignment.CenterVertically) {
                    androidx.compose.material3.Surface(
                        shape = RoundedCornerShape(4.dp),
                        color = MaterialTheme.colorScheme.primaryContainer,
                        modifier = Modifier.padding(end = 8.dp)
                    ) {
                        Text(
                            text = "ARTICLE",
                            style = MaterialTheme.typography.labelSmall,
                            color = MaterialTheme.colorScheme.onPrimaryContainer,
                            modifier = Modifier.padding(horizontal = 6.dp, vertical = 2.dp)
                        )
                    }
                    Text(
                        text = title ?: "Untitled Article",
                        style = MaterialTheme.typography.titleSmall,
                        color = MaterialTheme.colorScheme.onSurface,
                        maxLines = 2,
                        overflow = androidx.compose.ui.text.style.TextOverflow.Ellipsis,
                        modifier = Modifier.weight(1f)
                    )
                }
                if (!summary.isNullOrBlank()) {
                    Text(
                        text = summary,
                        style = MaterialTheme.typography.bodySmall,
                        color = MaterialTheme.colorScheme.onSurfaceVariant,
                        maxLines = 3,
                        overflow = androidx.compose.ui.text.style.TextOverflow.Ellipsis,
                        modifier = Modifier.padding(top = 4.dp)
                    )
                }
                if (publishedAt != null) {
                    Text(
                        text = java.text.SimpleDateFormat("MMM d, yyyy", java.util.Locale.US)
                            .format(java.util.Date(publishedAt * 1000)),
                        style = MaterialTheme.typography.labelSmall,
                        color = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.7f),
                        modifier = Modifier.padding(top = 6.dp)
                    )
                }
            }
        }
    }
}
