import SwiftUI

/// Telegram-parity peer profile screen with expandable header, shared media tabs.
struct OpponentProfileView: View {
    let route: ChatRoute

    @StateObject private var viewModel: PeerProfileViewModel
    @Environment(\.dismiss) private var dismiss
    @Environment(\.colorScheme) private var colorScheme
    @State private var copiedField: String?
    @State private var isLargeHeader = false
    @State private var topInset: CGFloat = 0
    @State private var isMuted = false
    @State private var showMoreSheet = false
    /// When true, shows "Message" button in action bar (group member profile context).
    var showMessageButton = false
    /// Navigation controller for pushing chat from profile.
    @State private var navController: UINavigationController?
    @State private var selectedTab: PeerProfileTab = .media
    @Namespace private var tabNamespace

    enum PeerProfileTab: String, CaseIterable {
        case media = "Media"
        case files = "Files"
        case links = "Links"
        case groups = "Groups"
    }

    init(route: ChatRoute) {
        self.route = route
        _viewModel = StateObject(wrappedValue: PeerProfileViewModel(dialogKey: route.publicKey))
        // Start expanded only if user has a real photo (not letter avatar)
        let hasPhoto = AvatarRepository.shared.loadAvatar(publicKey: route.publicKey) != nil
        _isLargeHeader = State(initialValue: hasPhoto)
    }

    // MARK: - Computed properties

    private var dialog: Dialog? {
        DialogRepository.shared.dialogs[route.publicKey]
    }

    private var displayName: String {
        if let dialog, !dialog.opponentTitle.isEmpty { return dialog.opponentTitle }
        if !route.title.isEmpty { return route.title }
        if let dialog, !dialog.opponentUsername.isEmpty { return "@\(dialog.opponentUsername)" }
        if !route.username.isEmpty { return "@\(route.username)" }
        return String(route.publicKey.prefix(12))
    }

    private var username: String {
        if let dialog, !dialog.opponentUsername.isEmpty { return dialog.opponentUsername }
        return route.username
    }

    private var effectiveVerified: Int {
        if let dialog { return dialog.effectiveVerified }
        if route.verified > 0 { return route.verified }
        return 0
    }

    private var opponentAvatar: UIImage? {
        AvatarRepository.shared.loadAvatar(publicKey: route.publicKey)
    }

    /// Only real photos can expand to full-width; letter avatars stay as circles.
    private var canExpand: Bool { opponentAvatar != nil }

    /// Telegram parity: show online status, not username/key
    private var subtitleText: String {
        viewModel.isOnline ? "online" : "offline"
    }

    // MARK: - Body

    var body: some View {
        scrollContent
            .scrollIndicators(.hidden)
            .modifier(ProfileScrollTracker(isLargeHeader: $isLargeHeader, topInset: $topInset, canExpand: canExpand))
            .background(RosettaColors.Adaptive.background.ignoresSafeArea())
            .navigationBarTitleDisplayMode(.inline)
            .navigationBarBackButtonHidden(true)
            .enableSwipeBack()
            .toolbar {
                ToolbarItem(placement: .navigationBarLeading) {
                    Button { dismiss() } label: { backButtonLabel }
                        .buttonStyle(.plain)
                        .padding(.leading, -8) // align with ChatDetail back button (8pt from edge)
                }
            }
            .toolbarBackground(.hidden, for: .navigationBar)
            .task {
                isMuted = dialog?.isMuted ?? false
                // Only expand when user has a REAL photo (not letter avatar)
                if opponentAvatar != nil {
                    isLargeHeader = true
                }
                viewModel.startObservingOnline()
                viewModel.loadSharedContent()
                viewModel.loadCommonGroups()
            }
            .background {
                NavigationControllerAccessor { nav in
                    self.navController = nav
                }
            }
            .confirmationDialog("", isPresented: $showMoreSheet, titleVisibility: .hidden) {
                if !route.isSavedMessages {
                    Button("Block User", role: .destructive) {}
                }
                Button("Clear Chat History", role: .destructive) {}
            }
    }

    private var scrollContent: some View {
        ScrollView(.vertical) {
            LazyVStack(spacing: 0) {
                infoSections
                    .padding(.top, 16)
                    .padding(.horizontal, 16)

                sharedMediaTabBar
                    .padding(.top, 20)

                sharedMediaContent
                    .padding(.top, 12)

                Spacer(minLength: 40)
            }
            .safeAreaInset(edge: .top, spacing: 0) {
                PeerProfileHeaderView(
                    isLargeHeader: $isLargeHeader,
                    topInset: $topInset,
                    displayName: displayName,
                    subtitleText: subtitleText,
                    effectiveVerified: effectiveVerified,
                    avatarImage: opponentAvatar,
                    avatarInitials: RosettaColors.initials(name: displayName, publicKey: route.publicKey),
                    avatarColorIndex: RosettaColors.avatarColorIndex(for: displayName, publicKey: route.publicKey),
                    isMuted: isMuted,
                    isSavedMessages: route.isSavedMessages,
                    showCallButton: !route.isSavedMessages,
                    showMuteButton: !route.isSavedMessages,
                    showMessageButton: route.isSavedMessages || showMessageButton,
                    onCall: handleCall,
                    onMuteToggle: handleMuteToggle,
                    onSearch: { dismiss() },
                    onMore: { showMoreSheet = true },
                    onMessage: handleMessage
                )
            }
        }
    }

