import Foundation
import UIKit
import SwiftUI
import LinkPresentation

class ShareService {
    static let shared = ShareService()

    private init() {}

    static func buildMonthlyCheckInShareText(summary: MonthlySummary, appName: String) -> String {
        """
        \(summary.periodLabel) Check-in
        Starting: \(summary.formattedStartingValue)
        Ending: \(summary.formattedEndingValue)
        Contributions: \(summary.formattedContributions)
        Net performance: \(summary.formattedNetPerformance) (\(summary.formattedNetPerformancePercentage))

        Shared from \(appName)
        """
    }

    static func buildPortfolioValueShareText(
        totalValue: String,
        changeText: String,
        changeLabel: String,
        yearChange: String?,
        sinceInceptionChange: String?,
        appName: String
    ) -> String {
        var lines = [
            "Total Portfolio Value",
            totalValue,
            "\(changeText) \(changeLabel)"
        ]

        if let yearChange {
            lines.append("YoY: \(yearChange)")
        }
        if let sinceInceptionChange {
            lines.append("Since inception: \(sinceInceptionChange)")
        }

        lines.append("")
        lines.append("Shared from \(appName)")
        return lines.joined(separator: "\n")
    }

    @MainActor
    func shareMonthlyCheckIn(summary: MonthlySummary, appName: String) {
        FirebaseService.shared.logShare(type: "monthly_checkin")
        let text = Self.buildMonthlyCheckInShareText(summary: summary, appName: appName)
        shareCard(
            cardTitle: "\(summary.periodLabel) Check-in",
            fallbackText: text
        ) {
            MonthlyCheckInShareCardView(
                summary: summary,
                appName: appName,
                qrCodeImage: GoalShareService.generateQRCode(for: GoalShareService.appStoreURL, size: 200)
            )
        }
    }

    @MainActor
    func sharePortfolioValue(
        totalValue: String,
        changeText: String,
        changeLabel: String,
        yearChange: String?,
        sinceInceptionChange: String?
    ) {
        FirebaseService.shared.logShare(type: "portfolio_value")
        let appName = Self.appDisplayName
        let text = Self.buildPortfolioValueShareText(
            totalValue: totalValue,
            changeText: changeText,
            changeLabel: changeLabel,
            yearChange: yearChange,
            sinceInceptionChange: sinceInceptionChange,
            appName: appName
        )

        shareCard(
            cardTitle: "Portfolio Snapshot",
            fallbackText: text
        ) {
            PortfolioValueShareCardView(
                totalValue: totalValue,
                changeText: changeText,
                changeLabel: changeLabel,
                yearChange: yearChange,
                sinceInceptionChange: sinceInceptionChange,
                appName: appName,
                qrCodeImage: GoalShareService.generateQRCode(for: GoalShareService.appStoreURL, size: 200)
            )
        }
    }

    func shareText(_ content: String) {
        guard let viewController = ShareService.topViewController() else { return }

        let activityVC = UIActivityViewController(
            activityItems: [content],
            applicationActivities: nil
        )

        if let popover = activityVC.popoverPresentationController {
            popover.sourceView = viewController.view
            popover.sourceRect = CGRect(
                x: viewController.view.bounds.midX,
                y: viewController.view.bounds.midY,
                width: 0,
                height: 0
            )
        }

        DispatchQueue.main.async {
            viewController.present(activityVC, animated: true)
        }
    }

    @MainActor
    private func shareCard<Content: View>(
        cardTitle: String,
        fallbackText: String,
        @ViewBuilder card: () -> Content
    ) {
        guard let viewController = ShareService.topViewController() else { return }
        let shareURL = GoalShareService.appStoreURL

        if #available(iOS 16.0, *) {
            let renderer = ImageRenderer(content: card())
            let scale = viewController.view.window?.windowScene?.screen.scale
                ?? viewController.traitCollection.displayScale
            renderer.scale = scale

            if let image = renderer.uiImage {
                let item = CardShareItem(
                    image: image,
                    title: cardTitle,
                    text: fallbackText,
                    url: shareURL
                )
                presentShareSheet(items: [item], from: viewController)
                return
            }
        }

