import HealthKit
import LoopKit
import LoopKitUI
import SwiftUI
import Swinject
import UIKit

extension Settings {
    struct VersionInfo: Equatable {
        var latestVersion: String?
        var isUpdateAvailable: Bool
        var isBlacklisted: Bool
        var latestDevVersion: String?
        var isDevUpdateAvailable: Bool
    }

    struct RootView: BaseView {
        let resolver: Resolver
        @StateObject var state = StateModel()

        @State private var showShareSheet = false
        @State private var searchText: String = ""

        @State private var shouldDisplayHint: Bool = false
        @State var hintDetent = PresentationDetent.large
        @State var selectedVerboseHint: AnyView?
        @State var hintLabel: String?
        @State private var decimalPlaceholder: Decimal = 0.0
        @State private var booleanPlaceholder: Bool = false
        @State private var versionInfo = VersionInfo(
            latestVersion: nil,
            isUpdateAvailable: false,
            isBlacklisted: false,
            latestDevVersion: nil,
            isDevUpdateAvailable: false
        )
        @State private var closedLoopDisabled = true
        @State private var showCopiedToast = false

        @Environment(\.colorScheme) var colorScheme
        @EnvironmentObject var appIcons: Icons
        @Environment(AppState.self) var appState
        @Environment(SettingsSearchHighlight.self) var searchHighlight

        private var filteredItems: [FilteredSettingItem] {
            SettingItems.filteredItems(searchText: searchText)
        }

        @ViewBuilder var versionInfoView: some View {
            VStack(alignment: .leading, spacing: 4) {
                // Main version info
                if let version = versionInfo.latestVersion {
                    let updateColor: Color = versionInfo.isUpdateAvailable ? .orange : .green
                    let versionIconName = versionInfo
                        .isUpdateAvailable ? "exclamationmark.triangle.fill" : "checkmark.circle.fill"

                    HStack {
                        Text("Latest version: \(version)")
                            .font(.footnote)
                            .foregroundColor(updateColor)
                        Image(systemName: versionIconName)
                            .foregroundColor(updateColor)
                    }
                    if versionInfo.isBlacklisted {
                        HStack {
                            Text("Warning: Known issues. Update now.")
                                .font(.footnote)
                                .foregroundColor(.red)
                            Image(systemName: "exclamationmark.octagon.fill")
                                .foregroundColor(.red)
                        }
                    }
                } else {
                    Text("Latest version: Fetching...")
                        .font(.footnote)
                        .foregroundColor(.secondary)
                }

                // Show latest dev version on any branch except main
                let buildDetails = BuildDetails.shared
                if buildDetails.trioBranch != "main" {
                    if let devVersion = versionInfo.latestDevVersion {
                        let devUpdateColor: Color = versionInfo.isDevUpdateAvailable ? .orange : .secondary
                        let devVersionIconName = versionInfo.isDevUpdateAvailable ? "arrow.up.circle.fill" : "hammer.fill"

                        HStack {
                            Text("Latest dev: \(devVersion)")
                                .font(.footnote)
                                .foregroundColor(devUpdateColor)
                            Image(systemName: devVersionIconName)
                                .font(.footnote)
                                .foregroundColor(devUpdateColor)
                        }
                    } else {
                        Text("Latest dev: Fetching...")
                            .font(.footnote)
                            .foregroundColor(.secondary)
                    }
                }
            }
        }

        private func copyVersionInfo(_ text: String) {
            UIPasteboard.general.string = text
            UINotificationFeedbackGenerator().notificationOccurred(.success)
            withAnimation { showCopiedToast = true }
            DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) {
                withAnimation { showCopiedToast = false }
            }
        }

