import SwiftUI
import Charts
import CoreData

struct DashboardView: View {
    @EnvironmentObject var iapService: IAPService
    @EnvironmentObject var accountStore: AccountStore
    @StateObject private var viewModel: DashboardViewModel
    @StateObject private var goalsViewModel = GoalsViewModel()
    @State private var showingImport = false
    @State private var showingAddSource = false
    @State private var showingCustomize = false
    @State private var sectionConfigs = DashboardLayoutStore.load()
    @AppStorage("showForecast") private var showForecast = true
    @State private var pendingAlertDismissed = false
    @State private var fullScreenSection: DashboardSection? = nil
    @State private var dragTargetID: String? = nil
    @State private var showingQuickUpdate = false
    @Environment(\.horizontalSizeClass) private var horizontalSizeClass

    init() {
        _viewModel = StateObject(wrappedValue: DashboardViewModel())
    }

    var body: some View {
        NavigationStack {
            ZStack {
                AppBackground()

                ScrollView {
                    VStack(spacing: 20) {
                        if viewModel.updateStreak >= 2 {
                            streakBadge
                        }

                        if viewModel.hasData {
                            if !pendingAlertDismissed && !viewModel.sourcesNeedingUpdate.isEmpty {
                                PendingUpdatesAlertBanner(
                                    count: viewModel.sourcesNeedingUpdate.count,
                                    onDismiss: {
                                        withAnimation {
                                            pendingAlertDismissed = true
                                        }
                                    }
                                )
                                .transition(.move(edge: .top).combined(with: .opacity))
                            }

                            if !viewModel.insights.isEmpty {
                                InsightsRow(insights: viewModel.insights)
                            }

                            if horizontalSizeClass == .regular {
                                iPadDashboardLayout
                            } else {
                                ForEach(visibleSections) { config in
                                    sectionView(for: config)
                                }
                            }
                        } else {
                            EmptyDashboardView(
                                onAddSource: { showingAddSource = true },
                                onImport: { showingImport = true },
                                onLoadSample: { SampleDataService.shared.seedSampleData() }
                            )
                        }
                    }
                    .padding()
                }

                if horizontalSizeClass == .regular, let section = fullScreenSection {
                    iPadFullScreenOverlay(for: section)
                        .transition(.opacity.combined(with: .scale(scale: 0.98)))
                        .zIndex(10)
                }
            }
            .animation(.easeInOut(duration: 0.25), value: fullScreenSection)
            .navigationTitle("Home")
            .refreshable {
                viewModel.refreshData()
            }
            .overlay {
                if viewModel.isLoading && !viewModel.hasData {
                    ProgressView()
                }
            }
            .toolbar {
                ToolbarItem(placement: .navigationBarTrailing) {
                    Button {
                        showingQuickUpdate = true
                    } label: {
                        Image(systemName: "plus.circle.fill")
                    }
                }
                ToolbarItem(placement: .navigationBarTrailing) {
                    accountFilterMenu
                }
                ToolbarItem(placement: .navigationBarLeading) {
                    Button {
                        showingCustomize = true
                    } label: {
                        Image(systemName: "slider.horizontal.3")
                    }
                }
            }
            .onAppear {
                viewModel.selectedAccount = accountStore.selectedAccount
                viewModel.showAllAccounts = accountStore.showAllAccounts
                viewModel.refreshData()
                goalsViewModel.selectedAccount = accountStore.selectedAccount
                goalsViewModel.showAllAccounts = accountStore.showAllAccounts
                goalsViewModel.refresh()
            }
            // Performance: Combine account selection changes into a single handler
            .onChange(of: accountStore.selectedAccount) { _, newAccount in
                viewModel.selectedAccount = newAccount
                viewModel.refreshData()
                goalsViewModel.selectedAccount = newAccount
                goalsViewModel.refresh()
            }
            .onChange(of: accountStore.showAllAccounts) { _, showAll in
                viewModel.showAllAccounts = showAll
                viewModel.refreshData()
                goalsViewModel.showAllAccounts = showAll
                goalsViewModel.refresh()
            }
            .sheet(isPresented: $showingImport) {
                ImportDataView()
            }
            .sheet(isPresented: $showingAddSource) {
                AddSourceView()
            }
            .sheet(isPresented: $showingCustomize) {
                DashboardCustomizeView(configs: $sectionConfigs)
            }
            .sheet(isPresented: $showingQuickUpdate) {
                QuickUpdateView()
                    .environment(\.managedObjectContext, CoreDataStack.shared.viewContext)
            }
            .sheet(isPresented: $viewModel.showingPaywall) {
                PaywallView()
            }
            .onReceive(NotificationCenter.default.publisher(for: .openQuickUpdate)) { _ in
                showingQuickUpdate = true
            }
        }
    }

    private var streakBadge: some View {
        HStack(spacing: 6) {
            Image(systemName: "flame.fill")
                .font(.caption.weight(.semibold))
            Text(String(format: String(localized: "streak_badge"), viewModel.updateStreak))
                .font(.caption.weight(.semibold))
        }
        .foregroundColor(.orange)
        .padding(.horizontal, 12)
        .padding(.vertical, 6)
        .background(Color.orange.opacity(0.15))
        .cornerRadius(20)
        .frame(maxWidth: .infinity, alignment: .leading)
    }

    private var accountFilterMenu: some View {
        Menu {
            Button {
                accountStore.selectAllAccounts()
            } label: {
                HStack {
                    Text("All Accounts")
                    if accountStore.showAllAccounts {
                        Image(systemName: "checkmark")
                    }
                }
            }

            Divider()

            ForEach(availableAccounts, id: \.objectID) { account in
                Button {
                    accountStore.selectAccount(account)
                } label: {
                    HStack {
                        Text(account.name)
                        if accountStore.selectedAccount?.safeId == account.safeId && !accountStore.showAllAccounts {
                            Image(systemName: "checkmark")
                        }
                    }
                }
            }
        } label: {
            Image(systemName: "person.2.circle")
        }
    }

    private var availableAccounts: [Account] {
        accountStore.accounts.filter { $0.safeId != nil }
    }