        presentShareSheet(items: [fallbackText], from: viewController)
    }

    func shareTextFile(content: String, fileName: String) {
        guard let viewController = ShareService.topViewController() else { return }

        let tempURL = FileManager.default.temporaryDirectory
            .appendingPathComponent(fileName)

        do {
            try content.write(to: tempURL, atomically: true, encoding: .utf8)

            let activityVC = UIActivityViewController(
                activityItems: [tempURL],
                applicationActivities: nil
            )

            if let popover = activityVC.popoverPresentationController {
                popover.sourceView = viewController.view
                popover.sourceRect = CGRect(
                    x: viewController.view.bounds.midX,
                    y: viewController.view.bounds.midY,
                    width: 0,
                    height: 0
                )
            }

            DispatchQueue.main.async {
                viewController.present(activityVC, animated: true)
            }
        } catch {
            print("Share file error: \(error)")
        }
    }

    func shareCalendarEvent(
        title: String,
        notes: String,
        startDate: Date,
        durationMinutes: Int = 60
    ) {
        let endDate = startDate.addingTimeInterval(TimeInterval(durationMinutes * 60))
        let icsContent = calendarICS(
            title: title,
            notes: notes,
            startDate: startDate,
            endDate: endDate
        )
        shareTextFile(content: icsContent, fileName: "PortfolioJournal-CheckIn.ics")
    }

    private static func topViewController(
        base: UIViewController? = UIApplication.shared.connectedScenes
            .compactMap { $0 as? UIWindowScene }
            .flatMap { $0.windows }
            .first(where: { $0.isKeyWindow })?.rootViewController
    ) -> UIViewController? {
        if let nav = base as? UINavigationController {
            return topViewController(base: nav.visibleViewController)
        }
        if let tab = base as? UITabBarController {
            return topViewController(base: tab.selectedViewController)
        }
        if let presented = base?.presentedViewController {
            return topViewController(base: presented)
        }
        return base
    }

    private func calendarICS(
        title: String,
        notes: String,
        startDate: Date,
        endDate: Date
    ) -> String {
        let uid = UUID().uuidString
        let formatter = DateFormatter()
        formatter.dateFormat = "yyyyMMdd'T'HHmmss'Z'"
        formatter.timeZone = TimeZone(secondsFromGMT: 0)
        let stamp = formatter.string(from: Date())
        let start = formatter.string(from: startDate)
        let end = formatter.string(from: endDate)

        return """
        BEGIN:VCALENDAR
        VERSION:2.0
        PRODID:-//PortfolioJournal//MonthlyCheckIn//EN
        BEGIN:VEVENT
        UID:\(uid)
        DTSTAMP:\(stamp)
        DTSTART:\(start)
        DTEND:\(end)
        SUMMARY:\(escapeICS(title))
        DESCRIPTION:\(escapeICS(notes))
        END:VEVENT
        END:VCALENDAR
        """
    }

    private func escapeICS(_ value: String) -> String {
        value
            .replacingOccurrences(of: "\\", with: "\\\\")
            .replacingOccurrences(of: "\n", with: "\\n")
            .replacingOccurrences(of: ";", with: "\\;")
            .replacingOccurrences(of: ",", with: "\\,")
    }

    private func presentShareSheet(items: [Any], from viewController: UIViewController) {
        let activityVC = UIActivityViewController(activityItems: items, applicationActivities: nil)
        if let popover = activityVC.popoverPresentationController {
            popover.sourceView = viewController.view
            popover.sourceRect = CGRect(
                x: viewController.view.bounds.midX,
                y: viewController.view.bounds.midY,
                width: 0,
                height: 0
            )
            popover.permittedArrowDirections = []
        }
        viewController.present(activityVC, animated: true)
    }

    private static var appDisplayName: String {
        if let name = Bundle.main.object(forInfoDictionaryKey: "CFBundleDisplayName") as? String {
            return name
        }
        if let name = Bundle.main.object(forInfoDictionaryKey: "CFBundleName") as? String {
            return name
        }
        return "Portfolio Journal"
    }
}

private class CardShareItem: NSObject, UIActivityItemSource {
    let image: UIImage
    let title: String
    let text: String
    let url: URL

    init(image: UIImage, title: String, text: String, url: URL) {
        self.image = image
        self.title = title
        self.text = text
        self.url = url
    }

    func activityViewControllerPlaceholderItem(_ activityViewController: UIActivityViewController) -> Any {
        image
    }

    func activityViewController(_ activityViewController: UIActivityViewController, itemForActivityType activityType: UIActivity.ActivityType?) -> Any? {
        image
    }

    func activityViewController(_ activityViewController: UIActivityViewController, subjectForActivityType activityType: UIActivity.ActivityType?) -> String {
        title
    }

    func activityViewControllerLinkMetadata(_ activityViewController: UIActivityViewController) -> LPLinkMetadata? {
        let metadata = LPLinkMetadata()
        metadata.title = title
        metadata.originalURL = url
        metadata.url = url
        metadata.imageProvider = NSItemProvider(object: image)
        if let appIcon = UIImage(named: "BrandMark") {
            metadata.iconProvider = NSItemProvider(object: appIcon)
        }
        return metadata
    }
}
