import UIKit
import Combine

/// ViewModel for OpponentProfileView — loads shared media and tracks online status.
/// Uses ObservableObject + @Published (project rule: NOT @Observable).
final class PeerProfileViewModel: ObservableObject {
    let dialogKey: String

    @Published var mediaItems: [SharedMediaItem] = []
    @Published var fileItems: [SharedFileItem] = []
    @Published var linkItems: [SharedLinkItem] = []
    @Published var commonGroups: [CommonGroupItem] = []
    @Published var isOnline = false

    private var dialogCancellable: AnyCancellable?

    init(dialogKey: String) {
        self.dialogKey = dialogKey
        let dialog = DialogRepository.shared.dialogs[dialogKey]
        isOnline = dialog?.isOnline ?? false
    }

    // MARK: - Online Status

    var onlineStatusText: String {
        isOnline ? "online" : "offline"
    }

    func startObservingOnline() {
        // Poll dialog changes (DialogRepository is @Observable, so we check periodically)
        dialogCancellable = Timer.publish(every: 2, on: .main, in: .common)
            .autoconnect()
            .sink { [weak self] _ in
                guard let self else { return }
                let online = DialogRepository.shared.dialogs[self.dialogKey]?.isOnline ?? false
                if self.isOnline != online {
                    self.isOnline = online
                }
            }
    }

    // MARK: - Shared Content (reuses GroupInfoViewModel pattern)

    func loadSharedContent() {
        let messages = MessageRepository.shared.messages(for: dialogKey)
        var media: [SharedMediaItem] = []
        var files: [SharedFileItem] = []
        var links: [SharedLinkItem] = []

        let urlDetector = try? NSDataDetector(types: NSTextCheckingResult.CheckingType.link.rawValue)

        for message in messages {
            let senderName = resolveSenderName(for: message.fromPublicKey)

            for attachment in message.attachments {
                switch attachment.type {
                case .image:
                    media.append(SharedMediaItem(
                        attachmentId: attachment.id,
                        messageId: message.id,
                        senderName: senderName,
                        timestamp: message.timestamp,
                        caption: message.text,
                        blurhash: AttachmentPreviewCodec.blurHash(from: attachment.preview)
                    ))
                case .file:
                    let parsed = AttachmentPreviewCodec.parseFilePreview(attachment.preview)
                    files.append(SharedFileItem(
                        attachmentId: attachment.id,
                        messageId: message.id,
                        fileName: parsed.fileName,
                        fileSize: parsed.fileSize,
                        preview: attachment.preview,
                        timestamp: message.timestamp,
                        senderName: senderName
                    ))
                default:
                    break
                }
            }

            let displayText = message.text
            if !displayText.isEmpty, let detector = urlDetector {
                let range = NSRange(displayText.startIndex..., in: displayText)
                for match in detector.matches(in: displayText, range: range) {
                    if let urlRange = Range(match.range, in: displayText) {
                        links.append(SharedLinkItem(
                            url: String(displayText[urlRange]),
                            messageId: message.id,
                            context: String(displayText.prefix(200)),
                            timestamp: message.timestamp,
                            senderName: senderName
                        ))
                    }
                }
            }
        }

        mediaItems = Array(media.suffix(30).reversed())
        fileItems = Array(files.suffix(30).reversed())
        linkItems = Array(links.suffix(30).reversed())
    }

    // MARK: - Common Groups

    func loadCommonGroups() {
        let allDialogs = DialogRepository.shared.dialogs
        let account = SessionManager.shared.currentPublicKey
        var groups: [CommonGroupItem] = []

        for (key, dialog) in allDialogs {
            guard DatabaseManager.isGroupDialogKey(key) else { continue }

            // Check cached member list for this group
            if let cached = GroupRepository.shared.cachedMembers(account: account, groupDialogKey: key) {
                if cached.memberKeys.contains(dialogKey) {
                    let avatar = AvatarRepository.shared.loadAvatar(publicKey: key)
                    groups.append(CommonGroupItem(
                        dialogKey: key,
                        title: dialog.opponentTitle.isEmpty ? String(key.prefix(12)) : dialog.opponentTitle,
                        avatar: avatar
                    ))
                }
            }
        }

        commonGroups = groups
    }

    // MARK: - Helpers

    private func resolveSenderName(for publicKey: String) -> String {
        if publicKey == SessionManager.shared.currentPublicKey {
            return SessionManager.shared.displayName.isEmpty ? "You" : SessionManager.shared.displayName
        }
        let dialog = DialogRepository.shared.dialogs[publicKey]
        return dialog?.opponentTitle ?? String(publicKey.prefix(12))
    }
}

// MARK: - Common Group Item

struct CommonGroupItem: Identifiable {
    let dialogKey: String
    let title: String
    let avatar: UIImage?
    var id: String { dialogKey }
}
