//
//  ReflectTimelineWidget.swift
//  ReflectWidget
//
//  Timeline widget showing mood history (small, medium, large)
//

import WidgetKit
import SwiftUI
import Intents

// MARK: - Widget Configuration

struct ReflectWidget: Widget {
    let kind: String = "ReflectWidget"

    var body: some WidgetConfiguration {
        IntentConfiguration(kind: kind,
                            intent: ConfigurationIntent.self,
                            provider: Provider()) { entry in
            ReflectWidgetEntryView(entry: entry)
        }
                            .configurationDisplayName("Reflect")
                            .description("")
                            .supportedFamilies([.systemSmall, .systemMedium, .systemLarge])
    }
}

// MARK: - Entry View Router

struct ReflectWidgetEntryView: View {
    @Environment(\.sizeCategory) var sizeCategory
    @Environment(\.widgetFamily) var family

    var entry: Provider.Entry

    private var showVotingForToday: Bool {
        !entry.hasVotedToday
    }

    @ViewBuilder
    var body: some View {
        Group {
            switch family {
            case .systemSmall:
                SmallWidgetView(entry: entry)
            case .systemMedium:
                MediumWidgetView(entry: entry)
            case .systemLarge:
                LargeWidgetView(entry: entry)
            case .systemExtraLarge:
                LargeWidgetView(entry: entry)
            case .accessoryCircular, .accessoryRectangular, .accessoryInline:
                SmallWidgetView(entry: entry)
            @unknown default:
                MediumWidgetView(entry: entry)
            }
        }
        .containerBackground(showVotingForToday ? Color.clear : Color(UIColor.systemBackground), for: .widget)
    }
}

// MARK: - Small Widget View

struct SmallWidgetView: View {
    var entry: Provider.Entry
    var todayView: WatchTimelineView?

    private var showVotingForToday: Bool {
        !entry.hasVotedToday
    }

    private var dayFormatter: DateFormatter {
        let f = DateFormatter()
        f.dateFormat = "EEEE"
        return f
    }

    private var dateFormatter: DateFormatter {
        let f = DateFormatter()
        f.dateFormat = "MMM d"
        return f
    }

    init(entry: Provider.Entry) {
        self.entry = entry
        let realData = TimeLineCreator.createViews(daysBack: 2)
        let hasRealData = realData.contains { view in
            let moodTint: MoodTintable.Type = UserDefaultsStore.moodTintable()
            return view.color != moodTint.color(forMood: .missing)
        }
        todayView = hasRealData ? realData.first : TimeLineCreator.createSampleViews(count: 1).first
    }

    var body: some View {
        if showVotingForToday {
            // Show interactive voting buttons (or open app links if expired)
            VotingView(family: .systemSmall, promptText: entry.promptText, hasSubscription: entry.hasSubscription)
        } else if let today = todayView {
            VStack(spacing: 0) {
                Spacer()

                // Large mood icon
                today.image
                    .resizable()
                    .aspectRatio(contentMode: .fit)
                    .frame(width: 70, height: 70)
                    .foregroundColor(today.color)
                    .accessibilityLabel(today.mood.strValue)

                Spacer()
                    .frame(height: 12)

                // Date info
                VStack(spacing: 2) {
                    Text(dayFormatter.string(from: today.date))
                        .font(.caption2.weight(.medium))
                        .foregroundStyle(.secondary)
                        .textCase(.uppercase)

                    Text(dateFormatter.string(from: today.date))
                        .font(.subheadline.weight(.semibold))
                        .foregroundStyle(.primary)
                }

                Spacer()
            }
            .frame(maxWidth: .infinity, maxHeight: .infinity)
        }
    }
}

// MARK: - Medium Widget View

struct MediumWidgetView: View {
    var entry: Provider.Entry
    var timeLineView = [WatchTimelineView]()

    private var showVotingForToday: Bool {
        !entry.hasVotedToday
    }

    private var dayFormatter: DateFormatter {
        let f = DateFormatter()
        f.dateFormat = "EEE"
        return f
    }

    private var dateFormatter: DateFormatter {
        let f = DateFormatter()
        f.dateFormat = "d"
        return f
    }

    init(entry: Provider.Entry) {
        self.entry = entry
        let realData = Array(TimeLineCreator.createViews(daysBack: 6).prefix(5))
        let hasRealData = realData.contains { view in
            let moodTint: MoodTintable.Type = UserDefaultsStore.moodTintable()
            return view.color != moodTint.color(forMood: .missing)
        }
        timeLineView = hasRealData ? realData : TimeLineCreator.createSampleViews(count: 5)
    }

