import SwiftUI
import Bedrock
import SwiftData
import MessageUI

/// Wrapper to make URL identifiable for sheet presentation
private struct IdentifiableURL: Identifiable {
    let id = UUID()
    let url: URL
}

struct ShareCardView: View {
    @Environment(AppState.self) private var appState
    @State private var showingWalletAlert = false
    @State private var showingNfcAlert = false
    
    // Share state
    @State private var vCardFileURL: URL?
    @State private var messageComposeURL: IdentifiableURL?
    @State private var mailComposeURL: IdentifiableURL?
    
    // App Clip share state
    @State private var appClipState = AppClipShareState()

    var body: some View {
        NavigationStack {
            ZStack {
                // Dark background
                Color.ShareSheet.background
                    .ignoresSafeArea()
                
                ScrollView {
                    VStack(spacing: Design.Spacing.xLarge) {
                        if let card = appState.cardStore.selectedCard {
                            // QR Code section (vCard, no photo)
                            QRCodeSection(card: card)
                            
                            // App Clip section (includes photo)
                            AppClipSection(card: card, appClipState: appClipState)
                            
                            // Share options
                            ShareOptionsSection(
                                card: card,
                                preferredAction: appState.appSettings.preferredShareAction,
                                vCardFileURL: $vCardFileURL,
                                messageComposeURL: $messageComposeURL,
                                mailComposeURL: $mailComposeURL
                            )
                        } else {
                            EmptyShareState()
                        }
                    }
                    .padding(.horizontal, Design.Spacing.large)
                    .padding(.vertical, Design.Spacing.xLarge)
                }
            }
            .navigationTitle(String.localized("Send Your Card"))
            .navigationBarTitleDisplayMode(.inline)
            .toolbarColorScheme(.dark, for: .navigationBar)
            .toolbarBackground(Color.ShareSheet.background, for: .navigationBar)
            .toolbarBackground(.visible, for: .navigationBar)
            .alert(String.localized("Apple Wallet"), isPresented: $showingWalletAlert) {
                Button(String.localized("OK")) { }
            } message: {
                Text("Wallet export is coming soon. We'll let you know as soon as it's ready.")
            }
            .alert(String.localized("NFC Sharing"), isPresented: $showingNfcAlert) {
                Button(String.localized("OK")) { }
            } message: {
                Text("Hold your phone near another device to share instantly. NFC setup is on the way.")
            }
            .sheet(item: $messageComposeURL) { url in
                MessageComposeView(vCardURL: url)
                    .ignoresSafeArea()
            }
            .sheet(item: $mailComposeURL) { url in
                MailComposeView(vCardURL: url, cardName: appState.cardStore.selectedCard?.vCardName ?? "Contact")
                    .ignoresSafeArea()
            }
            .onAppear {
                prepareVCardFile()
            }
        }
    }
    
    private func prepareVCardFile() {
        guard let card = appState.cardStore.selectedCard, vCardFileURL == nil else { return }
        let service = VCardFileService()
        vCardFileURL = try? service.createVCardFile(for: card)
    }
}

// MARK: - QR Code Section

private struct QRCodeSection: View {
    let card: BusinessCard
    
    var body: some View {
        VStack(spacing: Design.Spacing.large) {
            // QR Code
            QRCodeView(payload: card.vCardPayload)
                .frame(width: Design.CardSize.qrSizeLarge, height: Design.CardSize.qrSizeLarge)
                .padding(Design.Spacing.large)
                .background(Color.white)
                .clipShape(.rect(cornerRadius: Design.CornerRadius.large))
            
            // Instruction text
            Text("Point your camera at the QR code to receive the card")
                .typography(.subheading)
                .foregroundStyle(Color.ShareSheet.secondaryText)
                .multilineTextAlignment(.center)
        }
        .frame(maxWidth: .infinity)
        .padding(Design.Spacing.xLarge)
        .background(Color.ShareSheet.cardBackground)
        .clipShape(.rect(cornerRadius: Design.CornerRadius.xLarge))
    }
}

// MARK: - App Clip Section

private struct AppClipSection: View {
    let card: BusinessCard
    @Bindable var appClipState: AppClipShareState
    
