// Copyright © 2023 Rangeproof Pty Ltd. All rights reserved.

import SwiftUI
import SessionUIKit
import SessionSnodeKit

struct MessageInfoView: View {
    @State var index = 1
    @State var showingAttachmentFullScreen = false
    var actions: [ContextMenuVC.Action]
    var messageViewModel: MessageViewModel
    var isMessageFailed: Bool {
        return [.failed, .failedToSync].contains(messageViewModel.state)
    }
    
    var body: some View {
        NavigationView {
            ZStack (alignment: .topLeading) {
                if #available(iOS 14.0, *) {
                    ThemeManager.currentTheme.colorSwiftUI(for: .backgroundPrimary).ignoresSafeArea()
                } else {
                    ThemeManager.currentTheme.colorSwiftUI(for: .backgroundPrimary)
                }
                
                ScrollView(.vertical, showsIndicators: false) {
                    VStack(
                        alignment: .leading,
                        spacing: 10
                    ) {
                        // Message bubble snapshot
                        if let body: String = messageViewModel.body, !body.isEmpty {
                            let (bubbleBackgroundColor, bubbleTextColor): (ThemeValue, ThemeValue) = (
                                messageViewModel.variant == .standardIncoming ||
                                messageViewModel.variant == .standardIncomingDeleted
                            ) ?
                            (.messageBubble_incomingBackground, .messageBubble_incomingText) :
                            (.messageBubble_outgoingBackground, .messageBubble_outgoingText)
                            
                            ZStack {
                                RoundedRectangle(cornerRadius: 18)
                                    .fill(themeColor: bubbleBackgroundColor)
                                
                                Text(body)
                                    .foregroundColor(themeColor: bubbleTextColor)
                                    .padding(
                                        EdgeInsets(
                                            top: 8,
                                            leading: 16,
                                            bottom: 8,
                                            trailing: 16
                                        )
                                    )
                            }
                            .frame(
                                maxWidth: .infinity,
                                maxHeight: .infinity,
                                alignment: .topLeading
                            )
                            .fixedSize(horizontal: true, vertical: true)
                            .padding(
                                EdgeInsets(
                                    top: 8,
                                    leading: 30,
                                    bottom: 4,
                                    trailing: 30
                                )
                            )
                        }
                        
                        if isMessageFailed {
                            let (image, statusText, tintColor) = messageViewModel.state.statusIconInfo(
                                variant: messageViewModel.variant,
                                hasAtLeastOneReadReceipt: messageViewModel.hasAtLeastOneReadReceipt
                            )
                            
                            HStack(spacing: 6) {
                                if let image: UIImage = image?.withRenderingMode(.alwaysTemplate) {
                                    Image(uiImage: image)
                                        .resizable()
                                        .scaledToFit()
                                        .foregroundColor(themeColor: tintColor)
                                        .frame(width: 13, height: 12)
                                }
                                
                                if let statusText: String = statusText {
                                    Text(statusText)
                                        .font(.system(size: 11))
                                        .foregroundColor(themeColor: tintColor)
                                }
                            }
                            .padding(
                                EdgeInsets(
                                    top: -8,
                                    leading: 30,
                                    bottom: 4,
                                    trailing: 30
                                )
                            )
                        }
                        
                        if let attachments = messageViewModel.attachments {
                            let attachment: Attachment = attachments[(index - 1 + attachments.count) % attachments.count]
                            
                            ZStack(alignment: .bottomTrailing) {
                                if attachments.count > 1 {
                                    // Attachment carousel view
                                    SessionCarouselView_SwiftUI(
                                        index: $index,
                                        isOutgoing: (messageViewModel.variant == .standardOutgoing),
                                        contentInfos: attachments
                                    )
                                    .frame(
                                        maxWidth: .infinity,
                                        maxHeight: .infinity,
                                        alignment: .topLeading
                                    )
                                } else {
                                    MediaView_SwiftUI(
                                        attachment: attachments[0],
                                        isOutgoing: (messageViewModel.variant == .standardOutgoing),
                                        cornerRadius: 0
                                    )
                                    .frame(
                                        maxWidth: .infinity,
                                        maxHeight: .infinity,
                                        alignment: .topLeading
                                    )
                                    .aspectRatio(1, contentMode: .fit)
                                    .clipShape(RoundedRectangle(cornerRadius: 15))
                                    .padding(
                                        EdgeInsets(
                                            top: 0,
                                            leading: 30,
                                            bottom: 0,
                                            trailing: 30
                                        )
                                    )
                                }
                                
                                Button {
                                    self.showingAttachmentFullScreen.toggle()
                                } label: {
                                    ZStack {
                                        Circle()
                                            .foregroundColor(.init(white: 0, opacity: 0.4))
                                        Image(systemName: "arrow.up.left.and.arrow.down.right")
                                            .font(.system(size: 13))
                                            .foregroundColor(.white)
                                    }
                                    .frame(width: 26, height: 26)
                                }
                                .sheet(isPresented: $showingAttachmentFullScreen) {
                                    MediaGalleryViewModel.createDetailViewSwiftUI(
                                        for: messageViewModel.threadId,
                                        threadVariant: messageViewModel.threadVariant,
                                        interactionId: messageViewModel.id,
                                        selectedAttachmentId: attachment.id,
                                        options: [ .sliderEnabled ]
                                    )
                                }
                                .padding(
                                    EdgeInsets(
                                        top: 0,
                                        leading: 0,
                                        bottom: 8,
                                        trailing: 38
                                    )
                                )
                            }
                            .padding(
                                EdgeInsets(
                                    top: 4,
                                    leading: 0,
                                    bottom: 4,
                                    trailing: 0
                                )
                            )
                            
                            // Attachment Info
                            ZStack {
                                RoundedRectangle(cornerRadius: 17)
                                    .fill(themeColor: .backgroundSecondary)
                                    
                                VStack(
                                    alignment: .leading,
                                    spacing: 16
                                ) {
                                    InfoBlock(title: "ATTACHMENT_INFO_FILE_ID".localized() + ":") {
                                        Text(attachment.serverId ?? "")
                                            .font(.system(size: 16))
                                            .foregroundColor(themeColor: .textPrimary)
                                    }
                                    
                                    HStack(
                                        alignment: .center
                                    ) {
                                        InfoBlock(title: "ATTACHMENT_INFO_FILE_TYPE".localized() + ":") {
                                            Text(attachment.contentType)
                                                .font(.system(size: 16))
                                                .foregroundColor(themeColor: .textPrimary)
                                        }
                                        
                                        Spacer()
                                        
                                        InfoBlock(title: "ATTACHMENT_INFO_FILE_SIZE".localized() + ":") {
                                            Text(Format.fileSize(attachment.byteCount))
                                                .font(.system(size: 16))
                                                .foregroundColor(themeColor: .textPrimary)
                                        }
                                        
                                        Spacer()
                                    }
                                    HStack(
                                        alignment: .center
                                    ) {
                                        let resolution: String = {
                                            guard let width = attachment.width, let height = attachment.height else { return "N/A" }
                                            return "\(width)×\(height)"
                                        }()
                                        InfoBlock(title: "ATTACHMENT_INFO_RESOLUTION".localized() + ":") {
                                            Text(resolution)
                                                .font(.system(size: 16))
                                                .foregroundColor(themeColor: .textPrimary)
                                        }
                                        
                                        Spacer()
                                        
                                        let duration: String = {
                                            guard let duration = attachment.duration else { return "N/A" }
                                            return floor(duration).formatted(format: .videoDuration)
                                        }()
                                        InfoBlock(title: "ATTACHMENT_INFO_DURATION".localized() + ":") {
                                            Text(duration)
                                                .font(.system(size: 16))
                                                .foregroundColor(themeColor: .textPrimary)
                                        }
                                        
                                        Spacer()
                                    }
                                }
                                .frame(
                                    maxWidth: .infinity,
                                    maxHeight: .infinity,
                                    alignment: .topLeading
                                )
                                .padding(
                                    EdgeInsets(
                                        top: 24,
                                        leading: 24,
                                        bottom: 24,
                                        trailing: 24
                                    )
                                )
                            }
                            .frame(maxHeight: .infinity)
                            .fixedSize(horizontal: false, vertical: true)
                            .padding(
                                EdgeInsets(
                                    top: 4,
                                    leading: 30,
                                    bottom: 4,
                                    trailing: 30
                                )
                            )
                        }

                        // Message Info
                        ZStack {
                            RoundedRectangle(cornerRadius: 17)
                                .fill(themeColor: .backgroundSecondary)
                                
                            VStack(
                                alignment: .leading,
                                spacing: 16
                            ) {
                                InfoBlock(title: "MESSAGE_INFO_SENT".localized() + ":") {
                                    Text(messageViewModel.dateForUI.fromattedForMessageInfo)
                                        .font(.system(size: 16))
                                        .foregroundColor(themeColor: .textPrimary)
                                }
                                
                                InfoBlock(title: "MESSAGE_INFO_RECEIVED".localized() + ":") {
                                    Text(messageViewModel.receivedDateForUI.fromattedForMessageInfo)
                                        .font(.system(size: 16))
                                        .foregroundColor(themeColor: .textPrimary)
                                }
                                
                                if isMessageFailed {
                                    let failureText: String = messageViewModel.mostRecentFailureText ?? "Message failed to send"
                                    InfoBlock(title: "ALERT_ERROR_TITLE".localized() + ":") {
                                        Text(failureText)
                                            .font(.system(size: 16))
                                            .foregroundColor(themeColor: .danger)
                                    }
                                }
                                
                                InfoBlock(title: "MESSAGE_INFO_FROM".localized() + ":") {
                                    HStack(
                                        spacing: 10
                                    ) {
                                        Circle()
                                            .frame(
                                                width: 46,
                                                height: 46,
                                                alignment: .topLeading
                                            )
                                            .foregroundColor(themeColor: .primary)
        //                                ProfilePictureSwiftUI(size: .message)
                                            
                                            
                                        VStack(
                                            alignment: .leading,
                                            spacing: 4
                                        ) {
                                            if !messageViewModel.authorName.isEmpty  {
                                                Text(messageViewModel.authorName)
                                                    .bold()
                                                    .font(.system(size: 18))
                                                    .foregroundColor(themeColor: .textPrimary)
                                            }
                                            Text(messageViewModel.authorId)
                                                .font(.spaceMono(size: 16))
                                                .foregroundColor(themeColor: .textPrimary)
                                        }
                                    }
                                }
                            }
                            .frame(
                                maxWidth: .infinity,
                                maxHeight: .infinity,
                                alignment: .topLeading
                            )
                            .padding(
                                EdgeInsets(
                                    top: 24,
                                    leading: 24,
                                    bottom: 24,
                                    trailing: 24
                                )
                            )
                        }
                        .frame(maxHeight: .infinity)
                        .fixedSize(horizontal: false, vertical: true)
                        .padding(
                            EdgeInsets(
                                top: 4,
                                leading: 30,
                                bottom: 4,
                                trailing: 30
                            )
                        )

                        // Actions
                        if !actions.isEmpty {
                            ZStack {
                                RoundedRectangle(cornerRadius: 17)
                                    .fill(themeColor: .backgroundSecondary)
                                
                                VStack(
                                    alignment: .leading,
                                    spacing: 0
                                ) {
                                    ForEach(
                                        0...(actions.count - 1),
                                        id: \.self
                                    ) { index in
                                        let tintColor: ThemeValue = actions[index].isDestructive ? .danger : .textPrimary
                                        HStack(spacing: 24) {
                                            Image(uiImage: actions[index].icon!.withRenderingMode(.alwaysTemplate))
                                                .resizable()
                                                .scaledToFit()
                                                .foregroundColor(themeColor: tintColor)
                                                .frame(width: 26, height: 26)
                                            Text(actions[index].title)
                                                .bold()
                                                .font(.system(size: 18))
                                                .foregroundColor(themeColor: tintColor)
                                        }
                                        .frame(width: .infinity, height: 60)
                                        .onTapGesture {
                                            actions[index].work()
                                        }
                                        
                                        if index < (actions.count - 1) {
                                            Divider()
                                                .foregroundColor(themeColor: .borderSeparator)
                                        }
                                    }
                                }
                                .frame(
                                    maxWidth: .infinity,
                                    maxHeight: .infinity,
                                    alignment: .topLeading
                                )
                                .padding(
                                    EdgeInsets(
                                        top: 0,
                                        leading: 24,
                                        bottom: 0,
                                        trailing: 24
                                    )
                                )
                            }
                            .frame(maxHeight: .infinity)
                            .fixedSize(horizontal: false, vertical: true)
                            .padding(
                                EdgeInsets(
                                    top: 4,
                                    leading: 30,
                                    bottom: 4,
                                    trailing: 30
                                )
                            )
                        }
                    }
                }
            }
        }
    }
}