        var body: some View {
            List {
                if searchText.isEmpty {
                    let buildDetails = BuildDetails.shared

                    /// The current development version of the app.
                    ///
                    /// Follows a semantic pattern where release versions are like `0.5.0`, and
                    /// development versions increment with a fourth component (e.g., `0.5.0.1`, `0.5.0.2`)
                    /// after the base release. For example:
                    /// - After release `0.5.0` → `0.5.0`
                    /// - First dev push → `0.5.0.1`
                    /// - Next dev push → `0.5.0.2`
                    /// - Next release `0.6.0` → `0.6.0`
                    /// - Next dev push → `0.6.0.1`
                    ///
                    /// If the dev version is unavailable, `"unknown"` is returned.
                    let devVersion = Bundle.main.appDevVersion ?? "unknown"

                    let buildNumber = Bundle.main.buildVersionNumber ?? String(localized: "Unknown")

                    Section(
                        header: HStack(spacing: 4) {
                            Button {
                                copyVersionInfo(
                                    "Trio v\(devVersion) (\(buildNumber)) \(buildDetails.branchAndSha)"
                                )
                            } label: {
                                Image(systemName: "doc.on.doc.fill")
                            }
                            .buttonStyle(.plain)
                            Text("BRANCH: \(buildDetails.branchAndSha)")
                        }.textCase(nil),
                        content: {
                            NavigationLink(destination: SubmodulesView(buildDetails: buildDetails)) {
                                HStack {
                                    Image(appIcons.appIcon.rawValue)
                                        .resizable()
                                        .aspectRatio(contentMode: .fit)
                                        .frame(width: 50, height: 50)
                                        .cornerRadius(10)
                                        .padding(.trailing, 10)
                                    VStack(alignment: .leading, spacing: 4) {
                                        Text("Trio v\(devVersion) (\(buildNumber))")
                                            .font(.headline)
                                        if let expirationDate = buildDetails.calculateExpirationDate() {
                                            let formattedDate = DateFormatter.localizedString(
                                                from: expirationDate,
                                                dateStyle: .medium,
                                                timeStyle: .none
                                            )
                                            Text("\(buildDetails.expirationHeaderString): \(formattedDate)")
                                                .font(.footnote)
                                                .foregroundColor(.secondary)
                                        } else {
                                            Text("Simulator Build has no expiry")
                                                .font(.footnote)
                                                .foregroundColor(.secondary)
                                        }

                                        versionInfoView
                                    }
                                }
                            }
                        }
                    ).listRowBackground(Color.chart)

                    let miniHintText = closedLoopDisabled ?
                        String(localized: "Add a CGM and pump to enable automated insulin delivery") :
                        String(localized: "Enable automated insulin delivery.")
                    let miniHintTextColorForDisabled: Color = colorScheme == .dark ? .orange : .accentColor
                    let miniHintTextColor: Color = closedLoopDisabled ? miniHintTextColorForDisabled : .secondary
                    SettingInputSection(
                        decimalValue: $decimalPlaceholder,
                        booleanValue: $state.closedLoop,
                        shouldDisplayHint: $shouldDisplayHint,
                        selectedVerboseHint: Binding(
                            get: { selectedVerboseHint },
                            set: {
                                selectedVerboseHint = $0.map { AnyView($0) }
                                hintLabel = String(localized: "Closed Loop")
                            }
                        ),
                        units: state.units,
                        type: .boolean,
                        label: String(localized: "Closed Loop"),
                        miniHint: miniHintText,
                        verboseHint: VStack(alignment: .leading, spacing: 10) {
                            Text(
                                "Running Trio in closed loop mode requires an active CGM sensor session and a connected pump. This enables automated insulin delivery."
                            )
                            Text(
                                "Before enabling, dial in your settings (basal / insulin sensitivity / carb ratio), and familiarize yourself with the app."
                            )
                        },
                        headerText: String(localized: "Automated Insulin Delivery"),
                        isToggleDisabled: closedLoopDisabled,
                        miniHintColor: miniHintTextColor
                    )
                    .onAppear {
                        closedLoopDisabled = !state.hasCgmAndPump()
                    }

                    Section(
                        header: Text("Trio Configuration"),
                        content: {
                            ForEach(SettingItems.trioConfig) { item in
                                Text(LocalizedStringKey(item.title)).navigationLink(to: item.view, from: self)
                            }
                        }
                    )
                    .listRowBackground(Color.chart)

                    Section(
                        header: Text("Support & Community"),
                        content: {
                            Button {
                                showShareSheet.toggle()
                            } label: {
                                HStack {
                                    Text("Share Logs")
                                        .foregroundColor(.primary)
                                    Spacer()
                                    Image(systemName: "chevron.right")
                                        .foregroundColor(.secondary)
                                        .font(.footnote)
                                }
                            }
                            .frame(maxWidth: .infinity, alignment: .leading)

                            Button {
                                if let url = URL(string: "https://github.com/nightscout/Trio/issues/new/choose") {
                                    UIApplication.shared.open(url)
                                }
                            } label: {
                                HStack {
                                    Text("Submit Ticket on GitHub")
                                        .foregroundColor(.primary)
                                    Spacer()
                                    Image(systemName: "chevron.right")
                                        .foregroundColor(.secondary)
                                        .font(.footnote)
                                }
                            }
                            .frame(maxWidth: .infinity, alignment: .leading)

                            Button {
                                if let url = URL(string: "https://discord.triodocs.org") {
                                    UIApplication.shared.open(url)
                                }
                            } label: {
                                HStack {
                                    Text("Trio Discord")
                                        .foregroundColor(.primary)
                                    Spacer()
                                    Image(systemName: "chevron.right")
                                        .foregroundColor(.secondary)
                                        .font(.footnote)
                                }
                            }
                            .frame(maxWidth: .infinity, alignment: .leading)

                            Button {
                                if let url = URL(string: "https://facebook.triodocs.org") {
                                    UIApplication.shared.open(url)
                                }
                            } label: {
                                HStack {
                                    Text("Trio Facebook")
                                        .foregroundColor(.primary)
                                    Spacer()
                                    Image(systemName: "chevron.right")
                                        .foregroundColor(.secondary)
                                        .font(.footnote)
                                }
                            }
                            .frame(maxWidth: .infinity, alignment: .leading)
                        }
                    ).listRowBackground(Color.chart)

                    Section(
                        header: Text("Trio Backup"),
                        content: {
                            Text(String(
                                localized: "Export Settings",
                                comment: "Export Settings menu item in Trio Settings Root View"
                            ))
                                .navigationLink(to: .settingsExport, from: self)
                        }
                    ).listRowBackground(Color.chart)

                } else {
                    Section(
                        header: Text("Search Results"),
                        content: {
                            if filteredItems.isNotEmpty {
                                ForEach(filteredItems) { filteredItem in
                                    NavigationLink(value: SearchResultTarget(
                                        screen: filteredItem.settingItem.view,
                                        scrollLabel: filteredItem.scrollLabel.localized
                                    )) {
                                        VStack(alignment: .leading) {
                                            Text(filteredItem.matchedContent.localized).bold()
                                            if let path = filteredItem.settingItem.path {
                                                Text(path.map(\.localized).joined(separator: " > "))
                                                    .font(.caption)
                                                    .foregroundColor(.secondary)
                                            }
                                        }
                                    }
                                }
                            } else {
                                Text("No settings matching your search query")
                                    +
                                    Text(" »\(searchText)« ").bold()
                                    +
                                    Text("found.")
                            }
                        }
                    ).listRowBackground(Color.chart)
                }
            }
            .overlay(alignment: .bottom) {
                if showCopiedToast {
                    Label("Copied", systemImage: "checkmark.circle.fill")
                        .font(.footnote.weight(.semibold))
                        .foregroundColor(.white)
                        .padding(.horizontal, 16)
                        .padding(.vertical, 10)
                        .background(.ultraThinMaterial, in: Capsule())
                        .padding(.bottom, 32)
                        .transition(.move(edge: .bottom).combined(with: .opacity))
                }
            }
            .scrollContentBackground(.hidden).background(appState.trioBackgroundColor(for: colorScheme))
            .sheet(isPresented: $shouldDisplayHint) {
                SettingInputHintView(
                    hintDetent: $hintDetent,
                    shouldDisplayHint: $shouldDisplayHint,
                    hintLabel: hintLabel ?? "",
                    hintText: selectedVerboseHint ?? AnyView(EmptyView()),
                    sheetTitle: String(localized: "Help", comment: "Help sheet title")
                )
            }
            .sheet(isPresented: $showShareSheet) {
                ShareSheet(activityItems: state.logItems())
            }
            .onAppear(perform: configureView)
            .navigationTitle("Settings")
            .navigationBarTitleDisplayMode(.automatic)
            .toolbar {
                ToolbarItem(placement: .topBarTrailing) {
                    Button(
                        action: {
                            if let url = URL(string: "https://triodocs.org/") {
                                UIApplication.shared.open(url)
                            }
                        },
                        label: {
                            HStack {
                                Text("Trio Docs")
                                Image(systemName: "questionmark.circle")
                            }
                        }
                    )
                }
            }
            .searchable(text: $searchText, placement: .navigationBarDrawer(displayMode: .always))
            .navigationDestination(for: SearchResultTarget.self) { target in
                state.view(for: target.screen)
                    .onAppear {
                        searchHighlight.highlightedSetting = target.scrollLabel
                    }
            }
            .screenNavigation(self)
            .onAppear {
                Task { @MainActor in
                    let (_, latestVersion, isNewer, isBlacklisted) = await AppVersionChecker.shared.refreshVersionInfo()
                    versionInfo.latestVersion = latestVersion
                    versionInfo.isUpdateAvailable = isNewer
                    versionInfo.isBlacklisted = isBlacklisted

                    // Fetch dev version if not on main branch
                    let buildDetails = BuildDetails.shared
                    if buildDetails.trioBranch != "main" {
                        let (devVersion, isDevNewer) = await AppVersionChecker.shared.checkForNewDevVersion()
                        versionInfo.latestDevVersion = devVersion
                        versionInfo.isDevUpdateAvailable = isDevNewer
                    }
                }
            }
        }
    }
}