    var body: some View {
        VStack(spacing: Design.Spacing.large) {
            // Header
            HStack {
                Image(systemName: "app.gift")
                    .typography(.heading)
                    .foregroundStyle(Color.ShareSheet.text)
                Text("App Clip (includes photo)")
                    .typography(.heading)
                    .foregroundStyle(Color.ShareSheet.text)
            }
            
            // Content based on state
            if appClipState.isUploading {
                ProgressView()
                    .tint(Color.ShareSheet.text)
                    .padding(Design.Spacing.xLarge)
                    .accessibilityLabel(Text("Uploading card"))
            } else if let result = appClipState.uploadResult {
                // Show QR code for App Clip URL
                QRCodeView(payload: result.appClipURL.absoluteString)
                    .frame(width: Design.CardSize.qrSizeLarge, height: Design.CardSize.qrSizeLarge)
                    .padding(Design.Spacing.large)
                    .background(Color.white)
                    .clipShape(.rect(cornerRadius: Design.CornerRadius.large))
                
                // Expiration notice
                Text("Expires in 7 days")
                    .typography(.caption)
                    .foregroundStyle(Color.ShareSheet.secondaryText)
                
                // Reset button
                Button {
                    appClipState.reset()
                } label: {
                    Text("Generate New Link")
                        .typography(.subheading)
                        .foregroundStyle(Color.ShareSheet.text)
                }
            } else {
                // Generate button
                Button {
                    Task { await appClipState.shareViaAppClip(card: card) }
                } label: {
                    HStack(spacing: Design.Spacing.small) {
                        Image(systemName: "qrcode")
                        Text("Generate App Clip Link")
                    }
                    .typography(.heading)
                    .foregroundStyle(Color.ShareSheet.background)
                    .padding(.horizontal, Design.Spacing.xLarge)
                    .padding(.vertical, Design.Spacing.medium)
                    .background(Color.ShareSheet.text)
                    .clipShape(.capsule)
                }
                
                // Description
                Text("Creates a link that opens a mini-app for recipients to preview and save your card with photo.")
                    .typography(.caption)
                    .foregroundStyle(Color.ShareSheet.secondaryText)
                    .multilineTextAlignment(.center)
            }
            
            // Error message
            if let error = appClipState.errorMessage {
                Text(error)
                    .typography(.caption)
                    .foregroundStyle(.red)
                    .multilineTextAlignment(.center)
            }
        }
        .frame(maxWidth: .infinity)
        .padding(Design.Spacing.xLarge)
        .background(Color.ShareSheet.cardBackground)
        .clipShape(.rect(cornerRadius: Design.CornerRadius.xLarge))
    }
}

// MARK: - Share Options Section

private struct ShareOptionsSection: View {
    enum ShareOption: String, CaseIterable, Identifiable {
        case shareSheet
        case textMessage
        case email

        var id: String { rawValue }
    }

    let card: BusinessCard
    let preferredAction: PreferredShareAction
    @Binding var vCardFileURL: URL?
    @Binding var messageComposeURL: IdentifiableURL?
    @Binding var mailComposeURL: IdentifiableURL?

    var body: some View {
        VStack(spacing: 0) {
            ForEach(Array(orderedOptions.enumerated()), id: \.element.id) { index, option in
                switch option {
                case .shareSheet:
                    if let url = vCardFileURL {
                        ShareLink(item: url) {
                            RowContent(
                                title: String.localized("Share card"),
                                systemImage: "square.and.arrow.up",
                                iconColor: Color.ShareSheet.secondaryText
                            )
                        }
                        .buttonStyle(.plain)
                    } else {
                        RowContent(
                            title: String.localized("Share card"),
                            systemImage: "square.and.arrow.up",
                            iconColor: Color.ShareSheet.secondaryText.opacity(Design.Opacity.medium)
                        )
                    }
                case .textMessage:
                    Button {
                        if let url = vCardFileURL {
                            messageComposeURL = IdentifiableURL(url: url)
                        }
                    } label: {
                        RowContent(
                            title: String.localized("Text your card"),
                            systemImage: "message.fill",
                            iconColor: Color.ShareSheet.secondaryText
                        )
                    }
                    .buttonStyle(.plain)
                    .disabled(vCardFileURL == nil)
                case .email:
                    Button {
                        if let url = vCardFileURL {
                            mailComposeURL = IdentifiableURL(url: url)
                        }
                    } label: {
                        RowContent(
                            title: String.localized("Email your card"),
                            systemImage: "envelope.fill",
                            iconColor: Color.ShareSheet.secondaryText
                        )
                    }
                    .buttonStyle(.plain)
                    .disabled(vCardFileURL == nil)
                }

                if index < orderedOptions.count - 1 {
                    Divider()
                        .overlay(Color.ShareSheet.rowBackground)
                }
            }
        }
        .background(Color.ShareSheet.cardBackground)
        .clipShape(.rect(cornerRadius: Design.CornerRadius.large))
    }

