//
//  ExportService.swift
//  Reflect
//
//  Handles exporting mood data to CSV and PDF formats with beautiful visualizations.
//

import Foundation
import SwiftUI
import PDFKit
import UIKit

class ExportService {

    static let shared = ExportService()

    // MARK: - Date Formatter

    private let dateFormatter: DateFormatter = {
        let formatter = DateFormatter()
        formatter.dateStyle = .medium
        formatter.timeStyle = .short
        return formatter
    }()

    private let shortDateFormatter: DateFormatter = {
        let formatter = DateFormatter()
        formatter.dateFormat = "MMM d"
        return formatter
    }()

    private let isoFormatter: ISO8601DateFormatter = {
        let formatter = ISO8601DateFormatter()
        formatter.formatOptions = [.withInternetDateTime]
        return formatter
    }()

    // MARK: - Colors (using default mood tint colors)

    private let moodColors: [Mood: UIColor] = [
        .great: UIColor(red: 0.29, green: 0.78, blue: 0.55, alpha: 1.0),    // Green
        .good: UIColor(red: 0.56, green: 0.79, blue: 0.35, alpha: 1.0),     // Light Green
        .average: UIColor(red: 1.0, green: 0.76, blue: 0.03, alpha: 1.0),   // Yellow
        .bad: UIColor(red: 1.0, green: 0.58, blue: 0.0, alpha: 1.0),        // Orange
        .horrible: UIColor(red: 0.91, green: 0.30, blue: 0.24, alpha: 1.0)  // Red
    ]

    private func trackDataExported(format: String, count: Int) {
        Task { @MainActor in
            AnalyticsManager.shared.track(.dataExported(format: format, count: count))
        }
    }

    // MARK: - CSV Export

    func generateCSV(entries: [MoodEntryModel]) -> String {
        var csv = "Date,Mood,Mood Value,Notes,Weekday,Entry Type,Timestamp\n"

        let sortedEntries = entries.sorted { $0.forDate > $1.forDate }

        for entry in sortedEntries {
            let date = dateFormatter.string(from: entry.forDate)
            let mood = entry.mood.widgetDisplayName
            let moodValue = entry.moodValue + 1  // 1-5 scale
            let notes = escapeCSV(entry.notes ?? "")
            let weekday = weekdayName(from: entry.weekDay)
            let entryType = EntryType(rawValue: entry.entryType)?.description ?? "Unknown"
            let timestamp = isoFormatter.string(from: entry.timestamp)

            csv += "\(date),\(mood),\(moodValue),\(notes),\(weekday),\(entryType),\(timestamp)\n"
        }

        return csv
    }

    func exportCSV(entries: [MoodEntryModel]) -> URL? {
        let csv = generateCSV(entries: entries)

        let filename = "Reflect-Export-\(formattedDate()).csv"
        let tempURL = FileManager.default.temporaryDirectory.appendingPathComponent(filename)

        do {
            try csv.write(to: tempURL, atomically: true, encoding: .utf8)
            trackDataExported(format: "csv", count: entries.count)
            return tempURL
        } catch {
            print("ExportService: Failed to write CSV: \(error)")
            return nil
        }
    }

    // MARK: - PDF Export