    private var visibleSections: [DashboardSectionConfig] {
        sectionConfigs.filter { $0.isVisible }
    }

    // MARK: - iPad Layout Helpers

    private var iPadGridSections: [DashboardSectionConfig] {
        visibleSections.filter { $0.id != DashboardSection.totalValue.id }
    }

    @ViewBuilder
    private var iPadDashboardLayout: some View {
        // Total Portfolio Value — always full width, never in the grid
        let totalConfig = sectionConfigs.first(where: { $0.id == DashboardSection.totalValue.id })
            ?? DashboardSectionConfig(id: DashboardSection.totalValue.id, isVisible: true, isCollapsed: false)
        sectionView(for: DashboardSectionConfig(id: totalConfig.id, isVisible: true, isCollapsed: totalConfig.isCollapsed))

        // Other cards — 2-column grid with drag-and-drop
        if !iPadGridSections.isEmpty {
            LazyVGrid(
                columns: [GridItem(.flexible()), GridItem(.flexible())],
                spacing: 16
            ) {
                ForEach(iPadGridSections) { config in
                    sectionView(for: config)
                        .gridCellColumns(config.columnSpan)
                        .overlay {
                            if dragTargetID == config.id {
                                RoundedRectangle(cornerRadius: AppConstants.UI.cornerRadius)
                                    .stroke(Color.appPrimary, lineWidth: 2)
                            }
                        }
                        .draggable(config.id)
                        .dropDestination(for: String.self) { items, _ in
                            guard let fromID = items.first else { return false }
                            return handleIPadDrop(fromID: fromID, toID: config.id)
                        } isTargeted: { isTargeted in
                            dragTargetID = isTargeted ? config.id : nil
                        }
                        .contextMenu {
                            Button {
                                toggleColumnSpan(for: config.id)
                            } label: {
                                Label(
                                    config.columnSpan == 2 ? "Normal width" : "Expand to full width",
                                    systemImage: config.columnSpan == 2 ? "rectangle" : "rectangle.expand.diagonal"
                                )
                            }
                            Button {
                                withAnimation(.easeInOut(duration: 0.25)) {
                                    fullScreenSection = DashboardSection(rawValue: config.id)
                                }
                            } label: {
                                Label("View full screen", systemImage: "arrow.up.left.and.arrow.down.right")
                            }
                        }
                }
            }
        }
    }

    @ViewBuilder
    private func iPadFullScreenOverlay(for section: DashboardSection) -> some View {
        ZStack {
            Color(.systemBackground)
                .opacity(0.97)
                .ignoresSafeArea()

            VStack(spacing: 0) {
                HStack {
                    Text(section.title)
                        .font(.title3.weight(.semibold))
                    Spacer()
                    Button {
                        withAnimation(.easeInOut(duration: 0.25)) {
                            fullScreenSection = nil
                        }
                    } label: {
                        Image(systemName: "xmark.circle.fill")
                            .font(.title2)
                            .foregroundColor(.secondary)
                    }
                }
                .padding()

                Divider()

                ScrollView {
                    VStack(spacing: 20) {
                        let totalConfig = sectionConfigs.first(where: { $0.id == DashboardSection.totalValue.id })
                            ?? DashboardSectionConfig(id: DashboardSection.totalValue.id, isVisible: true, isCollapsed: false)
                        sectionView(for: DashboardSectionConfig(id: totalConfig.id, isVisible: true, isCollapsed: totalConfig.isCollapsed))

                        if let config = sectionConfigs.first(where: { $0.id == section.id }) {
                            sectionView(for: DashboardSectionConfig(id: config.id, isVisible: true, isCollapsed: false))
                        }
                    }
                    .padding()
                    .frame(maxWidth: 800)
                    .frame(maxWidth: .infinity)
                }
            }
        }
    }

    private func handleIPadDrop(fromID: String, toID: String) -> Bool {
        guard fromID != toID,
              let fromIndex = sectionConfigs.firstIndex(where: { $0.id == fromID }),
              let toIndex = sectionConfigs.firstIndex(where: { $0.id == toID }) else { return false }
        withAnimation {
            sectionConfigs.move(fromOffsets: IndexSet(integer: fromIndex), toOffset: toIndex > fromIndex ? toIndex + 1 : toIndex)
        }
        DashboardLayoutStore.save(sectionConfigs)
        dragTargetID = nil
        return true
    }

    private func toggleColumnSpan(for id: String) {
        guard let index = sectionConfigs.firstIndex(where: { $0.id == id }) else { return }
        withAnimation {
            sectionConfigs[index].columnSpan = sectionConfigs[index].columnSpan == 2 ? 1 : 2
        }
        DashboardLayoutStore.save(sectionConfigs)
    }