    private var headerDateRange: String {
        guard let first = timeLineView.first, let last = timeLineView.last else { return "" }
        let formatter = DateFormatter()
        formatter.dateFormat = "MMM d"
        return "\(formatter.string(from: last.date)) - \(formatter.string(from: first.date))"
    }

    var body: some View {
        if showVotingForToday {
            // Show interactive voting buttons (or open app links if expired)
            VotingView(family: .systemMedium, promptText: entry.promptText, hasSubscription: entry.hasSubscription)
        } else {
            GeometryReader { geo in
                let cellHeight = geo.size.height - 36

                VStack(spacing: 4) {
                    // Header
                    HStack {
                        Text("Last 5 Days")
                            .font(.subheadline.weight(.semibold))
                            .foregroundStyle(.primary)
                        Text("·")
                            .foregroundStyle(.secondary)
                        Text(headerDateRange)
                            .font(.caption)
                            .foregroundStyle(.secondary)
                        Spacer()
                    }
                    .padding(.horizontal, 14)
                    .padding(.top, 10)

                    // Single row of 5 days
                    HStack(spacing: 8) {
                        ForEach(Array(timeLineView.enumerated()), id: \.element.id) { index, item in
                            MediumDayCell(
                                dayLabel: dayFormatter.string(from: item.date),
                                dateLabel: dateFormatter.string(from: item.date),
                                image: item.image,
                                color: item.color,
                                isToday: index == 0,
                                height: cellHeight,
                                mood: item.mood
                            )
                        }
                    }
                    .padding(.horizontal, 10)
                    .padding(.bottom, 10)
                }
            }
        }
    }
}

// MARK: - Medium Day Cell

struct MediumDayCell: View {
    let dayLabel: String
    let dateLabel: String
    let image: Image
    let color: Color
    let isToday: Bool
    let height: CGFloat
    let mood: Mood

    var body: some View {
        ZStack {
            RoundedRectangle(cornerRadius: 14)
                .fill(color.opacity(isToday ? 0.25 : 0.12))
                .frame(height: height)

            VStack(spacing: 4) {
                Text(dayLabel)
                    .font(.caption2.weight(isToday ? .bold : .medium))
                    .foregroundStyle(isToday ? .primary : .secondary)
                    .textCase(.uppercase)

                image
                    .resizable()
                    .aspectRatio(contentMode: .fit)
                    .frame(width: 36, height: 36)
                    .foregroundColor(color)
                    .accessibilityLabel(mood.strValue)

                Text(dateLabel)
                    .font(.caption.weight(isToday ? .bold : .semibold))
                    .foregroundStyle(isToday ? color : .secondary)
            }
        }
        .frame(maxWidth: .infinity)
    }
}

// MARK: - Large Widget View

struct LargeWidgetView: View {
    var entry: Provider.Entry
    var timeLineView = [WatchTimelineView]()

    private var showVotingForToday: Bool {
        !entry.hasVotedToday
    }

    init(entry: Provider.Entry) {
        self.entry = entry
        let realData = Array(TimeLineCreator.createViews(daysBack: 11).prefix(10))
        let hasRealData = realData.contains { view in
            let moodTint: MoodTintable.Type = UserDefaultsStore.moodTintable()
            return view.color != moodTint.color(forMood: .missing)
        }
        timeLineView = hasRealData ? realData : TimeLineCreator.createSampleViews(count: 10)
    }

    private var dayFormatter: DateFormatter {
        let f = DateFormatter()
        f.dateFormat = "EEE"
        return f
    }

    private var dateFormatter: DateFormatter {
        let f = DateFormatter()
        f.dateFormat = "d"
        return f
    }