    func generatePDF(entries: [MoodEntryModel], title: String = "Mood Report") -> Data? {
        let sortedEntries = entries.sorted { $0.forDate > $1.forDate }
        let validEntries = sortedEntries.filter { ![.missing, .placeholder].contains($0.mood) }

        guard !validEntries.isEmpty else { return nil }

        // Calculate statistics
        let stats = calculateStats(entries: validEntries)

        // PDF Setup
        let pageWidth: CGFloat = 612  // US Letter
        let pageHeight: CGFloat = 792
        let margin: CGFloat = 40
        let contentWidth = pageWidth - (margin * 2)

        let pdfMetaData = [
            kCGPDFContextCreator: "Reflect App",
            kCGPDFContextTitle: title
        ]

        let format = UIGraphicsPDFRendererFormat()
        format.documentInfo = pdfMetaData as [String: Any]

        let renderer = UIGraphicsPDFRenderer(
            bounds: CGRect(x: 0, y: 0, width: pageWidth, height: pageHeight),
            format: format
        )

        let data = renderer.pdfData { context in
            // PAGE 1: Overview
            context.beginPage()
            var yPosition: CGFloat = margin

            // Header with gradient background
            yPosition = drawHeader(at: yPosition, title: title, stats: stats, margin: margin, width: contentWidth, pageWidth: pageWidth, in: context)

            // Summary Cards
            yPosition = drawSummaryCards(at: yPosition, stats: stats, margin: margin, width: contentWidth, in: context)

            // Mood Distribution Chart
            yPosition = drawMoodDistributionChart(at: yPosition, stats: stats, margin: margin, width: contentWidth, in: context)

            // Weekday Analysis
            if yPosition < pageHeight - 250 {
                yPosition = drawWeekdayAnalysis(at: yPosition, entries: validEntries, margin: margin, width: contentWidth, in: context)
            }

            // PAGE 2: Trends & Details
            context.beginPage()
            yPosition = margin + 20

            // Page 2 Header
            yPosition = drawSectionTitle("Trends & Patterns", at: yPosition, margin: margin)

            // Mood Trend Line (last 30 entries)
            yPosition = drawTrendChart(at: yPosition, entries: validEntries, margin: margin, width: contentWidth, in: context)

            // Streaks Section
            yPosition = drawStreaksSection(at: yPosition, stats: stats, margin: margin, width: contentWidth, in: context)

            // Recent Entries Table
            yPosition = drawRecentEntries(at: yPosition, entries: validEntries, margin: margin, width: contentWidth, pageHeight: pageHeight, in: context)

            // Footer
            drawFooter(pageWidth: pageWidth, pageHeight: pageHeight, margin: margin, in: context)
        }

        trackDataExported(format: "pdf", count: entries.count)
        return data
    }

    func exportPDF(entries: [MoodEntryModel], title: String = "Mood Report") -> URL? {
        guard let data = generatePDF(entries: entries, title: title) else {
            return nil
        }

        let filename = "Reflect-Report-\(formattedDate()).pdf"
        let tempURL = FileManager.default.temporaryDirectory.appendingPathComponent(filename)

        do {
            try data.write(to: tempURL)
            return tempURL
        } catch {
            print("ExportService: Failed to write PDF: \(error)")
            return nil
        }
    }

    // MARK: - PDF Drawing: Header

    private func drawHeader(at y: CGFloat, title: String, stats: ExportStats, margin: CGFloat, width: CGFloat, pageWidth: CGFloat, in context: UIGraphicsPDFRendererContext) -> CGFloat {
        let headerHeight: CGFloat = 120

        // Draw gradient background
        let gradientColors = [
            UIColor(red: 0.29, green: 0.56, blue: 0.89, alpha: 1.0).cgColor,
            UIColor(red: 0.56, green: 0.35, blue: 0.89, alpha: 1.0).cgColor
        ]
        let colorSpace = CGColorSpaceCreateDeviceRGB()
        if let gradient = CGGradient(colorsSpace: colorSpace, colors: gradientColors as CFArray, locations: [0, 1]) {
            context.cgContext.saveGState()
            context.cgContext.addRect(CGRect(x: 0, y: y, width: pageWidth, height: headerHeight))
            context.cgContext.clip()
            context.cgContext.drawLinearGradient(gradient, start: CGPoint(x: 0, y: y), end: CGPoint(x: pageWidth, y: y + headerHeight), options: [])
            context.cgContext.restoreGState()
        }

        // Title
        let titleFont = UIFont.systemFont(ofSize: 28, weight: .bold)
        let titleAttributes: [NSAttributedString.Key: Any] = [
            .font: titleFont,
            .foregroundColor: UIColor.white
        ]
        let titleString = NSAttributedString(string: title, attributes: titleAttributes)
        titleString.draw(at: CGPoint(x: margin, y: y + 25))

        // Subtitle with date range
        let subtitleFont = UIFont.systemFont(ofSize: 14, weight: .medium)
        let subtitleAttributes: [NSAttributedString.Key: Any] = [
            .font: subtitleFont,
            .foregroundColor: UIColor.white.withAlphaComponent(0.9)
        ]
        let subtitleString = NSAttributedString(string: stats.dateRange, attributes: subtitleAttributes)
        subtitleString.draw(at: CGPoint(x: margin, y: y + 60))

        // Generated date
        let dateFont = UIFont.systemFont(ofSize: 11, weight: .regular)
        let dateAttributes: [NSAttributedString.Key: Any] = [
            .font: dateFont,
            .foregroundColor: UIColor.white.withAlphaComponent(0.7)
        ]
        let generatedString = NSAttributedString(string: "Generated \(dateFormatter.string(from: Date()))", attributes: dateAttributes)
        generatedString.draw(at: CGPoint(x: margin, y: y + 85))

        return y + headerHeight + 25
    }