    // MARK: - Back Button (always white chevron — glass capsule provides dark tint for contrast)

    private var backButtonLabel: some View {
        TelegramVectorIcon(
            pathData: TelegramIconPath.backChevron,
            viewBox: CGSize(width: 11, height: 20),
            color: isLargeHeader ? .white : RosettaColors.Adaptive.text
        )
        .frame(width: 11, height: 20)
        .frame(width: 36, height: 36)
        .frame(height: 44)
        .padding(.horizontal, 4)
        .contentShape(Rectangle())
        .background {
            if isLargeHeader {
                TelegramGlassCapsule()
            } else {
                Capsule()
                    .fill(RosettaColors.adaptive(
                        light: Color.black.opacity(0.06),
                        dark: Color.white.opacity(0.12)))
                    .overlay(
                        Capsule()
                            .strokeBorder(RosettaColors.adaptive(
                                light: Color.black.opacity(0.08),
                                dark: Color.white.opacity(0.08)), lineWidth: 0.5)
                    )
            }
        }
    }

    // MARK: - Info Sections

    private var infoSections: some View {
        TelegramSectionCard {
            VStack(spacing: 0) {
                if !username.isEmpty {
                    infoRow(label: "username", value: "@\(username)", rawValue: username, fieldId: "username")
                    telegramDivider
                }
                infoRow(label: "public key", value: route.publicKey, rawValue: route.publicKey, fieldId: "publicKey")
            }
        }
    }

    private var telegramDivider: some View {
        Rectangle()
            .fill(telegramSeparatorColor)
            .frame(height: 1 / UIScreen.main.scale)
            .padding(.leading, 16)
    }

    private func infoRow(label: String, value: String, rawValue: String, fieldId: String) -> some View {
        Button {
            UIPasteboard.general.string = rawValue
            withAnimation(.easeInOut(duration: 0.2)) { copiedField = fieldId }
            Task { @MainActor in
                try? await Task.sleep(for: .seconds(1.5))
                withAnimation(.easeInOut(duration: 0.2)) {
                    if copiedField == fieldId { copiedField = nil }
                }
            }
        } label: {
            VStack(alignment: .leading, spacing: 2) {
                Text(label)
                    .font(.system(size: 14))
                    .foregroundStyle(RosettaColors.Adaptive.textSecondary)
                Text(copiedField == fieldId ? "Copied" : value)
                    .font(.system(size: 17))
                    .foregroundStyle(copiedField == fieldId ? RosettaColors.online : RosettaColors.primaryBlue)
                    .lineLimit(1)
                    .truncationMode(.middle)
            }
            .frame(maxWidth: .infinity, alignment: .leading)
            .padding(.horizontal, 16)
            .padding(.vertical, 12)
        }
        .buttonStyle(.plain)
    }

    // MARK: - Shared Media Tab Bar (Telegram parity)

    private var tabActiveColor: Color { RosettaColors.Adaptive.text }
    private var tabInactiveColor: Color {
        RosettaColors.adaptive(light: Color.black.opacity(0.4), dark: Color(red: 0x98/255, green: 0x98/255, blue: 0x9E/255))
    }
    private var tabIndicatorFill: Color {
        RosettaColors.adaptive(light: Color.black.opacity(0.08), dark: Color.white.opacity(0.18))
    }

    private var sharedMediaTabBar: some View {
        HStack(spacing: 0) {
            ForEach(PeerProfileTab.allCases, id: \.self) { tab in
                Button {
                    withAnimation(.spring(response: 0.35, dampingFraction: 0.8)) {
                        selectedTab = tab
                    }
                } label: {
                    Text(tab.rawValue)
                        .font(.system(size: 14, weight: .medium))
                        .foregroundStyle(selectedTab == tab ? tabActiveColor : tabInactiveColor)
                        .padding(.horizontal, 12)
                        .padding(.vertical, 8)
                        .background {
                            if selectedTab == tab {
                                Capsule()
                                    .fill(tabIndicatorFill)
                                    .matchedGeometryEffect(id: "peer_tab", in: tabNamespace)
                            }
                        }
                }
                .buttonStyle(.plain)
            }
        }
        .padding(.horizontal, 3)
        .padding(.vertical, 3)
        .background {
            TelegramGlassCapsule()
        }
        .padding(.horizontal, 16)
    }

