import ActivityKit
import SwiftUI
import WidgetKit

struct LiveActivity: Widget {
    var body: some WidgetConfiguration {
        let configuration = ActivityConfiguration(for: LiveActivityAttributes.self) { context in
            LiveActivityView(context: context)
                .addIsWatchOS()
        } dynamicIsland: { context in
            let hasStaticColorScheme = context.state.glucoseColorScheme == "staticColor"

            var glucoseColor: Color {
                let state = context.state
                let isMgdL = state.unit == "mg/dL"

                // TODO: workaround for now: set low value to 55, to have dynamic color shades between 55 and user-set low (approx. 70); same for high glucose
                let hardCodedLow = isMgdL ? Decimal(55) : 55.asMmolL
                let hardCodedHigh = isMgdL ? Decimal(220) : 220.asMmolL

                return Color.getDynamicGlucoseColor(
                    glucoseValue: Decimal(string: state.bg) ?? 100,
                    highGlucoseColorValue: !hasStaticColorScheme
                        ? hardCodedHigh : state.highGlucose,
                    lowGlucoseColorValue: !hasStaticColorScheme
                        ? hardCodedLow : state.lowGlucose,
                    targetGlucose: isMgdL ? state.target : state.target.asMmolL,
                    glucoseColorScheme: state.glucoseColorScheme
                )
            }

            return DynamicIsland {
                DynamicIslandExpandedRegion(.leading) {
                    LiveActivityExpandedLeadingView(
                        context: context,
                        glucoseColor: glucoseColor
                    )
                }
                DynamicIslandExpandedRegion(.trailing) {
                    LiveActivityExpandedTrailingView(
                        context: context,
                        glucoseColor: hasStaticColorScheme ? .primary : glucoseColor
                    )
                }
                DynamicIslandExpandedRegion(.bottom) {
                    LiveActivityExpandedBottomView(context: context)
                }
                DynamicIslandExpandedRegion(.center) {
                    LiveActivityExpandedCenterView(context: context)
                }
            } compactLeading: {
                LiveActivityCompactLeadingView(
                    context: context,
                    glucoseColor: glucoseColor
                )
            } compactTrailing: {
                LiveActivityCompactTrailingView(
                    context: context,
                    glucoseColor: hasStaticColorScheme ? .primary : glucoseColor
                )
            } minimal: {
                LiveActivityMinimalView(
                    context: context,
                    glucoseColor: glucoseColor
                )
            }
            .widgetURL(URL(string: "Trio://"))
            .keylineTint(glucoseColor)
            .contentMargins(.horizontal, 0, for: .minimal)
            .contentMargins(.trailing, 0, for: .compactLeading)
            .contentMargins(.leading, 0, for: .compactTrailing)
        }

        if #available(iOS 18.0, *) {
            return configuration.supplementalActivityFamilies([.small])
        } else {
            return configuration
        }
    }
}

// Mock structure to replace GlucoseData
struct MockGlucoseData {
    var glucose: Int
    var date: Date
    var direction: String? // You can refine this based on your expected data
}

private extension LiveActivityAttributes {
    static var preview: LiveActivityAttributes {
        LiveActivityAttributes(startDate: Date())
    }
}

private extension LiveActivityAttributes.ContentState {
    static var chartData: [MockGlucoseData] = [
        MockGlucoseData(
            glucose: 120,
            date: Date().addingTimeInterval(-600),
            direction: "flat"
        ),
        MockGlucoseData(
            glucose: 125,
            date: Date().addingTimeInterval(-300),
            direction: "flat"
        ),
        MockGlucoseData(glucose: 130, date: Date(), direction: "flat")
    ]

    static var detailedViewState =
        LiveActivityAttributes.ContentAdditionalState(
            chart: chartData.map {
                LiveActivityAttributes.ChartItem(value: Decimal($0.glucose), date: $0.date)
            },
            rotationDegrees: 0,
            cob: 20,
            iob: 1.5,
            tdd: 43.21,
            isOverrideActive: false,
            overrideName: "Exercise",
            overrideDate: Date().addingTimeInterval(-3600),
            overrideDuration: 120,
            overrideTarget: 150,
            widgetItems: LiveActivityAttributes.LiveActivityItem.defaultItems
        )