    // MARK: - PDF Drawing: Summary Cards

    private func drawSummaryCards(at y: CGFloat, stats: ExportStats, margin: CGFloat, width: CGFloat, in context: UIGraphicsPDFRendererContext) -> CGFloat {
        let cardHeight: CGFloat = 80
        let cardWidth = (width - 20) / 3
        let cornerRadius: CGFloat = 10

        let cards: [(String, String, UIColor)] = [
            ("\(stats.totalEntries)", "Total Entries", UIColor(red: 0.29, green: 0.78, blue: 0.55, alpha: 1.0)),
            (String(format: "%.1f", stats.averageMood), "Avg Mood (1-5)", UIColor(red: 0.29, green: 0.56, blue: 0.89, alpha: 1.0)),
            (stats.mostCommonMood, "Top Mood", moodColors[Mood.allValues.first { $0.widgetDisplayName == stats.mostCommonMood } ?? .average] ?? .gray)
        ]

        for (index, card) in cards.enumerated() {
            let xPos = margin + CGFloat(index) * (cardWidth + 10)

            // Card background
            let cardRect = CGRect(x: xPos, y: y, width: cardWidth, height: cardHeight)
            let cardPath = UIBezierPath(roundedRect: cardRect, cornerRadius: cornerRadius)

            // Light background
            UIColor(white: 0.97, alpha: 1.0).setFill()
            cardPath.fill()

            // Accent bar on left
            let accentRect = CGRect(x: xPos, y: y, width: 4, height: cardHeight)
            let accentPath = UIBezierPath(roundedRect: accentRect, byRoundingCorners: [.topLeft, .bottomLeft], cornerRadii: CGSize(width: cornerRadius, height: cornerRadius))
            card.2.setFill()
            accentPath.fill()

            // Value
            let valueFont = UIFont.systemFont(ofSize: 24, weight: .bold)
            let valueAttributes: [NSAttributedString.Key: Any] = [
                .font: valueFont,
                .foregroundColor: UIColor.darkGray
            ]
            let valueString = NSAttributedString(string: card.0, attributes: valueAttributes)
            valueString.draw(at: CGPoint(x: xPos + 15, y: y + 18))

            // Label
            let labelFont = UIFont.systemFont(ofSize: 11, weight: .medium)
            let labelAttributes: [NSAttributedString.Key: Any] = [
                .font: labelFont,
                .foregroundColor: UIColor.gray
            ]
            let labelString = NSAttributedString(string: card.1, attributes: labelAttributes)
            labelString.draw(at: CGPoint(x: xPos + 15, y: y + 50))
        }

        return y + cardHeight + 30
    }

    // MARK: - PDF Drawing: Mood Distribution Chart