    // MARK: - Shared Media Content

    @ViewBuilder
    private var sharedMediaContent: some View {
        switch selectedTab {
        case .media:
            if viewModel.mediaItems.isEmpty {
                emptyState(icon: "photo.on.rectangle", title: "No Media Yet")
            } else {
                peerMediaGrid
            }
        case .files:
            if viewModel.fileItems.isEmpty {
                emptyState(icon: "doc", title: "No Files Yet")
            } else {
                peerFilesList
            }
        case .links:
            if viewModel.linkItems.isEmpty {
                emptyState(icon: "link", title: "No Links Yet")
            } else {
                peerLinksList
            }
        case .groups:
            if viewModel.commonGroups.isEmpty {
                emptyState(icon: "person.2", title: "No Groups in Common")
            } else {
                commonGroupsList
            }
        }
    }

    private func emptyState(icon: String, title: String) -> some View {
        VStack(spacing: 12) {
            Image(systemName: icon)
                .font(.system(size: 40))
                .foregroundStyle(RosettaColors.Adaptive.textSecondary.opacity(0.5))
            Text(title)
                .font(.system(size: 15, weight: .medium))
                .foregroundStyle(RosettaColors.Adaptive.textSecondary)
        }
        .frame(maxWidth: .infinity)
        .padding(.vertical, 40)
    }

    private var peerMediaGrid: some View {
        let columns = Array(repeating: GridItem(.flexible(), spacing: 1), count: 3)
        return LazyVGrid(columns: columns, spacing: 1) {
            ForEach(viewModel.mediaItems) { item in
                PeerMediaTile(item: item, allItems: viewModel.mediaItems)
            }
        }
    }

    private var peerFilesList: some View {
        TelegramSectionCard {
            VStack(spacing: 0) {
                ForEach(Array(viewModel.fileItems.enumerated()), id: \.element.id) { index, file in
                    HStack(spacing: 12) {
                        Image(systemName: "doc.fill")
                            .font(.system(size: 22))
                            .foregroundStyle(RosettaColors.primaryBlue)
                            .frame(width: 40, height: 40)
                            .background(RoundedRectangle(cornerRadius: 10).fill(RosettaColors.primaryBlue.opacity(0.12)))
                        VStack(alignment: .leading, spacing: 2) {
                            Text(file.fileName).font(.system(size: 16)).foregroundStyle(RosettaColors.Adaptive.text).lineLimit(1)
                            Text(file.subtitle).font(.system(size: 13)).foregroundStyle(RosettaColors.Adaptive.textSecondary)
                        }
                        Spacer()
                    }
                    .padding(.horizontal, 16).padding(.vertical, 10)

                    if index < viewModel.fileItems.count - 1 {
                        Rectangle().fill(telegramSeparatorColor).frame(height: 1 / UIScreen.main.scale).padding(.leading, 68)
                    }
                }
            }
        }
        .padding(.horizontal, 16)
    }

    private var peerLinksList: some View {
        TelegramSectionCard {
            VStack(spacing: 0) {
                ForEach(Array(viewModel.linkItems.enumerated()), id: \.element.id) { index, link in
                    Button { if let url = URL(string: link.url) { UIApplication.shared.open(url) } } label: {
                        HStack(spacing: 12) {
                            Text(String(link.displayHost.prefix(1)).uppercased())
                                .font(.system(size: 18, weight: .bold)).foregroundStyle(.white)
                                .frame(width: 40, height: 40)
                                .background(RoundedRectangle(cornerRadius: 10).fill(RosettaColors.primaryBlue))
                            VStack(alignment: .leading, spacing: 2) {
                                Text(link.displayHost).font(.system(size: 16, weight: .medium)).foregroundStyle(RosettaColors.Adaptive.text).lineLimit(1)
                                Text(link.context).font(.system(size: 13)).foregroundStyle(RosettaColors.Adaptive.textSecondary).lineLimit(2)
                            }
                            Spacer()
                        }
                        .padding(.horizontal, 16).padding(.vertical, 10)
                    }.buttonStyle(.plain)

                    if index < viewModel.linkItems.count - 1 {
                        Rectangle().fill(telegramSeparatorColor).frame(height: 1 / UIScreen.main.scale).padding(.leading, 68)
                    }
                }
            }
        }
        .padding(.horizontal, 16)
    }