    private var orderedOptions: [ShareOption] {
        let supportedOptions = availableOptions
        guard let preferred = mapPreferredAction(preferredAction),
              supportedOptions.contains(preferred) else {
            return supportedOptions
        }
        return [preferred] + supportedOptions.filter { $0 != preferred }
    }

    private var availableOptions: [ShareOption] {
        var options: [ShareOption] = [.shareSheet]
        if MFMessageComposeViewController.canSendText() {
            options.append(.textMessage)
        }
        if MFMailComposeViewController.canSendMail() {
            options.append(.email)
        }
        return options
    }

    private func mapPreferredAction(_ action: PreferredShareAction) -> ShareOption? {
        switch action {
        case .shareSheet: .shareSheet
        case .textMessage: .textMessage
        case .email: .email
        }
    }
}

// MARK: - Empty State

private struct EmptyShareState: View {
    var body: some View {
        VStack(spacing: Design.Spacing.large) {
            Image(systemName: "rectangle.on.rectangle.slash")
                .typography(.title2)
                .foregroundStyle(Color.ShareSheet.secondaryText)
            
            Text("No card selected")
                .typography(.heading)
                .foregroundStyle(Color.ShareSheet.text)
            
            Text("Choose a card in the My Cards tab to start sharing.")
                .typography(.subheading)
                .foregroundStyle(Color.ShareSheet.secondaryText)
                .multilineTextAlignment(.center)
        }
        .padding(Design.Spacing.xLarge)
    }
}

// MARK: - Row Content

private struct RowContent: View {
    let title: String
    let systemImage: String
    let iconColor: Color

    var body: some View {
        HStack(spacing: Design.Spacing.medium) {
            Image(systemName: systemImage)
                .typography(.body)
                .foregroundStyle(iconColor)
                .frame(width: Design.Spacing.xLarge)
            
            Text(title)
                .foregroundStyle(Color.ShareSheet.text)
            
            Spacer()
        }
        .padding(.horizontal, Design.Spacing.large)
        .padding(.vertical, Design.Spacing.medium)
        .contentShape(.rect)
    }
}

// MARK: - Message Compose View

private struct MessageComposeView: UIViewControllerRepresentable {
    let vCardURL: IdentifiableURL
    @Environment(\.dismiss) private var dismiss
    
    func makeUIViewController(context: Context) -> MFMessageComposeViewController {
        let controller = MFMessageComposeViewController()
        controller.messageComposeDelegate = context.coordinator
        controller.body = String.localized("ShareMessageBody")
        
        if let data = try? Data(contentsOf: vCardURL.url) {
            controller.addAttachmentData(data, typeIdentifier: "public.vcard", filename: vCardURL.url.lastPathComponent)
        }
        
        return controller
    }
    
    func updateUIViewController(_ uiViewController: MFMessageComposeViewController, context: Context) {}
    
    func makeCoordinator() -> Coordinator {
        Coordinator(dismiss: dismiss)
    }
    
    class Coordinator: NSObject, MFMessageComposeViewControllerDelegate {
        let dismiss: DismissAction
        
        init(dismiss: DismissAction) {
            self.dismiss = dismiss
        }
        
        func messageComposeViewController(_ controller: MFMessageComposeViewController, didFinishWith result: MessageComposeResult) {
            dismiss()
        }
    }
}

// MARK: - Mail Compose View

private struct MailComposeView: UIViewControllerRepresentable {
    let vCardURL: IdentifiableURL
    let cardName: String
    @Environment(\.dismiss) private var dismiss
    
    func makeUIViewController(context: Context) -> MFMailComposeViewController {
        let controller = MFMailComposeViewController()
        controller.mailComposeDelegate = context.coordinator
        controller.setSubject(String.localized("ShareEmailSubjectSimple", cardName))
        controller.setMessageBody(String.localized("ShareEmailBodySimple"), isHTML: false)
        
        if let data = try? Data(contentsOf: vCardURL.url) {
            controller.addAttachmentData(data, mimeType: "text/vcard", fileName: vCardURL.url.lastPathComponent)
        }
        
        return controller
    }
    
    func updateUIViewController(_ uiViewController: MFMailComposeViewController, context: Context) {}
    
    func makeCoordinator() -> Coordinator {
        Coordinator(dismiss: dismiss)
    }
    
    class Coordinator: NSObject, MFMailComposeViewControllerDelegate {
        let dismiss: DismissAction
        
        init(dismiss: DismissAction) {
            self.dismiss = dismiss
        }
        
        func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
            dismiss()
        }
    }
}

// MARK: - Preview

#Preview {
    ShareCardView()
        .environment(AppState(modelContext: try! ModelContainer(for: BusinessCard.self, Contact.self, AppSettings.self).mainContext))
}