    private func drawMoodDistributionChart(at y: CGFloat, stats: ExportStats, margin: CGFloat, width: CGFloat, in context: UIGraphicsPDFRendererContext) -> CGFloat {
        let currentY = drawSectionTitle("Mood Distribution", at: y, margin: margin)

        let chartHeight: CGFloat = 140
        let barHeight: CGFloat = 22
        let barSpacing: CGFloat = 8
        let labelWidth: CGFloat = 70
        let percentWidth: CGFloat = 50

        let sortedMoods: [Mood] = [.great, .good, .average, .bad, .horrible]

        for (index, mood) in sortedMoods.enumerated() {
            let count = stats.moodDistribution[mood.widgetDisplayName] ?? 0
            let percentage = stats.totalEntries > 0 ? (Double(count) / Double(stats.totalEntries)) * 100 : 0
            let barY = currentY + CGFloat(index) * (barHeight + barSpacing)

            // Mood label
            let labelFont = UIFont.systemFont(ofSize: 12, weight: .medium)
            let labelAttributes: [NSAttributedString.Key: Any] = [
                .font: labelFont,
                .foregroundColor: UIColor.darkGray
            ]
            let labelString = NSAttributedString(string: mood.widgetDisplayName, attributes: labelAttributes)
            labelString.draw(at: CGPoint(x: margin, y: barY + 3))

            // Bar background
            let barX = margin + labelWidth
            let maxBarWidth = width - labelWidth - percentWidth - 10
            let barRect = CGRect(x: barX, y: barY, width: maxBarWidth, height: barHeight)
            let barPath = UIBezierPath(roundedRect: barRect, cornerRadius: 4)
            UIColor(white: 0.92, alpha: 1.0).setFill()
            barPath.fill()

            // Filled bar
            let filledWidth = maxBarWidth * CGFloat(percentage / 100)
            if filledWidth > 0 {
                let filledRect = CGRect(x: barX, y: barY, width: max(8, filledWidth), height: barHeight)
                let filledPath = UIBezierPath(roundedRect: filledRect, cornerRadius: 4)
                (moodColors[mood] ?? .gray).setFill()
                filledPath.fill()
            }

            // Percentage label
            let percentFont = UIFont.systemFont(ofSize: 12, weight: .semibold)
            let percentAttributes: [NSAttributedString.Key: Any] = [
                .font: percentFont,
                .foregroundColor: moodColors[mood] ?? .gray
            ]
            let percentString = NSAttributedString(string: String(format: "%.0f%%", percentage), attributes: percentAttributes)
            percentString.draw(at: CGPoint(x: margin + width - percentWidth + 10, y: barY + 3))
        }

        return currentY + chartHeight + 20
    }

    // MARK: - PDF Drawing: Weekday Analysis

    private func drawWeekdayAnalysis(at y: CGFloat, entries: [MoodEntryModel], margin: CGFloat, width: CGFloat, in context: UIGraphicsPDFRendererContext) -> CGFloat {
        let currentY = drawSectionTitle("Mood by Day of Week", at: y, margin: margin)

        let weekdays = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]
        var weekdayAverages: [Double] = Array(repeating: 0, count: 7)
        var weekdayCounts: [Int] = Array(repeating: 0, count: 7)

        for entry in entries {
            let weekdayIndex = entry.weekDay - 1
            if weekdayIndex >= 0 && weekdayIndex < 7 {
                weekdayAverages[weekdayIndex] += Double(entry.moodValue + 1)
                weekdayCounts[weekdayIndex] += 1
            }
        }

        for i in 0..<7 {
            if weekdayCounts[i] > 0 {
                weekdayAverages[i] /= Double(weekdayCounts[i])
            }
        }

        // Draw bar chart
        let chartHeight: CGFloat = 100
        let barWidth = (width - 60) / 7
        let maxValue: Double = 5.0