    private var commonGroupsList: some View {
        TelegramSectionCard {
            VStack(spacing: 0) {
                ForEach(Array(viewModel.commonGroups.enumerated()), id: \.element.id) { index, group in
                    HStack(spacing: 12) {
                        let initials = RosettaColors.initials(name: group.title, publicKey: group.dialogKey)
                        let colorIdx = RosettaColors.avatarColorIndex(for: group.title, publicKey: group.dialogKey)
                        AvatarView(initials: initials, colorIndex: colorIdx, size: 40, isOnline: false, image: group.avatar)

                        Text(group.title)
                            .font(.system(size: 17))
                            .foregroundStyle(RosettaColors.Adaptive.text)
                            .lineLimit(1)
                        Spacer()
                    }
                    .padding(.horizontal, 16).padding(.vertical, 8)

                    if index < viewModel.commonGroups.count - 1 {
                        Rectangle().fill(telegramSeparatorColor).frame(height: 1 / UIScreen.main.scale).padding(.leading, 68)
                    }
                }
            }
        }
        .padding(.horizontal, 16)
    }

    // MARK: - Actions

    private func handleCall() {
        let name = displayName
        let user = username
        Task { @MainActor in
            _ = CallManager.shared.startOutgoingCall(toPublicKey: route.publicKey, title: name, username: user)
        }
    }

    private func handleMuteToggle() {
        DialogRepository.shared.toggleMute(opponentKey: route.publicKey)
        isMuted.toggle()
    }

    private func handleMessage() {
        if route.isSavedMessages {
            // Pop back to Saved Messages chat
            dismiss()
        } else {
            // Push chat with this user
            let chatView = ChatDetailView(route: route)
            let vc = UIHostingController(rootView: chatView)
            vc.navigationItem.hidesBackButton = true
            navController?.pushViewController(vc, animated: true)
        }
    }
}

// MARK: - Media Tile

private struct PeerMediaTile: View {
    let item: SharedMediaItem
    let allItems: [SharedMediaItem]
    @State private var image: UIImage?
    @State private var blurImage: UIImage?

    var body: some View {
        GeometryReader { proxy in
            ZStack {
                if let image { Image(uiImage: image).resizable().scaledToFill().frame(width: proxy.size.width, height: proxy.size.width).clipped() }
                else if let blurImage { Image(uiImage: blurImage).resizable().scaledToFill().frame(width: proxy.size.width, height: proxy.size.width).clipped() }
                else { Color(white: 0.15) }
            }
            .contentShape(Rectangle())
            .onTapGesture { openGallery() }
        }
        .aspectRatio(1, contentMode: .fit)
        .task { loadImages() }
    }

    private func loadImages() {
        if let cached = AttachmentCache.shared.loadImage(forAttachmentId: item.attachmentId) { image = cached }
        else if !item.blurhash.isEmpty { blurImage = BlurHashDecoder.decode(blurHash: item.blurhash, width: 32, height: 32) }
    }

    private func openGallery() {
        let viewable = allItems.map { ViewableImageInfo(attachmentId: $0.attachmentId, messageId: $0.messageId, senderName: $0.senderName, timestamp: Date(timeIntervalSince1970: Double($0.timestamp) / 1000.0), caption: $0.caption) }
        let index = allItems.firstIndex(where: { $0.attachmentId == item.attachmentId }) ?? 0
        ImageViewerPresenter.shared.present(state: ImageViewerState(images: viewable, initialIndex: index, sourceFrame: .zero))
    }
}

// MARK: - Scroll Tracking

private struct ProfileScrollTracker: ViewModifier {
    @Binding var isLargeHeader: Bool
    @Binding var topInset: CGFloat
    let canExpand: Bool

    func body(content: Content) -> some View {
        if #available(iOS 18, *) {
            IOS18ScrollTracker(isLargeHeader: $isLargeHeader, topInset: $topInset, canExpand: canExpand) { content }
        } else { content }
    }
}

@available(iOS 18, *)
private struct IOS18ScrollTracker<Content: View>: View {
    @Binding var isLargeHeader: Bool
    @Binding var topInset: CGFloat
    let canExpand: Bool
    @State private var scrollPhase: ScrollPhase = .idle
    let content: () -> Content

    var body: some View {
        content()
            .onScrollGeometryChange(for: CGFloat.self) { $0.contentInsets.top } action: { _, v in topInset = v }
            .onScrollGeometryChange(for: CGFloat.self) { $0.contentOffset.y + $0.contentInsets.top } action: { _, v in
                if scrollPhase == .interacting {
                    let shouldExpand = canExpand && (v < -10 || (isLargeHeader && v < 0))
                    guard shouldExpand != isLargeHeader else { return }
                    withAnimation(.spring(response: 0.35, dampingFraction: 0.86)) {
                        isLargeHeader = shouldExpand
                    }
                }
            }
            .onScrollPhaseChange { _, p in scrollPhase = p }
            .onChange(of: isLargeHeader) { wasLarge, isLarge in
                if isLarge && !wasLarge {
                    UIImpactFeedbackGenerator(style: .light).impactOccurred()
                }
            }
    }
}