    var body: some View {
        if showVotingForToday {
            // Show interactive voting buttons for large widget (or open app links if expired)
            LargeVotingView(promptText: entry.promptText, hasSubscription: entry.hasSubscription)
        } else {
            GeometryReader { geo in
                let cellHeight = (geo.size.height - 70) / 2 // Subtract header height, divide by 2 rows

                VStack(spacing: 6) {
                    // Header
                    HStack {
                        VStack(alignment: .leading, spacing: 2) {
                            Text("Last 10 Days")
                                .font(.subheadline.weight(.semibold))
                                .foregroundStyle(.primary)
                            Text(headerDateRange)
                                .font(.caption2)
                                .foregroundStyle(.secondary)
                        }
                        Spacer()
                    }
                    .padding(.horizontal, 12)
                    .padding(.top, 8)

                    // Calendar grid - 2 rows of 5
                    VStack(spacing: 6) {
                        // First row (most recent 5)
                        HStack(spacing: 6) {
                            ForEach(Array(timeLineView.prefix(5).enumerated()), id: \.element.id) { index, item in
                                DayCell(
                                    dayLabel: dayFormatter.string(from: item.date),
                                    dateLabel: dateFormatter.string(from: item.date),
                                    image: item.image,
                                    color: item.color,
                                    isToday: index == 0,
                                    height: cellHeight,
                                    mood: item.mood
                                )
                            }
                        }

                        // Second row (older 5)
                        HStack(spacing: 6) {
                            ForEach(Array(timeLineView.suffix(5).enumerated()), id: \.element.id) { _, item in
                                DayCell(
                                    dayLabel: dayFormatter.string(from: item.date),
                                    dateLabel: dateFormatter.string(from: item.date),
                                    image: item.image,
                                    color: item.color,
                                    isToday: false,
                                    height: cellHeight,
                                    mood: item.mood
                                )
                            }
                        }
                    }
                    .padding(.horizontal, 10)
                    .padding(.bottom, 8)
                }
            }
        }
    }

    private var headerDateRange: String {
        guard let first = timeLineView.first, let last = timeLineView.last else { return "" }
        let formatter = DateFormatter()
        formatter.dateFormat = "MMM d"
        return "\(formatter.string(from: last.date)) - \(formatter.string(from: first.date))"
    }
}

// MARK: - Day Cell for Large Widget

struct DayCell: View {
    let dayLabel: String
    let dateLabel: String
    let image: Image
    let color: Color
    let isToday: Bool
    let height: CGFloat
    let mood: Mood

    var body: some View {
        VStack(spacing: 2) {
            Text(dayLabel)
                .font(.caption2.weight(isToday ? .bold : .medium))
                .foregroundStyle(isToday ? .primary : .secondary)
                .textCase(.uppercase)

            ZStack {
                RoundedRectangle(cornerRadius: 14)
                    .fill(color.opacity(isToday ? 0.25 : 0.12))
                    .frame(height: height - 16)

                VStack(spacing: 6) {
                    image
                        .resizable()
                        .aspectRatio(contentMode: .fit)
                        .frame(width: 38, height: 38)
                        .foregroundColor(color)
                        .accessibilityLabel(mood.strValue)

                    Text(dateLabel)
                        .font(.caption.weight(isToday ? .bold : .semibold))
                        .foregroundStyle(isToday ? color : .secondary)
                }
            }
        }
        .frame(maxWidth: .infinity)
    }
}

// MARK: - Supporting Views

struct TimeHeaderView: View {
    let startDate: Date
    let endDate: Date

    var formatter: DateFormatter {
        let dateFormatter = DateFormatter()
        dateFormatter.dateStyle = .medium
        return dateFormatter
    }

    var body: some View {
        HStack {
            Text(startDate, formatter: formatter)
                .font(.system(.footnote))
            Text(" - ")
                .font(.system(.footnote))
            Text(endDate, formatter: formatter)
                .font(.system(.footnote))
        }
    }
}

struct TimeBodyView: View {
    let group: [WatchTimelineView]
    var showVotingForToday: Bool = false
    var promptText: String = ""
    var hasSubscription: Bool = false

    var body: some View {
        if showVotingForToday {
            // Show voting view without extra background container
            InlineVotingView(promptText: promptText, hasSubscription: hasSubscription)
                .padding()
        } else {
            ZStack {
                Color(UIColor.secondarySystemBackground)
                HStack(spacing: 4) {
                    ForEach(group) { watchView in
                        EntryCard(timeLineView: watchView)
                    }
                }
                .padding()
            }
        }
    }
}

struct EntryCard: View {
    var timeLineView: WatchTimelineView

    var body: some View {
        timeLineView.image
            .resizable()
            .aspectRatio(contentMode: .fit)
            .frame(width: 50, height: 50, alignment: .center)
            .foregroundColor(timeLineView.color)
            .accessibilityLabel(timeLineView.mood.strValue)
    }
}