        for (index, avg) in weekdayAverages.enumerated() {
            let barX = margin + CGFloat(index) * (barWidth + 5) + 10
            let barHeight = chartHeight * CGFloat(avg / maxValue)

            // Bar
            if barHeight > 0 {
                let barRect = CGRect(x: barX, y: currentY + chartHeight - barHeight, width: barWidth - 5, height: barHeight)
                let barPath = UIBezierPath(roundedRect: barRect, byRoundingCorners: [.topLeft, .topRight], cornerRadii: CGSize(width: 4, height: 4))

                // Color based on average
                let color: UIColor
                if avg >= 4.0 { color = moodColors[.great]! }
                else if avg >= 3.0 { color = moodColors[.good]! }
                else if avg >= 2.5 { color = moodColors[.average]! }
                else if avg >= 1.5 { color = moodColors[.bad]! }
                else { color = moodColors[.horrible]! }

                color.setFill()
                barPath.fill()
            }

            // Day label
            let labelFont = UIFont.systemFont(ofSize: 10, weight: .medium)
            let labelAttributes: [NSAttributedString.Key: Any] = [
                .font: labelFont,
                .foregroundColor: UIColor.gray
            ]
            let labelString = NSAttributedString(string: weekdays[index], attributes: labelAttributes)
            let labelSize = labelString.size()
            labelString.draw(at: CGPoint(x: barX + (barWidth - 5 - labelSize.width) / 2, y: currentY + chartHeight + 5))

            // Value label
            if weekdayCounts[index] > 0 {
                let valueFont = UIFont.systemFont(ofSize: 9, weight: .semibold)
                let valueAttributes: [NSAttributedString.Key: Any] = [
                    .font: valueFont,
                    .foregroundColor: UIColor.darkGray
                ]
                let valueString = NSAttributedString(string: String(format: "%.1f", avg), attributes: valueAttributes)
                let valueSize = valueString.size()
                valueString.draw(at: CGPoint(x: barX + (barWidth - 5 - valueSize.width) / 2, y: currentY + chartHeight - barHeight - 15))
            }
        }