    @ViewBuilder
    private func sectionView(for config: DashboardSectionConfig) -> some View {
        if let section = DashboardSection(rawValue: config.id) {
            switch section {
        case .totalValue:
            if config.isCollapsed {
                CompactCard(title: "Portfolio", subtitle: viewModel.portfolioSummary.formattedTotalValue)
            } else {
                TotalValueCard(
                    totalValue: viewModel.portfolioSummary.formattedTotalValue,
                    changeText: "\(viewModel.latestPortfolioChange.formattedAbsolute) (\(viewModel.latestPortfolioChange.formattedPercentage))",
                    changeLabel: "since last check-in",
                    isPositive: viewModel.latestPortfolioChange.absolute >= 0,
                    forecast: showForecast ? viewModel.portfolioForecast : nil,
                    isPremium: iapService.isPremium,
                    onUnlockTap: {
                        viewModel.showingPaywall = true
                    },
                    yearChange: viewModel.portfolioSummary.formattedYearChange,
                    sinceInceptionChange: viewModel.portfolioSummary.formattedAllTimeReturn,
                    isYearPositive: viewModel.isYearChangePositive,
                    isSinceInceptionPositive: viewModel.portfolioSummary.allTimeReturn >= 0,
                    onShareTap: {
                        ShareService.shared.sharePortfolioValue(
                            totalValue: viewModel.portfolioSummary.formattedTotalValue,
                            changeText: "\(viewModel.latestPortfolioChange.formattedAbsolute) (\(viewModel.latestPortfolioChange.formattedPercentage))",
                            changeLabel: "since last check-in",
                            yearChange: viewModel.portfolioSummary.formattedYearChange,
                            sinceInceptionChange: viewModel.portfolioSummary.formattedAllTimeReturn
                        )
                    }
                )
            }
        case .monthlyCheckIn:
            if config.isCollapsed {
                CompactCard(title: "Monthly Check-in", subtitle: "Last update: \(viewModel.formattedLastUpdate)")
            } else {
                MonthlyCheckInCard(lastUpdated: viewModel.formattedLastUpdate)
            }
        case .momentumStreaks:
            if config.isCollapsed {
                MomentumStreaksCompactCard()
            } else {
                MomentumStreaksCard()
            }
        case .monthlySummary:
            if viewModel.monthlySummary.contributions != 0 {
                if config.isCollapsed {
                    CompactCard(
                        title: "Cashflow vs Growth",
                        subtitle: "\(viewModel.monthlySummary.formattedContributions) contributions"
                    )
                } else {
                    MonthlySummaryCard(summary: viewModel.monthlySummary)
                }
            }
        case .evolution:
            if config.isCollapsed {
                EvolutionCompactCard(data: viewModel.evolutionData)
            } else if !viewModel.evolutionData.isEmpty {
                EvolutionChartCard(
                    data: viewModel.evolutionData,
                    categoryData: viewModel.categoryEvolutionData,
                    goals: goalsViewModel.goals
                )
            }
        case .categoryBreakdown:
            if config.isCollapsed {
                let top = viewModel.topCategories.first
                CompactCard(
                    title: "Top Category",
                    subtitle: "\(top?.categoryName ?? "—") \(top?.formattedPercentage ?? "")"
                )
            } else if !viewModel.categoryMetrics.isEmpty {
                CategoryBreakdownCard(categories: viewModel.topCategories)
            }
        case .goals:
            let homeGoals = goalsViewModel.goals.filter { !GoalsViewModel.isAchieved(progress: goalsViewModel.progress(for: $0)) }
            if config.isCollapsed {
                CompactCard(title: "Goals", subtitle: "\(homeGoals.count) active")
            } else {
                GoalsSummaryCard(
                    goals: homeGoals,
                    progressProvider: goalsViewModel.progress(for:),
                    currentValueProvider: goalsViewModel.totalValue(for:),
                    paceStatusProvider: goalsViewModel.paceStatus(for:),
                    etaProvider: { goal in
                        let currentValue = goalsViewModel.totalValue(for: goal)
                        return viewModel.goalEtaText(for: goal, currentValue: currentValue)
                    }
                )
            }
        case .pendingUpdates:
            if config.isCollapsed {
                CompactCard(title: "Pending Updates", subtitle: "\(viewModel.sourcesNeedingUpdate.count) sources")
            } else if !viewModel.sourcesNeedingUpdate.isEmpty {
                PendingUpdatesCard(sources: viewModel.sourcesNeedingUpdate)
            }
        case .periodReturns:
            if config.isCollapsed {
                CompactCard(title: "Returns", subtitle: viewModel.portfolioSummary.formattedMonthChange)
            } else {
                PeriodReturnsCard(
                    monthChange: viewModel.portfolioSummary.formattedMonthChange,
                    yearChange: viewModel.portfolioSummary.formattedYearChange,
                    allTimeChange: viewModel.portfolioSummary.formattedAllTimeReturn,
                    isMonthPositive: viewModel.isMonthChangePositive,
                    isYearPositive: viewModel.isYearChangePositive,
                    isAllTimePositive: viewModel.portfolioSummary.allTimeReturn >= 0
                )
            }
        case .contributionsVsReturns:
            let contrib = viewModel.portfolioSummary.totalContributions
            let returns = viewModel.portfolioSummary.allTimeReturn
            if contrib > 0 || returns != 0 {
                if config.isCollapsed {
                    CompactCard(title: "Invested vs. Returns", subtitle: contrib.currencyString)
                } else {
                    ContributionsVsReturnsCard(
                        totalContributions: contrib,
                        totalReturns: returns
                    )
                }
            }
        }
        } else {
            EmptyView()
        }
    }
}

// MARK: - Total Value Card

struct TotalValueCard: View {
    let totalValue: String
    let changeText: String
    let changeLabel: String
    let isPositive: Bool
    var forecast: PortfolioForecast?
    var isPremium: Bool = false
    var onUnlockTap: (() -> Void)?
    var yearChange: String?
    var sinceInceptionChange: String?
    var isYearPositive: Bool = true
    var isSinceInceptionPositive: Bool = true
    var onShareTap: (() -> Void)?

