Загрузка данных


import SwiftUI

struct HistoryView: View {
    @ObservedObject var store: StickStore
    @State private var logToDelete: StickLog? = nil
    @State private var showDeleteAlert = false

    var totalCount: Int {
        store.logs.count
    }

    var firstLogDate: Date? {
        store.logs.map { $0.date }.min()
    }

    var lastLogDate: Date? {
        store.logs.map { $0.date }.max()
    }

    struct DayGroup: Identifiable {
        var id: Date { date }
        let date: Date
        let logs: [StickLog]
    }

    struct MonthGroup: Identifiable {
        var id: String { month }
        let month: String
        let days: [DayGroup]
    }

    struct YearGroup: Identifiable {
        var id: String { year }
        let year: String
        let months: [MonthGroup]
    }

    var groupedByYearAndMonth: [YearGroup] {
        let calendar = Calendar.current
        
        let dailyGrouped = Dictionary(grouping: store.logs) { log in
            calendar.startOfDay(for: log.date)
        }
        
        let daysArray = dailyGrouped.map { DayGroup(date: $0.key, logs: $0.value.sorted(by: { $0.date > $1.date })) }

        let yearGrouped = Dictionary(grouping: daysArray) { day in
            calendar.component(.year, from: day.date)
        }

        return yearGrouped.map { (yearKey, daysInYear) in
            let monthGrouped = Dictionary(grouping: daysInYear) { day in
                calendar.component(.month, from: day.date)
            }

            let monthsArray = monthGrouped.map { (monthKey, daysInMonth) in
                let monthName = formattedMonthName(monthKey)
                let sortedDays = daysInMonth.sorted(by: { $0.date > $1.date })
                return MonthGroup(month: monthName, days: sortedDays)
            }.sorted { m1, m2 in
                guard let d1 = m1.days.first?.date, let d2 = m2.days.first?.date else { return false }
                return d1 > d2
            }

            return YearGroup(year: String(yearKey), months: monthsArray)
        }.sorted { y1, y2 in
            (Int(y1.year) ?? 0) > (Int(y2.year) ?? 0)
        }
    }

    var body: some View {
        ZStack(alignment: .top) {
            // Задний фон
            Color(uiColor: .systemGroupedBackground)
                .ignoresSafeArea()

            // Основной скролл с отступом сверху под плашку
            ScrollView {
                VStack(spacing: 20) {
                    topCardsView
                    
                    if store.logs.isEmpty {
                        emptyStateView
                    } else {
                        historyListView
                    }
                }
                .padding(.top, 70) // Отступ, чтобы контент не перекрывался заголовком изначально
                .padding(.bottom, 20)
            }

            // Нативная блюр-панель сверху
            blurHeaderView
        }
        .alert("Удалить эту запись?", isPresented: $showDeleteAlert) {
            Button("Удалить", role: .destructive) {
                if let log = logToDelete {
                    let impact = UINotificationFeedbackGenerator()
                    impact.notificationOccurred(.error)
                    store.deleteLog(log)
                }
            }
            Button("Отмена", role: .cancel) {
                let impact = UIImpactFeedbackGenerator(style: .light)
                impact.impactOccurred()
                logToDelete = nil
            }
        } message: {
            Text("Запись будет удалена безвозвратно.")
        }
    }

    // MARK: - Subviews

    private var blurHeaderView: some View {
        VStack(spacing: 0) {
            HStack {
                Text("Вся история")
                    .font(.system(size: 28, weight: .bold, design: .rounded))
                    .foregroundColor(.primary)
                Spacer()
            }
            .padding(.horizontal)
            .padding(.bottom, 12)
        }
        .frame(maxWidth: .infinity)
        .background(.ultraThinMaterial) // Красивый блюр с эффектом размытия контента
        .overlay(
            Divider()
                .opacity(0.4),
            alignment: .bottom
        )
    }