        return currentY + chartHeight + 40
    }

    // MARK: - PDF Drawing: Trend Chart

    private func drawTrendChart(at y: CGFloat, entries: [MoodEntryModel], margin: CGFloat, width: CGFloat, in context: UIGraphicsPDFRendererContext) -> CGFloat {
        var currentY = y + 10

        let chartHeight: CGFloat = 120
        let recentEntries = Array(entries.prefix(30).reversed())

        guard recentEntries.count >= 2 else {
            return currentY
        }

        // Section label
        let labelFont = UIFont.systemFont(ofSize: 12, weight: .medium)
        let labelAttributes: [NSAttributedString.Key: Any] = [
            .font: labelFont,
            .foregroundColor: UIColor.gray
        ]
        let labelString = NSAttributedString(string: "Last \(recentEntries.count) Entries", attributes: labelAttributes)
        labelString.draw(at: CGPoint(x: margin, y: currentY))
        currentY += 25

        // Draw chart background
        let chartRect = CGRect(x: margin, y: currentY, width: width, height: chartHeight)
        let chartPath = UIBezierPath(roundedRect: chartRect, cornerRadius: 8)
        UIColor(white: 0.97, alpha: 1.0).setFill()
        chartPath.fill()

        // Draw grid lines
        context.cgContext.setStrokeColor(UIColor(white: 0.9, alpha: 1.0).cgColor)
        context.cgContext.setLineWidth(1)
        for i in 1...4 {
            let gridY = currentY + chartHeight - (chartHeight * CGFloat(i) / 5)
            context.cgContext.move(to: CGPoint(x: margin + 10, y: gridY))
            context.cgContext.addLine(to: CGPoint(x: margin + width - 10, y: gridY))
            context.cgContext.strokePath()
        }

        // Draw trend line
        let pointSpacing = (width - 40) / CGFloat(recentEntries.count - 1)
        var points: [CGPoint] = []

        for (index, entry) in recentEntries.enumerated() {
            let x = margin + 20 + CGFloat(index) * pointSpacing
            let normalizedMood = CGFloat(entry.moodValue) / 4.0  // 0-4 scale to 0-1
            let pointY = currentY + chartHeight - 15 - (normalizedMood * (chartHeight - 30))
            points.append(CGPoint(x: x, y: pointY))
        }

        // Draw the line
        let linePath = UIBezierPath()
        linePath.move(to: points[0])
        for point in points.dropFirst() {
            linePath.addLine(to: point)
        }
        UIColor(red: 0.29, green: 0.56, blue: 0.89, alpha: 1.0).setStroke()
        linePath.lineWidth = 2.5
        linePath.lineCapStyle = .round
        linePath.lineJoinStyle = .round
        linePath.stroke()

        // Draw points
        for (index, point) in points.enumerated() {
            let entry = recentEntries[index]
            let color = moodColors[entry.mood] ?? .gray

            let pointRect = CGRect(x: point.x - 4, y: point.y - 4, width: 8, height: 8)
            let pointPath = UIBezierPath(ovalIn: pointRect)
            color.setFill()
            pointPath.fill()

            UIColor.white.setStroke()
            pointPath.lineWidth = 1.5
            pointPath.stroke()
        }

        return currentY + chartHeight + 30
    }

    // MARK: - PDF Drawing: Streaks Section

    private func drawStreaksSection(at y: CGFloat, stats: ExportStats, margin: CGFloat, width: CGFloat, in context: UIGraphicsPDFRendererContext) -> CGFloat {
        let currentY = drawSectionTitle("Streaks & Consistency", at: y, margin: margin)

        let cardWidth = (width - 15) / 2
        let cardHeight: CGFloat = 60

        let streaks: [(String, String, String)] = [
            ("\(stats.currentStreak)", "Current Streak", "days in a row"),
            ("\(stats.longestStreak)", "Longest Streak", "days tracked"),
            ("\(stats.positiveStreak)", "Best Mood Streak", "good/great days"),
            (String(format: "%.0f%%", stats.stabilityScore * 100), "Mood Stability", "consistency score")
        ]

        for (index, streak) in streaks.enumerated() {
            let row = index / 2
            let col = index % 2
            let xPos = margin + CGFloat(col) * (cardWidth + 15)
            let yPos = currentY + CGFloat(row) * (cardHeight + 10)

            // Card background
            let cardRect = CGRect(x: xPos, y: yPos, width: cardWidth, height: cardHeight)
            let cardPath = UIBezierPath(roundedRect: cardRect, cornerRadius: 8)
            UIColor(white: 0.97, alpha: 1.0).setFill()
            cardPath.fill()

            // Value
            let valueFont = UIFont.systemFont(ofSize: 22, weight: .bold)
            let valueAttributes: [NSAttributedString.Key: Any] = [
                .font: valueFont,
                .foregroundColor: UIColor(red: 0.29, green: 0.56, blue: 0.89, alpha: 1.0)
            ]
            let valueString = NSAttributedString(string: streak.0, attributes: valueAttributes)
            valueString.draw(at: CGPoint(x: xPos + 12, y: yPos + 10))

            // Label
            let labelFont = UIFont.systemFont(ofSize: 10, weight: .medium)
            let labelAttributes: [NSAttributedString.Key: Any] = [
                .font: labelFont,
                .foregroundColor: UIColor.gray
            ]
            let labelString = NSAttributedString(string: "\(streak.1) - \(streak.2)", attributes: labelAttributes)
            labelString.draw(at: CGPoint(x: xPos + 12, y: yPos + 38))
        }

        return currentY + (cardHeight + 10) * 2 + 20
    }

    // MARK: - PDF Drawing: Recent Entries

    private func drawRecentEntries(at y: CGFloat, entries: [MoodEntryModel], margin: CGFloat, width: CGFloat, pageHeight: CGFloat, in context: UIGraphicsPDFRendererContext) -> CGFloat {
        var currentY = drawSectionTitle("Recent Entries", at: y, margin: margin)

        let recentEntries = Array(entries.prefix(15))
        let rowHeight: CGFloat = 28

        // Header
        let headerFont = UIFont.systemFont(ofSize: 10, weight: .semibold)
        let headerAttributes: [NSAttributedString.Key: Any] = [
            .font: headerFont,
            .foregroundColor: UIColor.gray
        ]

        NSAttributedString(string: "Date", attributes: headerAttributes).draw(at: CGPoint(x: margin, y: currentY))
        NSAttributedString(string: "Mood", attributes: headerAttributes).draw(at: CGPoint(x: margin + 120, y: currentY))
        NSAttributedString(string: "Notes", attributes: headerAttributes).draw(at: CGPoint(x: margin + 200, y: currentY))

        currentY += 20

        // Divider
        context.cgContext.setStrokeColor(UIColor(white: 0.9, alpha: 1.0).cgColor)
        context.cgContext.setLineWidth(1)
        context.cgContext.move(to: CGPoint(x: margin, y: currentY))
        context.cgContext.addLine(to: CGPoint(x: margin + width, y: currentY))
        context.cgContext.strokePath()
        currentY += 8

        // Entries
        let bodyFont = UIFont.systemFont(ofSize: 10, weight: .regular)

        for entry in recentEntries {
            if currentY > pageHeight - 60 { break }

            // Date
            let dateAttributes: [NSAttributedString.Key: Any] = [
                .font: bodyFont,
                .foregroundColor: UIColor.darkGray
            ]
            let dateString = NSAttributedString(string: shortDateFormatter.string(from: entry.forDate), attributes: dateAttributes)
            dateString.draw(at: CGPoint(x: margin, y: currentY + 5))

            // Mood indicator dot
            let dotRect = CGRect(x: margin + 120, y: currentY + 8, width: 10, height: 10)
            let dotPath = UIBezierPath(ovalIn: dotRect)
            (moodColors[entry.mood] ?? .gray).setFill()
            dotPath.fill()

            // Mood name
            let moodAttributes: [NSAttributedString.Key: Any] = [
                .font: bodyFont,
                .foregroundColor: moodColors[entry.mood] ?? .gray
            ]
            let moodString = NSAttributedString(string: entry.mood.widgetDisplayName, attributes: moodAttributes)
            moodString.draw(at: CGPoint(x: margin + 135, y: currentY + 5))

            // Notes (truncated)
            if let notes = entry.notes, !notes.isEmpty {
                let truncatedNotes = notes.count > 40 ? String(notes.prefix(40)) + "..." : notes
                let notesAttributes: [NSAttributedString.Key: Any] = [
                    .font: bodyFont,
                    .foregroundColor: UIColor.gray
                ]
                let notesString = NSAttributedString(string: truncatedNotes, attributes: notesAttributes)
                notesString.draw(at: CGPoint(x: margin + 200, y: currentY + 5))
            }

            currentY += rowHeight
        }

        return currentY + 20
    }

    // MARK: - PDF Drawing: Footer

    private func drawFooter(pageWidth: CGFloat, pageHeight: CGFloat, margin: CGFloat, in context: UIGraphicsPDFRendererContext) {
        let footerY = pageHeight - 30

        let footerFont = UIFont.systemFont(ofSize: 9, weight: .regular)
        let footerAttributes: [NSAttributedString.Key: Any] = [
            .font: footerFont,
            .foregroundColor: UIColor.lightGray
        ]
        let footerString = NSAttributedString(string: "Generated by Reflect - Your Mood Tracking Companion", attributes: footerAttributes)
        let footerSize = footerString.size()
        footerString.draw(at: CGPoint(x: (pageWidth - footerSize.width) / 2, y: footerY))
    }

    // MARK: - PDF Drawing: Section Title

    private func drawSectionTitle(_ title: String, at y: CGFloat, margin: CGFloat) -> CGFloat {
        let font = UIFont.systemFont(ofSize: 16, weight: .bold)
        let attributes: [NSAttributedString.Key: Any] = [
            .font: font,
            .foregroundColor: UIColor.darkGray
        ]
        let string = NSAttributedString(string: title, attributes: attributes)
        string.draw(at: CGPoint(x: margin, y: y))
        return y + 30
    }

    // MARK: - Statistics

    struct ExportStats {
        let totalEntries: Int
        let dateRange: String
        let averageMood: Double
        let mostCommonMood: String
        let moodDistribution: [String: Int]
        let currentStreak: Int
        let longestStreak: Int
        let positiveStreak: Int
        let stabilityScore: Double
    }

    private func calculateStats(entries: [MoodEntryModel]) -> ExportStats {
        let validEntries = entries.filter { ![.missing, .placeholder].contains($0.mood) }

        var moodCounts: [String: Int] = [:]
        var totalMoodValue = 0

        for entry in validEntries {
            let moodName = entry.mood.widgetDisplayName
            moodCounts[moodName, default: 0] += 1
            totalMoodValue += entry.moodValue + 1
        }

        let avgMood = validEntries.isEmpty ? 0 : Double(totalMoodValue) / Double(validEntries.count)
        let mostCommon = moodCounts.max(by: { $0.value < $1.value })?.key ?? "N/A"

        var dateRange = "No entries"
        if let first = validEntries.last?.forDate, let last = validEntries.first?.forDate {
            dateRange = "\(shortDateFormatter.string(from: first)) - \(shortDateFormatter.string(from: last))"
        }

        // Calculate streaks
        let calendar = Calendar.current
        let sortedByDateDesc = validEntries.sorted { $0.forDate > $1.forDate }
        var currentStreak = 0
        var longestStreak = 1
        var tempStreak = 1

        if let mostRecent = sortedByDateDesc.first?.forDate {
            let today = calendar.startOfDay(for: Date())
            let yesterday = calendar.date(byAdding: .day, value: -1, to: today)!

            if calendar.isDate(mostRecent, inSameDayAs: today) || calendar.isDate(mostRecent, inSameDayAs: yesterday) {
                currentStreak = 1
                for i in 1..<sortedByDateDesc.count {
                    let dayDiff = calendar.dateComponents([.day], from: sortedByDateDesc[i].forDate, to: sortedByDateDesc[i-1].forDate).day ?? 0
                    if dayDiff == 1 {
                        currentStreak += 1
                    } else {
                        break
                    }
                }
            }
        }

        let sortedByDateAsc = validEntries.sorted { $0.forDate < $1.forDate }
        for i in 1..<sortedByDateAsc.count {
            let dayDiff = calendar.dateComponents([.day], from: sortedByDateAsc[i-1].forDate, to: sortedByDateAsc[i].forDate).day ?? 0
            if dayDiff == 1 {
                tempStreak += 1
                longestStreak = max(longestStreak, tempStreak)
            } else {
                tempStreak = 1
            }
        }

        // Positive streak
        var positiveStreak = 0
        var tempPositive = 0
        for entry in sortedByDateAsc {
            if [Mood.good, Mood.great].contains(entry.mood) {
                tempPositive += 1
                positiveStreak = max(positiveStreak, tempPositive)
            } else {
                tempPositive = 0
            }
        }

        // Stability score
        var swings = 0
        for i in 1..<sortedByDateAsc.count {
            let diff = abs(sortedByDateAsc[i].moodValue - sortedByDateAsc[i-1].moodValue)
            if diff >= 2 { swings += 1 }
        }
        let stabilityScore = sortedByDateAsc.count > 1 ? 1.0 - min(Double(swings) / Double(sortedByDateAsc.count - 1), 1.0) : 1.0

        return ExportStats(
            totalEntries: validEntries.count,
            dateRange: dateRange,
            averageMood: avgMood,
            mostCommonMood: mostCommon,
            moodDistribution: moodCounts,
            currentStreak: currentStreak,
            longestStreak: longestStreak,
            positiveStreak: positiveStreak,
            stabilityScore: stabilityScore
        )
    }

    // MARK: - Helpers

    private func escapeCSV(_ string: String) -> String {
        var result = string
        if result.contains("\"") || result.contains(",") || result.contains("\n") {
            result = result.replacingOccurrences(of: "\"", with: "\"\"")
            result = "\"\(result)\""
        }
        return result
    }

    private func weekdayName(from weekday: Int) -> String {
        let weekdays = ["", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]
        return weekdays[safe: weekday] ?? "Unknown"
    }

    private func formattedDate() -> String {
        let formatter = DateFormatter()
        formatter.dateFormat = "yyyy-MM-dd"
        return formatter.string(from: Date())
    }
}

// MARK: - EntryType Description

extension EntryType: CustomStringConvertible {
    public var description: String {
        switch self {
        case .listView: return "Manual"
        case .widget: return "Widget"
        case .watch: return "Watch"
        case .shortcut: return "Shortcut"
        case .filledInMissing: return "Auto-filled"
        case .notification: return "Notification"
        case .header: return "Header"
        case .siri: return "Siri"
        case .controlCenter: return "Control Center"
        case .liveActivity: return "Live Activity"
        }
    }
}

// MARK: - Safe Array Access

private extension Array {
    subscript(safe index: Int) -> Element? {
        return indices.contains(index) ? self[index] : nil
    }
}