    var body: some View {
        VStack(spacing: 8) {
            HStack {
                Spacer()
                Text("Total Portfolio Value")
                    .font(.title3.weight(.bold))
                    .foregroundColor(.white.opacity(0.85))
                Spacer()
            }
            .overlay(alignment: .trailing) {
                if let onShareTap {
                    Button(action: onShareTap) {
                        Image(systemName: "square.and.arrow.up")
                            .font(.subheadline.weight(.semibold))
                            .foregroundColor(.white.opacity(0.9))
                    }
                    .padding(.trailing, 16)
                }
            }

            Text(totalValue)
                .font(.system(size: 42, weight: .bold, design: .rounded))
                .foregroundColor(.white)

            HStack(spacing: 4) {
                Image(systemName: isPositive ? "arrow.up.right" : "arrow.down.right")
                    .font(.caption)
                Text(changeText)
                    .font(.subheadline.weight(.medium))
                Text(changeLabel)
                    .font(.subheadline)
                    .foregroundColor(.white.opacity(0.8))
            }
            .foregroundColor(.white)

            // YoY and Since Inception returns
            if yearChange != nil || sinceInceptionChange != nil {
                HStack(spacing: 16) {
                    if let yearChange = yearChange {
                        VStack(spacing: 2) {
                            Text("YoY")
                                .font(.caption2)
                                .foregroundColor(.white.opacity(0.7))
                            Text(yearChange)
                                .font(.caption.weight(.semibold))
                                .foregroundColor(.white)
                        }
                    }

                    if let sinceInceptionChange = sinceInceptionChange {
                        VStack(spacing: 2) {
                            Text("Since inception")
                                .font(.caption2)
                                .foregroundColor(.white.opacity(0.7))
                            Text(sinceInceptionChange)
                                .font(.caption.weight(.semibold))
                                .foregroundColor(.white)
                        }
                    }
                }
                .padding(.top, 4)
            }

            // Forecast section
            if let forecast = forecast {
                Divider()
                    .background(Color.white.opacity(0.3))
                    .padding(.vertical, 8)

                if isPremium {
                    VStack(spacing: 4) {
                        HStack(spacing: 4) {
                            Image(systemName: "wand.and.stars")
                                .font(.caption)
                            Text("12-month forecast")
                                .font(.caption)
                        }
                        .foregroundColor(.white.opacity(0.85))

                        Text(forecast.formattedForecastValue)
                            .font(.title2.weight(.bold))
                            .foregroundColor(.white)

                        Text(forecast.formattedGrowthPercentage)
                            .font(.caption.weight(.semibold))
                            .foregroundColor(forecast.isPositiveGrowth ? .white : .white.opacity(0.8))
                    }
                } else {
                    Button {
                        onUnlockTap?()
                    } label: {
                        HStack(spacing: 6) {
                            Image(systemName: "lock.fill")
                                .font(.caption)
                            Text("Unlock 12-month forecast")
                                .font(.caption.weight(.semibold))
                        }
                        .foregroundColor(.white)
                        .padding(.horizontal, 12)
                        .padding(.vertical, 6)
                        .background(Color.white.opacity(0.2))
                        .cornerRadius(16)
                    }
                }
            }
        }
        .frame(maxWidth: .infinity)
        .padding(.vertical, 24)
        .background(LinearGradient.appPrimaryGradient)
        .cornerRadius(AppConstants.UI.cornerRadius)
        .shadow(color: .black.opacity(0.05), radius: 8, y: 2)
    }
}

// MARK: - Monthly Check-in Card

struct MonthlyCheckInCard: View {
    let lastUpdated: String
    @State private var startDestinationActive = false

    @FetchRequest(
        sortDescriptors: [NSSortDescriptor(keyPath: \JournalEntry.completionTime, ascending: false)],
        predicate: NSPredicate(format: "completionTime != nil"),
        animation: .none
    ) private var latestJournalEntry: FetchedResults<JournalEntry>

    private var effectiveLastCheckInDate: Date? {
        latestJournalEntry.first?.completionTime
    }

    private var checkInProgress: Double {
        guard let last = effectiveLastCheckInDate,
              let next = nextCheckInDate else { return 1 }
        let totalDays = Double(max(1, last.startOfDay.daysBetween(next.startOfDay)))
        guard totalDays > 0 else { return 1 }
        let elapsedDays = Double(last.startOfDay.daysBetween(Date()))
        return min(max(elapsedDays / totalDays, 0), 1)
    }

    private var nextCheckInDate: Date? {
        guard let last = effectiveLastCheckInDate else { return nil }
        let effective = MonthlyCheckInStore.effectiveMonth(for: last, relativeTo: last)
        return effective.adding(months: 1).endOfMonth
    }

    private var isOverdue: Bool {
        guard let next = nextCheckInDate else { return false }
        return Date() > next
    }

    private var daysUntilDeadline: Int? {
        guard let next = nextCheckInDate else { return nil }
        return Calendar.current.dateComponents([.day], from: Date().startOfDay, to: next.startOfDay).day
    }

    private var progressBarTint: Color {
        if isOverdue { return .red }
        if let days = daysUntilDeadline, days <= 3 { return .orange }
        return .appSecondary
    }

    private var reminderDate: Date? {
        guard let nextCheckInDate else { return nil }
        let settings = AppSettings.getOrCreate(in: CoreDataStack.shared.viewContext)
        let reminderTime = settings.defaultNotificationTime ?? defaultReminderTime
        let timeComponents = Calendar.current.dateComponents([.hour, .minute], from: reminderTime)
        return Calendar.current.date(
            bySettingHour: timeComponents.hour ?? 9,
            minute: timeComponents.minute ?? 0,
            second: 0,
            of: nextCheckInDate
        )
    }

    /// True during the first half of the month (before mid-month threshold) when the previous
    /// period's check-in should be offered for update instead of starting a new one.
    private var isBeforeMidMonth: Bool {
        guard effectiveLastCheckInDate != nil else { return false }
        let cal = Calendar.current
        let day = cal.component(.day, from: Date())
        let daysInMonth = cal.range(of: .day, in: .month, for: Date())?.count ?? 30
        return day < daysInMonth / 2
    }

    /// Reference date to pass to MonthlyCheckInView depending on the current phase.
    private var navigationReferenceDate: Date {
        if isBeforeMidMonth {
            return Calendar.current.date(byAdding: .month, value: -1, to: Date()) ?? Date()
        }
        // Use day 25 so effectiveMonth always resolves to the current calendar month
        var comps = Calendar.current.dateComponents([.year, .month], from: Date())
        comps.day = 25
        return Calendar.current.date(from: comps) ?? Date()
    }

    private var buttonLabel: String {
        if isBeforeMidMonth {
            let formatter = DateFormatter()
            formatter.dateFormat = "MMMM"
            formatter.locale = .current
            let prev = Calendar.current.date(byAdding: .month, value: -1, to: Date()) ?? Date()
            return String(format: NSLocalizedString("checkin_update_month", comment: ""), formatter.string(from: prev))
        }
        return NSLocalizedString("checkin_start_new", comment: "")
    }

    private var currentMonthLabel: String {
        let formatter = DateFormatter()
        formatter.dateFormat = "LLLL yyyy"
        if isBeforeMidMonth {
            let prev = Calendar.current.date(byAdding: .month, value: -1, to: Date()) ?? Date()
            return formatter.string(from: prev)
        }
        return formatter.string(from: Date())
    }