struct InfoBlock<Content>: View where Content: View {
    let title: String
    let content: () -> Content
    
    var body: some View {
        VStack(
            alignment: .leading,
            spacing: 4
        ) {
            Text(self.title)
                .bold()
                .font(.system(size: 18))
                .foregroundColor(themeColor: .textPrimary)
            self.content()
        }
        .frame(
            minWidth: 100,
            alignment: .leading
        )
    }
}

struct MessageInfoView_Previews: PreviewProvider {
    static var messageViewModel: MessageViewModel {
        let result = MessageViewModel(
            optimisticMessageId: UUID(),
            threadId: "d4f1g54sdf5g1d5f4g65ds4564df65f4g65d54gdfsg",
            threadVariant: .contact,
            threadHasDisappearingMessagesEnabled: false,
            threadOpenGroupServer: nil,
            threadOpenGroupPublicKey: nil,
            threadContactNameInternal: "Test",
            timestampMs: SnodeAPI.currentOffsetTimestampMs(),
            receivedAtTimestampMs: SnodeAPI.currentOffsetTimestampMs(),
            authorId: "d4f1g54sdf5g1d5f4g65ds4564df65f4g65d54gdfsg",
            authorNameInternal: "Test",
            body: "Test Message",
            expiresStartedAtMs: nil,
            expiresInSeconds: nil,
            state: .failed,
            isSenderOpenGroupModerator: false,
            currentUserProfile: Profile.fetchOrCreateCurrentUser(),
            quote: nil,
            quoteAttachment: nil,
            linkPreview: nil,
            linkPreviewAttachment: nil,
            attachments: nil
        )
        
        return result
    }
    
    static var actions: [ContextMenuVC.Action] {
        return [
            .reply(messageViewModel, nil),
            .retry(messageViewModel, nil),
            .delete(messageViewModel, nil)
        ]
    }
    
    static var previews: some View {
        MessageInfoView(
            actions: actions,
            messageViewModel: messageViewModel
        )
    }
}