    // 0 is the widest digit. Use this to get an upper bound on text width.

    // Use mmol/l notation with decimal point as well for the same reason, it uses up to 4 characters, while mg/dl uses up to 3
    static var testWide: LiveActivityAttributes.ContentState {
        LiveActivityAttributes.ContentState(
            unit: "mg/dL",
            bg: "00.0",
            direction: "→",
            change: "+0.0",
            date: Date(),
            highGlucose: 180,
            lowGlucose: 70,
            target: 100,
            glucoseColorScheme: "staticColor",
            useDetailedViewIOS: false,
            useDetailedViewWatchOS: false,
            detailedViewState: detailedViewState,
            isInitialState: false
        )
    }

    static var testVeryWide: LiveActivityAttributes.ContentState {
        LiveActivityAttributes.ContentState(
            unit: "mg/dL",
            bg: "00.0",
            direction: "↑↑",
            change: "+0.0",
            date: Date(),
            highGlucose: 180,
            lowGlucose: 70,
            target: 100,
            glucoseColorScheme: "staticColor",
            useDetailedViewIOS: false,
            useDetailedViewWatchOS: false,
            detailedViewState: detailedViewState,
            isInitialState: false
        )
    }

    static var testSuperWide: LiveActivityAttributes.ContentState {
        LiveActivityAttributes.ContentState(
            unit: "mg/dL",
            bg: "00.0",
            direction: "↑↑↑",
            change: "+0.0",
            date: Date(),
            highGlucose: 180,
            lowGlucose: 70,
            target: 100,
            glucoseColorScheme: "staticColor",
            useDetailedViewIOS: false,
            useDetailedViewWatchOS: false,
            detailedViewState: detailedViewState,
            isInitialState: false
        )
    }

    // 2 characters for BG, 1 character for change is the minimum that will be shown
    static var testNarrow: LiveActivityAttributes.ContentState {
        LiveActivityAttributes.ContentState(
            unit: "mg/dL",
            bg: "00",
            direction: "↑",
            change: "+0",
            date: Date(),
            highGlucose: 180,
            lowGlucose: 70,
            target: 100,
            glucoseColorScheme: "staticColor",
            useDetailedViewIOS: false,
            useDetailedViewWatchOS: false,
            detailedViewState: detailedViewState,
            isInitialState: false
        )
    }

    static var testMedium: LiveActivityAttributes.ContentState {
        LiveActivityAttributes.ContentState(
            unit: "mg/dL",
            bg: "000",
            direction: "↗︎",
            change: "+00",
            date: Date(),
            highGlucose: 180,
            lowGlucose: 70,
            target: 100,
            glucoseColorScheme: "staticColor",
            useDetailedViewIOS: false,
            useDetailedViewWatchOS: false,
            detailedViewState: detailedViewState,
            isInitialState: false
        )
    }

    static var testExpired: LiveActivityAttributes.ContentState {
        LiveActivityAttributes.ContentState(
            unit: "mg/dL",
            bg: "--",
            direction: nil,
            change: "--",
            date: Date().addingTimeInterval(-60 * 60),
            highGlucose: 180,
            lowGlucose: 70,
            target: 100,
            glucoseColorScheme: "staticColor",
            useDetailedViewIOS: false,
            useDetailedViewWatchOS: false,
            detailedViewState: detailedViewState,
            isInitialState: false
        )
    }

    static var testWideDetailed: LiveActivityAttributes.ContentState
    {
        LiveActivityAttributes.ContentState(
            unit: "mg/dL",
            bg: "00.0",
            direction: "→",
            change: "+0.0",
            date: Date(),
            highGlucose: 180,
            lowGlucose: 70,
            target: 100,
            glucoseColorScheme: "staticColor",
            useDetailedViewIOS: true,
            useDetailedViewWatchOS: true,
            detailedViewState: detailedViewState,
            isInitialState: false
        )
    }