    var body: some View {
        VStack(alignment: .leading, spacing: 12) {
            Text("Monthly Check-in")
                .font(.headline)

            Text(currentMonthLabel)
                .font(.subheadline)
                .foregroundColor(.secondary)

            HStack {
                Text("Last update: \(lastUpdated)")
                    .font(.caption)
                    .foregroundColor(.secondary)

                Spacer()

                if let reminderDate {
                    Button {
                        let title = String(
                            format: NSLocalizedString("calendar_event_title", comment: ""),
                            appDisplayName
                        )
                        let notes = String(
                            format: NSLocalizedString("calendar_event_notes", comment: ""),
                            appDisplayName
                        )
                        ShareService.shared.shareCalendarEvent(
                            title: title,
                            notes: notes,
                            startDate: reminderDate
                        )
                    } label: {
                        Image(systemName: "calendar.badge.plus")
                    }
                    .font(.subheadline.weight(.semibold))
                }
            }

            ProgressView(value: checkInProgress)
                .tint(progressBarTint)

            if let nextDate = nextCheckInDate {
                Text("Next check-in: \(nextDate.mediumDateString)")
                    .font(.caption)
                    .foregroundColor(isOverdue ? .red : .secondary)
            }

            Button {
                startDestinationActive = true
            } label: {
                Text(buttonLabel)
                    .font(.headline.weight(.semibold))
                    .frame(maxWidth: .infinity)
                    .padding(.vertical, 12)
                    .background(Color.appPrimary)
                    .foregroundColor(.white)
                    .cornerRadius(AppConstants.UI.cornerRadius)
            }

            NavigationLink(
                isActive: $startDestinationActive
            ) {
                MonthlyCheckInView(referenceDate: navigationReferenceDate)
            } label: {
                EmptyView()
            }
        }
        .padding()
        .background(Color(.systemBackground))
        .cornerRadius(AppConstants.UI.cornerRadius)
        .shadow(color: .black.opacity(0.05), radius: 8, y: 2)
    }

    private var defaultReminderTime: Date {
        var components = DateComponents()
        components.hour = 9
        components.minute = 0
        return Calendar.current.date(from: components) ?? Date()
    }

    private 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"
    }
}

// MARK: - Momentum & Streaks Card

struct MomentumStreaksCard: View {
    @State private var stats: MonthlyCheckInStats = .empty

    var body: some View {
        VStack(alignment: .leading, spacing: 12) {
            HStack(alignment: .firstTextBaseline) {
                Text("Momentum & Streaks")
                    .font(.headline)
                Spacer()
                if stats.totalCheckIns > 0 {
                    Text(String(format: NSLocalizedString("on_time_rate", comment: ""), onTimeRateText))
                        .font(.subheadline.weight(.semibold))
                        .foregroundColor(.appSecondary)
                } else {
                    Text("Log a check-in to start a streak")
                        .font(.subheadline)
                        .foregroundColor(.secondary)
                }
            }

            HStack(spacing: 12) {
                statTile(
                    title: "Streak",
                    value: "\(stats.currentStreak)x",
                    subtitle: "On-time in a row"
                )
                statTile(
                    title: "Best",
                    value: "\(stats.bestStreak)x",
                    subtitle: "Personal best"
                )
                statTile(
                    title: "Avg early",
                    value: formattedDaysText(for: stats.averageDaysBeforeDeadline),
                    subtitle: "vs deadline"
                )
            }

            ProgressView(value: stats.onTimeRate, total: 1)
                .tint(.appSecondary)

            HStack {
                Text("On-time score")
                    .font(.caption)
                    .foregroundColor(.secondary)
                Spacer()
                Text(
                    String(
                        format: NSLocalizedString("on_time_count", comment: ""),
                        stats.onTimeCount,
                        stats.totalCheckIns
                    )
                )
                    .font(.caption)
                    .foregroundColor(.secondary)
            }

            if let closest = stats.closestCutoffDays {
                Text(
                    String(
                        format: NSLocalizedString("tightest_finish", comment: ""),
                        formattedDaysLabel(for: closest)
                    )
                )
                    .font(.caption)
                    .foregroundColor(.secondary)
            }

            if !stats.achievements.isEmpty {
                VStack(alignment: .leading, spacing: 8) {
                    Text(String(localized: "achievements_title"))
                        .font(.subheadline.weight(.semibold))

                    ScrollView(.horizontal, showsIndicators: false) {
                        HStack(spacing: 10) {
                            ForEach(stats.achievements) { achievement in
                                achievementBadge(achievement)
                            }
                        }
                    }
                }
            }

            NavigationLink {
                AchievementsView(referenceDate: Date())
            } label: {
                HStack {
                    Text(String(localized: "achievements_view_all"))
                        .font(.subheadline.weight(.semibold))
                    Spacer()
                    Image(systemName: "chevron.right")
                        .font(.caption)
                        .foregroundColor(.secondary)
                }
                .padding(.vertical, 8)
            }
            .buttonStyle(.plain)
        }
        .padding()
        .background(Color(.systemBackground))
        .cornerRadius(AppConstants.UI.cornerRadius)
        .shadow(color: .black.opacity(0.05), radius: 8, y: 2)
        .onAppear(perform: refreshStats)
        .onReceive(NotificationCenter.default.publisher(for: .NSManagedObjectContextObjectsDidChange)) { _ in
            refreshStats()
        }
    }

    private var onTimeRateText: String {
        String(format: "%.0f%%", stats.onTimeRate * 100)
    }

    private func refreshStats() {
        stats = MonthlyCheckInStore.stats(referenceDate: Date())
    }

    @ViewBuilder
    private func statTile(title: String, value: String, subtitle: String) -> some View {
        VStack(alignment: .leading, spacing: 4) {
            Text(title)
                .font(.caption)
                .foregroundColor(.secondary)
            Text(value)
                .font(.title3.weight(.semibold))
            Text(subtitle)
                .font(.caption2)
                .foregroundColor(.secondary)
        }
        .padding()
        .frame(maxWidth: .infinity, alignment: .leading)
        .background(Color.gray.opacity(0.08))
        .cornerRadius(AppConstants.UI.smallCornerRadius)
    }