    private var topCardsView: some View {
        VStack(spacing: 12) {
            // Карточка общего количества
            HStack {
                VStack(alignment: .leading, spacing: 4) {
                    Text("ВСЕГО СКУРЕНО")
                        .font(.system(size: 11, weight: .black))
                        .foregroundColor(.primary.opacity(0.6))
                        .tracking(1.0)

                    Text("\(totalCount) шт.")
                        .font(.system(size: 28, weight: .heavy, design: .rounded))
                        .foregroundColor(.orange)
                }
                Spacer()
                Image(systemName: "flame.circle.fill")
                    .font(.system(size: 38))
                    .foregroundColor(.orange)
            }
            .padding(.vertical, 16)
            .padding(.horizontal, 20)
            .background(Color(uiColor: .secondarySystemGroupedBackground))
            .cornerRadius(18)
            .shadow(color: Color.black.opacity(0.04), radius: 6, x: 0, y: 3)

            // Карточки первого и последнего стика
            HStack(spacing: 14) {
                VStack(spacing: 6) {
                    Text("ПЕРВАЯ ЗАПИСЬ")
                        .font(.system(size: 10, weight: .black))
                        .foregroundColor(.orange)
                        .tracking(1.0)

                    if let firstDate = firstLogDate {
                        Text(firstDate, style: .date)
                            .font(.system(size: 14, weight: .bold))
                            .multilineTextAlignment(.center)
                    } else {
                        Text("—")
                            .font(.system(size: 14, weight: .bold))
                            .foregroundColor(.secondary)
                    }
                }
                .frame(maxWidth: .infinity)
                .padding(.vertical, 14)
                .padding(.horizontal, 10)
                .background(Color(uiColor: .secondarySystemGroupedBackground))
                .cornerRadius(18)
                .shadow(color: Color.black.opacity(0.04), radius: 6, x: 0, y: 3)

                VStack(spacing: 6) {
                    Text("ПОСЛЕДНЯЯ ЗАПИСЬ")
                        .font(.system(size: 10, weight: .black))
                        .foregroundColor(.red)
                        .tracking(1.0)

                    if let lastDate = lastLogDate {
                        Text(lastDate, style: .date)
                            .font(.system(size: 14, weight: .bold))
                            .multilineTextAlignment(.center)
                    } else {
                        Text("—")
                            .font(.system(size: 14, weight: .bold))
                            .foregroundColor(.secondary)
                    }
                }
                .frame(maxWidth: .infinity)
                .padding(.vertical, 14)
                .padding(.horizontal, 10)
                .background(Color(uiColor: .secondarySystemGroupedBackground))
                .cornerRadius(18)
                .shadow(color: Color.black.opacity(0.04), radius: 6, x: 0, y: 3)
            }
        }
        .padding(.horizontal)
    }

    private var emptyStateView: some View {
        VStack(spacing: 12) {
            Image(systemName: "tray")
                .font(.system(size: 48))
                .foregroundColor(.secondary)
            Text("История пуста")
                .font(.headline)
            Text("Здесь будут отображаться абсолютно все ваши записи.")
                .font(.subheadline)
                .foregroundColor(.secondary)
                .multilineTextAlignment(.center)
        }
        .padding(.top, 40)
        .padding(.horizontal)
    }

    private var historyListView: some View {
        LazyVStack(alignment: .leading, spacing: 24) {
            ForEach(groupedByYearAndMonth) { yearGroup in
                VStack(alignment: .leading, spacing: 16) {
                    Text(yearGroup.year)
                        .font(.system(size: 28, weight: .heavy, design: .rounded))
                        .padding(.horizontal)

                    ForEach(yearGroup.months) { monthGroup in
                        VStack(alignment: .leading, spacing: 12) {
                            HStack {
                                Text(monthGroup.month.uppercased())
                                    .font(.system(size: 13, weight: .bold))
                                    .foregroundColor(.primary)
                                    .tracking(1.2)
                                Spacer()
                            }
                            .padding(.vertical, 10)
                            .padding(.horizontal, 16)
                            .background(Color.orange.opacity(0.15))
                            .cornerRadius(12)
                            .padding(.horizontal)

                            ForEach(monthGroup.days) { dayGroup in
                                dayCell(dayGroup)
                            }
                        }
                    }
                }
            }
        }
    }

    private func dayCell(_ dayGroup: DayGroup) -> some View {
        VStack(alignment: .leading, spacing: 8) {
            Text(formattedDayHeader(dayGroup.date))
                .font(.system(size: 14, weight: .semibold))
                .foregroundColor(.secondary)
                .padding(.horizontal)

            VStack(spacing: 0) {
                ForEach(Array(dayGroup.logs.enumerated()), id: \.element.id) { index, log in
                    HStack {
                        Image(systemName: "flame.fill")
                            .font(.system(size: 16))
                            .foregroundColor(.orange)

                        Text(log.date, style: .time)
                            .font(.system(size: 16, weight: .medium))

                        Spacer()

                        Button(action: {
                            let impact = UINotificationFeedbackGenerator()
                            impact.notificationOccurred(.warning)
                            logToDelete = log
                            showDeleteAlert = true
                        }) {
                            Image(systemName: "trash")
                                .font(.system(size: 14))
                                .foregroundColor(.red.opacity(0.7))
                                .padding(8)
                        }
                    }
                    .padding(.horizontal, 16)
                    .padding(.vertical, 10)

                    if index < dayGroup.logs.count - 1 {
                        Divider()
                            .padding(.leading, 16)
                    }
                }
            }
            .background(Color(uiColor: .secondarySystemGroupedBackground))
            .cornerRadius(16)
            .padding(.horizontal)
        }
    }

    private func formattedMonthName(_ monthNumber: Int) -> String {
        let fmt = DateFormatter()
        fmt.locale = Locale(identifier: "ru_RU")
        return fmt.standaloneMonthSymbols[monthNumber - 1].capitalized
    }

    private func formattedDayHeader(_ date: Date) -> String {
        let formatter = DateFormatter()
        formatter.locale = Locale(identifier: "ru_RU")
        formatter.dateFormat = "d MMMM, EEEE"
        return formatter.string(from: date).capitalized
    }
}