    static var testVeryWideDetailed:
        LiveActivityAttributes.ContentState
    {
        LiveActivityAttributes.ContentState(
            unit: "mg/dL",
            bg: "00.0",
            direction: "↑↑",
            change: "+0.0",
            date: Date(),
            highGlucose: 180,
            lowGlucose: 70,
            target: 100,
            glucoseColorScheme: "staticColor",
            useDetailedViewIOS: true,
            useDetailedViewWatchOS: true,
            detailedViewState: detailedViewState,
            isInitialState: false
        )
    }

    static var testSuperWideDetailed:
        LiveActivityAttributes.ContentState
    {
        LiveActivityAttributes.ContentState(
            unit: "mg/dL",
            bg: "00.0",
            direction: "↑↑↑",
            change: "+0.0",
            date: Date(),
            highGlucose: 180,
            lowGlucose: 70,
            target: 100,
            glucoseColorScheme: "staticColor",
            useDetailedViewIOS: true,
            useDetailedViewWatchOS: true,
            detailedViewState: detailedViewState,
            isInitialState: false
        )
    }

    // 2 characters for BG, 1 character for change is the minimum that will be shown
    static var testNarrowDetailed:
        LiveActivityAttributes.ContentState
    {
        LiveActivityAttributes.ContentState(
            unit: "mg/dL",
            bg: "00",
            direction: "↑",
            change: "+0",
            date: Date(),
            highGlucose: 180,
            lowGlucose: 70,
            target: 100,
            glucoseColorScheme: "staticColor",
            useDetailedViewIOS: true,
            useDetailedViewWatchOS: true,
            detailedViewState: detailedViewState,
            isInitialState: false
        )
    }

    static var testMediumDetailed:
        LiveActivityAttributes.ContentState
    {
        LiveActivityAttributes.ContentState(
            unit: "mg/dL",
            bg: "000",
            direction: "↗︎",
            change: "+00",
            date: Date(),
            highGlucose: 180,
            lowGlucose: 70,
            target: 100,
            glucoseColorScheme: "staticColor",
            useDetailedViewIOS: true,
            useDetailedViewWatchOS: true,
            detailedViewState: detailedViewState,
            isInitialState: false
        )
    }

    static var testExpiredDetailed:
        LiveActivityAttributes.ContentState
    {
        LiveActivityAttributes.ContentState(
            unit: "mg/dL",
            bg: "--",
            direction: nil,
            change: "--",
            date: Date().addingTimeInterval(-60 * 60),
            highGlucose: 180,
            lowGlucose: 70,
            target: 100,
            glucoseColorScheme: "staticColor",
            useDetailedViewIOS: true,
            useDetailedViewWatchOS: true,
            detailedViewState: detailedViewState,
            isInitialState: false
        )
    }
}

@available(iOS 17.0, iOSApplicationExtension 17.0, *)
#Preview("Simple", as: .content, using: LiveActivityAttributes.preview) {
    LiveActivity()
} contentStates: {
    LiveActivityAttributes.ContentState.testSuperWide
    LiveActivityAttributes.ContentState.testVeryWide
    LiveActivityAttributes.ContentState.testWide
    LiveActivityAttributes.ContentState.testMedium
    LiveActivityAttributes.ContentState.testNarrow
    LiveActivityAttributes.ContentState.testExpired
}

@available(iOS 17.0, iOSApplicationExtension 17.0, *)
#Preview("Detailed", as: .content, using: LiveActivityAttributes.preview) {
    LiveActivity()
} contentStates: {
    LiveActivityAttributes.ContentState.testSuperWideDetailed
    LiveActivityAttributes.ContentState.testVeryWideDetailed
    LiveActivityAttributes.ContentState.testWideDetailed
    LiveActivityAttributes.ContentState.testMediumDetailed
    LiveActivityAttributes.ContentState.testNarrowDetailed
    LiveActivityAttributes.ContentState.testExpiredDetailed
}