    @ViewBuilder
    private func achievementBadge(_ achievement: MonthlyCheckInAchievement) -> some View {
        HStack(alignment: .top, spacing: 8) {
            Image(systemName: achievement.icon)
                .font(.headline)
                .foregroundColor(.appSecondary)
            VStack(alignment: .leading, spacing: 2) {
                Text(achievement.title)
                    .font(.caption.weight(.semibold))
                Text(achievement.detail)
                    .font(.caption2)
                    .foregroundColor(.secondary)
            }
        }
        .padding(10)
        .background(Color.appSecondary.opacity(0.12))
        .cornerRadius(AppConstants.UI.smallCornerRadius)
    }

    private func formattedDaysText(for days: Double?) -> String {
        guard let days, days >= 0 else { return "—" }
        return days >= 1 ? String(format: "%.1fd", days) : String(format: "%.0fh", days * 24)
    }

    private func formattedDaysLabel(for days: Double) -> String {
        if days >= 1 {
            return String(format: "%.1f days", days)
        }
        let hours = max(0, days * 24)
        return String(format: "%.0f hours", hours)
    }
}

struct MomentumStreaksCompactCard: View {
    @State private var stats: MonthlyCheckInStats = .empty

    var body: some View {
        CompactCard(
            title: "Momentum & Streaks",
            subtitle: "Streak: \(stats.currentStreak)x • Best: \(stats.bestStreak)x"
        )
        .onAppear(perform: refreshStats)
        .onReceive(NotificationCenter.default.publisher(for: .NSManagedObjectContextObjectsDidChange)) { _ in
            refreshStats()
        }
    }

    private func refreshStats() {
        stats = MonthlyCheckInStore.stats(referenceDate: Date())
    }
}

// MARK: - Monthly Summary Card

struct MonthlySummaryCard: View {
    let summary: MonthlySummary

    var body: some View {
        VStack(alignment: .leading, spacing: 12) {
            Text("Cashflow vs Growth")
                .font(.headline)

            HStack {
                VStack(alignment: .leading, spacing: 4) {
                    Text("Contributions")
                        .font(.caption)
                        .foregroundColor(.secondary)
                    Text(summary.formattedContributions)
                        .font(.subheadline.weight(.semibold))
                }

                Spacer()

                VStack(alignment: .trailing, spacing: 4) {
                    Text("Net Performance")
                        .font(.caption)
                        .foregroundColor(.secondary)
                    Text("\(summary.formattedNetPerformance) (\(summary.formattedNetPerformancePercentage))")
                        .font(.subheadline.weight(.semibold))
                        .foregroundColor(summary.netPerformance >= 0 ? .positiveGreen : .negativeRed)
                }
            }
        }
        .padding()
        .background(Color(.systemBackground))
        .cornerRadius(AppConstants.UI.cornerRadius)
        .shadow(color: .black.opacity(0.05), radius: 8, y: 2)
    }
}

// MARK: - Dashboard Customization

struct DashboardCustomizeView: View {
    @Environment(\.dismiss) private var dismiss
    @Binding var configs: [DashboardSectionConfig]

    var body: some View {
        NavigationStack {
            List {
                ForEach($configs) { $config in
                    HStack {
                        VStack(alignment: .leading, spacing: 4) {
                            Text(DashboardSection(rawValue: config.id)?.title ?? config.id)
                                .font(.subheadline.weight(.semibold))
                            Text(config.isCollapsed ? "Compact" : "Expanded")
                                .font(.caption)
                                .foregroundColor(.secondary)
                        }

                        Spacer()

                        Toggle("Show", isOn: $config.isVisible)
                            .labelsHidden()
                    }
                    .swipeActions(edge: .trailing) {
                        Button {
                            config.isCollapsed.toggle()
                        } label: {
                            Label(config.isCollapsed ? "Expand" : "Compact", systemImage: "arrow.up.left.and.arrow.down.right")
                        }
                        .tint(.appSecondary)
                    }
                }
                .onMove { indices, newOffset in
                    configs.move(fromOffsets: indices, toOffset: newOffset)
                }
            }
            .navigationTitle("Customize Dashboard")
            .toolbar {
                ToolbarItem(placement: .navigationBarLeading) {
                    EditButton()
                }
                ToolbarItem(placement: .navigationBarTrailing) {
                    Button("Done") {
                        DashboardLayoutStore.save(configs)
                        dismiss()
                    }
                    .fontWeight(.semibold)
                }
            }
        }
        .onDisappear {
            DashboardLayoutStore.save(configs)
        }
    }
}

struct CompactCard: View {
    let title: String
    let subtitle: String

    var body: some View {
        VStack(alignment: .leading, spacing: 6) {
            Text(title)
                .font(.headline)
            Text(subtitle)
                .font(.subheadline)
                .foregroundColor(.secondary)
        }
        .padding()
        .frame(maxWidth: .infinity, alignment: .leading)
        .background(Color(.systemBackground))
        .cornerRadius(AppConstants.UI.cornerRadius)
        .shadow(color: .black.opacity(0.05), radius: 8, y: 2)
    }
}

struct EvolutionCompactCard: View {
    let data: [(date: Date, value: Decimal)]

    var body: some View {
        VStack(alignment: .leading, spacing: 8) {
            Text("Portfolio Evolution")
                .font(.headline)
            if let last = data.last {
                Text(last.value.compactCurrencyString)
                    .font(.subheadline.weight(.semibold))
                    .foregroundColor(.secondary)
            }
            SparklineView(data: data, color: .appPrimary)
                .frame(height: 40)
        }
        .padding()
        .frame(maxWidth: .infinity, alignment: .leading)
        .background(Color(.systemBackground))
        .cornerRadius(AppConstants.UI.cornerRadius)
        .shadow(color: .black.opacity(0.05), radius: 8, y: 2)
    }
}