// MARK: - Preview Helpers

private enum WidgetPreviewHelpers {
    static func sampleTimelineViews(count: Int, startMood: Mood = .great) -> [WatchTimelineView] {
        let moods: [Mood] = [.great, .good, .average, .bad, .horrible]
        let startIndex = moods.firstIndex(of: startMood) ?? 0
        return (0..<count).map { index in
            let mood = moods[(startIndex + index) % moods.count]
            return WatchTimelineView(
                image: EmojiMoodImages.icon(forMood: mood),
                graphic: EmojiMoodImages.icon(forMood: mood),
                date: Calendar.current.date(byAdding: .day, value: -index, to: Date())!,
                color: MoodTints.Default.color(forMood: mood),
                secondaryColor: MoodTints.Default.secondary(forMood: mood),
                mood: mood
            )
        }
    }

    static func sampleEntry(timelineCount: Int = 5, hasVotedToday: Bool = true, hasSubscription: Bool = true, startMood: Mood = .great) -> SimpleEntry {
        SimpleEntry(
            date: Date(),
            configuration: ConfigurationIntent(),
            timeLineViews: sampleTimelineViews(count: timelineCount, startMood: startMood),
            hasSubscription: hasSubscription,
            hasVotedToday: hasVotedToday,
            promptText: "How are you feeling today?"
        )
    }
}

// MARK: - Previews

// Small - Logged States
#Preview("Timeline Small - Great", as: .systemSmall) {
    ReflectWidget()
} timeline: {
    WidgetPreviewHelpers.sampleEntry(timelineCount: 1, startMood: .great)
}

#Preview("Timeline Small - Good", as: .systemSmall) {
    ReflectWidget()
} timeline: {
    WidgetPreviewHelpers.sampleEntry(timelineCount: 1, startMood: .good)
}

#Preview("Timeline Small - Average", as: .systemSmall) {
    ReflectWidget()
} timeline: {
    WidgetPreviewHelpers.sampleEntry(timelineCount: 1, startMood: .average)
}

#Preview("Timeline Small - Bad", as: .systemSmall) {
    ReflectWidget()
} timeline: {
    WidgetPreviewHelpers.sampleEntry(timelineCount: 1, startMood: .bad)
}

#Preview("Timeline Small - Horrible", as: .systemSmall) {
    ReflectWidget()
} timeline: {
    WidgetPreviewHelpers.sampleEntry(timelineCount: 1, startMood: .horrible)
}

// Small - Voting States
#Preview("Timeline Small - Voting", as: .systemSmall) {
    ReflectWidget()
} timeline: {
    WidgetPreviewHelpers.sampleEntry(timelineCount: 1, hasVotedToday: false)
}

#Preview("Timeline Small - Non-Subscriber", as: .systemSmall) {
    ReflectWidget()
} timeline: {
    WidgetPreviewHelpers.sampleEntry(timelineCount: 1, hasVotedToday: false, hasSubscription: false)
}

// Medium - Logged States
#Preview("Timeline Medium - Logged", as: .systemMedium) {
    ReflectWidget()
} timeline: {
    WidgetPreviewHelpers.sampleEntry(timelineCount: 5)
}

// Medium - Voting States
#Preview("Timeline Medium - Voting", as: .systemMedium) {
    ReflectWidget()
} timeline: {
    WidgetPreviewHelpers.sampleEntry(timelineCount: 5, hasVotedToday: false)
}

#Preview("Timeline Medium - Non-Subscriber", as: .systemMedium) {
    ReflectWidget()
} timeline: {
    WidgetPreviewHelpers.sampleEntry(timelineCount: 5, hasVotedToday: false, hasSubscription: false)
}

// Large - Logged States
#Preview("Timeline Large - Logged", as: .systemLarge) {
    ReflectWidget()
} timeline: {
    WidgetPreviewHelpers.sampleEntry(timelineCount: 10)
}

// Large - Voting States
#Preview("Timeline Large - Voting", as: .systemLarge) {
    ReflectWidget()
} timeline: {
    WidgetPreviewHelpers.sampleEntry(timelineCount: 10, hasVotedToday: false)
}

#Preview("Timeline Large - Non-Subscriber", as: .systemLarge) {
    ReflectWidget()
} timeline: {
    WidgetPreviewHelpers.sampleEntry(timelineCount: 10, hasVotedToday: false, hasSubscription: false)
}