// MARK: - Period Returns Card

struct PeriodReturnsCard: View {
    let monthChange: String
    let yearChange: String
    let allTimeChange: String
    let isMonthPositive: Bool
    let isYearPositive: Bool
    let isAllTimePositive: Bool

    var body: some View {
        VStack(alignment: .leading, spacing: 12) {
            Text("Returns")
                .font(.headline)

            HStack(spacing: 16) {
                ReturnPeriodView(
                    period: "1M",
                    change: monthChange,
                    isPositive: isMonthPositive
                )

                Divider()

                ReturnPeriodView(
                    period: "1Y",
                    change: yearChange,
                    isPositive: isYearPositive
                )

                Divider()

                ReturnPeriodView(
                    period: "All",
                    change: allTimeChange,
                    isPositive: isAllTimePositive
                )
            }
            .frame(maxWidth: .infinity)
        }
        .padding()
        .background(Color(.systemBackground))
        .cornerRadius(AppConstants.UI.cornerRadius)
        .shadow(color: .black.opacity(0.05), radius: 8, y: 2)
    }
}

struct ReturnPeriodView: View {
    let period: String
    let change: String
    let isPositive: Bool

    var body: some View {
        VStack(spacing: 4) {
            Text(period)
                .font(.caption)
                .foregroundColor(.secondary)

            Text(change)
                .font(.subheadline.weight(.semibold))
                .foregroundColor(isPositive ? .positiveGreen : .negativeRed)
                .lineLimit(1)
                .minimumScaleFactor(0.8)
        }
        .frame(maxWidth: .infinity)
    }
}

// MARK: - Empty Dashboard View

struct EmptyDashboardView: View {
    let onAddSource: () -> Void
    let onImport: () -> Void
    let onLoadSample: () -> Void

    var body: some View {
        VStack(spacing: 20) {
            Image(systemName: "chart.pie")
                .font(.system(size: 60))
                .foregroundColor(.secondary)

            Text("Welcome to Portfolio Journal")
                .font(.custom("Avenir Next", size: 24).weight(.semibold))

            Text("Start by adding your first investment source to track your portfolio.")
                .font(.subheadline)
                .foregroundColor(.secondary)
                .multilineTextAlignment(.center)

            Button {
                onAddSource()
            } label: {
                Label("Add Investment Source", systemImage: "plus")
                    .font(.headline)
                    .foregroundColor(.white)
                    .padding()
                    .frame(maxWidth: .infinity)
                    .background(Color.appPrimary)
                    .cornerRadius(AppConstants.UI.cornerRadius)
            }

            HStack(spacing: 12) {
                Button {
                    onImport()
                } label: {
                    Label("Import", systemImage: "square.and.arrow.down")
                        .font(.subheadline.weight(.semibold))
                        .frame(maxWidth: .infinity)
                        .padding()
                        .background(Color.appPrimary.opacity(0.1))
                        .foregroundColor(.appPrimary)
                        .cornerRadius(AppConstants.UI.cornerRadius)
                }

                Button {
                    onLoadSample()
                } label: {
                    Label("Load Sample", systemImage: "sparkles")
                        .font(.subheadline.weight(.semibold))
                        .frame(maxWidth: .infinity)
                        .padding()
                        .background(Color.appSecondary.opacity(0.1))
                        .foregroundColor(.appSecondary)
                        .cornerRadius(AppConstants.UI.cornerRadius)
                }
            }
        }
        .padding()
    }
}

// MARK: - Pending Updates Alert Banner

struct PendingUpdatesAlertBanner: View {
    let count: Int
    let onDismiss: () -> Void

    var body: some View {
        HStack(spacing: 10) {
            Image(systemName: "exclamationmark.triangle.fill")
                .foregroundColor(.white)

            Text("\(count) source\(count == 1 ? "" : "s") pending update")
                .font(.subheadline.weight(.semibold))
                .foregroundColor(.white)

            Spacer()

            Button(action: onDismiss) {
                Image(systemName: "xmark")
                    .font(.caption.weight(.bold))
                    .foregroundColor(.white.opacity(0.8))
            }
        }
        .padding(.horizontal, 16)
        .padding(.vertical, 12)
        .background(Color.appWarning)
        .cornerRadius(AppConstants.UI.cornerRadius)
    }
}

// MARK: - Pending Updates Card

struct PendingUpdatesCard: View {
    @EnvironmentObject var iapService: IAPService
    let sources: [InvestmentSource]

    var body: some View {
        VStack(alignment: .leading, spacing: 12) {
            HStack {
                Image(systemName: "bell.badge.fill")
                    .foregroundColor(.appWarning)
                Text("Pending Updates")
                    .font(.headline)
                Spacer()
                Text("\(sources.count)")
                    .font(.subheadline)
                    .foregroundColor(.secondary)
            }

            ForEach(sources.prefix(3), id: \.objectID) { source in
                NavigationLink(destination: SourceDetailView(source: source, iapService: iapService)) {
                    HStack {
                        Circle()
                            .fill(source.category?.color ?? .gray)
                            .frame(width: 8, height: 8)

                        Text(source.name)
                            .font(.subheadline)

                        Spacer()

                        Text(source.latestSnapshot?.date.relativeDescription ?? "Never")
                            .font(.caption)
                            .foregroundColor(.secondary)

                        Image(systemName: "chevron.right")
                            .font(.caption)
                            .foregroundColor(.secondary)
                    }
                }
                .buttonStyle(.plain)
            }

            if sources.count > 3 {
                Text("+ \(sources.count - 3) more")
                    .font(.caption)
                    .foregroundColor(.secondary)
            }
        }
        .padding()
        .background(Color(.systemBackground))
        .cornerRadius(AppConstants.UI.cornerRadius)
        .shadow(color: .black.opacity(0.05), radius: 8, y: 2)
    }
}

// MARK: - Goals Summary Card

struct GoalsSummaryCard: View {
    let goals: [Goal]
    let progressProvider: (Goal) -> Double
    let currentValueProvider: (Goal) -> Decimal
    let paceStatusProvider: (Goal) -> GoalPaceStatus?
    let etaProvider: (Goal) -> String?

    var body: some View {
        if goals.isEmpty {
            EmptyGoalsCard()
        } else {
            VStack(alignment: .leading, spacing: 12) {
                HStack {
                    Text("Goals")
                        .font(.headline)
                    Spacer()
                    NavigationLink("View All") {
                        GoalsView()
                    }
                    .font(.caption.weight(.semibold))
                }

                ForEach(goals.prefix(2)) { goal in
                    let currentValue = currentValueProvider(goal)
                    let paceStatus = paceStatusProvider(goal)
                    let isAchieved = GoalsViewModel.isAchieved(progress: progressProvider(goal))
                    let targetUrgency = GoalsViewModel.urgencyLevel(
                        targetDate: goal.targetDate,
                        isBehind: paceStatus?.isBehind ?? false,
                        isAchieved: isAchieved
                    )
                    VStack(alignment: .leading, spacing: 6) {
                        HStack {
                            Text(goal.name)
                                .font(.subheadline.weight(.semibold))
                            Spacer()
                            Button {
                                GoalShareService.shared.shareGoal(
                                    name: goal.name,
                                    progress: progressProvider(goal),
                                    currentValue: currentValue,
                                    targetValue: goal.targetDecimal
                                )
                            } label: {
                                Image(systemName: "square.and.arrow.up")
                                    .font(.caption)
                                    .foregroundColor(.appPrimary)
                            }
                        }

                        GoalProgressBar(progress: progressProvider(goal), tint: .appSecondary, iconColor: .appSecondary)

                        HStack {
                            Text(currentValue.compactCurrencyString)
                                .font(.caption.weight(.semibold))
                            Spacer()
                            Text("of \(goal.targetDecimal.compactCurrencyString)")
                                .font(.caption)
                                .foregroundColor(.secondary)
                        }

                        if let targetDate = goal.targetDate {
                            Text("Target: \(targetDate.mediumDateString)")
                                .font(.caption2.weight(.semibold))
                                .foregroundColor(targetUrgency == .critical ? .negativeRed : (targetUrgency == .warning ? .appWarning : .secondary))
                        }

                        if let etaText = etaProvider(goal) {
                            Text(etaText)
                                .font(.caption2)
                                .foregroundColor(.secondary)
                        }

                        if let paceStatus {
                            Text(paceStatus.statusText)
                                .font(.caption2.weight(.semibold))
                                .foregroundColor(paceStatus.isBehind ? .negativeRed : .positiveGreen)
                        }
                    }
                }
            }
            .padding()
            .background(Color(.systemBackground))
            .cornerRadius(AppConstants.UI.cornerRadius)
            .shadow(color: .black.opacity(0.05), radius: 8, y: 2)
        }
    }
}

struct EmptyGoalsCard: View {
    var body: some View {
        VStack(alignment: .leading, spacing: 12) {
            HStack {
                Text("Goals")
                    .font(.headline)
                Spacer()
                NavigationLink("Set Goal") {
                    GoalsView()
                }
                .font(.caption.weight(.semibold))
            }
            Text("Add a milestone like 1M and track your progress each month.")
                .font(.subheadline)
                .foregroundColor(.secondary)
        }
        .padding()
        .background(Color(.systemBackground))
        .cornerRadius(AppConstants.UI.cornerRadius)
        .shadow(color: .black.opacity(0.05), radius: 8, y: 2)
    }
}

// MARK: - Contributions vs Returns Card

struct ContributionsVsReturnsCard: View {
    let totalContributions: Decimal
    let totalReturns: Decimal

    private var total: Decimal { totalContributions + totalReturns }
    private var contributionFraction: Double {
        guard total > 0 else { return 0.5 }
        return NSDecimalNumber(decimal: totalContributions / total).doubleValue
    }
    private var returnFraction: Double { 1 - contributionFraction }
    private var isReturnPositive: Bool { totalReturns >= 0 }

    var body: some View {
        VStack(alignment: .leading, spacing: 12) {
            Text(String(localized: "contributions_vs_returns_title"))
                .font(.headline)

            // Bar
            GeometryReader { geo in
                HStack(spacing: 2) {
                    RoundedRectangle(cornerRadius: 4)
                        .fill(Color.appSecondary)
                        .frame(width: max(4, geo.size.width * CGFloat(contributionFraction)))

                    RoundedRectangle(cornerRadius: 4)
                        .fill(isReturnPositive ? Color.positiveGreen : Color.negativeRed)
                        .frame(maxWidth: .infinity)
                }
                .frame(height: 16)
                .clipShape(RoundedRectangle(cornerRadius: 6))
            }
            .frame(height: 16)

            HStack {
                HStack(spacing: 6) {
                    Circle().fill(Color.appSecondary).frame(width: 10, height: 10)
                    VStack(alignment: .leading, spacing: 2) {
                        Text(String(localized: "contributions_vs_returns_invested"))
                            .font(.caption).foregroundColor(.secondary)
                        Text(totalContributions.currencyString)
                            .font(.subheadline.weight(.semibold))
                    }
                }
                Spacer()
                HStack(spacing: 6) {
                    Circle().fill(isReturnPositive ? Color.positiveGreen : Color.negativeRed).frame(width: 10, height: 10)
                    VStack(alignment: .trailing, spacing: 2) {
                        Text(String(localized: "contributions_vs_returns_returns"))
                            .font(.caption).foregroundColor(.secondary)
                        let prefix = totalReturns >= 0 ? "+" : ""
                        Text("\(prefix)\(totalReturns.currencyString)")
                            .font(.subheadline.weight(.semibold))
                            .foregroundColor(isReturnPositive ? .positiveGreen : .negativeRed)
                    }
                }
            }
        }
        .padding()
        .background(Color(.systemBackground))
        .cornerRadius(AppConstants.UI.cornerRadius)
        .shadow(color: .black.opacity(0.05), radius: 8, y: 2)
    }
}

#Preview {
    DashboardView()
        .environmentObject(IAPService())
        .environmentObject(AccountStore(iapService: IAPService()))
}
