import SwiftUI
import SwiftData

struct ArchiveListView: View {
    @Query(sort: \Indicator.capturedAt, order: .reverse)
    private var indicators: [Indicator]

    @Query(sort: \Report.reportDate, order: .reverse)
    private var reports: [Report]

    @Query(sort: \DiaryEntry.createdAt, order: .reverse)
    private var diaries: [DiaryEntry]

    @Query(sort: \Symptom.startedAt, order: .reverse)
    private var symptoms: [Symptom]

    @Query(sort: \HealthExport.createdAt, order: .reverse)
    private var exports: [HealthExport]

    @Query(sort: \CustomReminder.updatedAt, order: .reverse)
    private var customReminders: [CustomReminder]

    @Query(sort: \MetricReminder.updatedAt, order: .reverse)
    private var metricReminders: [MetricReminder]

    @Query(sort: \Medication.updatedAt, order: .reverse)
    private var medications: [Medication]

    /// 记录页内的 push 目的地。用单个 `navigationDestination(item:)` 驱动——
    /// 多个 `navigationDestination(isPresented:)` 并存时 SwiftUI 行为未定义(会误触发)。
    private enum Route: Hashable { case exports, reminders, medicationLibrary }

    @State private var filter: TimelineKind? = nil
    @State private var endingSymptom: Symptom?

    /// 默认无参;从首页「我的报告档案」进入时传 `.report` 预选分类 chip。
    /// 仅在视图创建时生效(RootView 切 tab 会重建 ArchiveListView)。
    init(initialFilter: TimelineKind? = nil) {
        _filter = State(initialValue: initialFilter)
    }
    @State private var selectedEntry: TimelineEntry?
    @State private var selectedGroup: IndicatorGroup?
    @State private var route: Route?

    /// 顶部搜索:点放大镜展开搜索框,按条目标题(指标/报告/症状/日记名)实时过滤,与分类 chip 叠加。
    @State private var searching = false
    @State private var query = ""

    @MainActor
    private var allEntries: [TimelineEntry] {
        let mapped =
            TimelineEntry.aggregatedIndicators(indicators) +
            reports.map(TimelineEntry.from(report:)) +
            diaries.map(TimelineEntry.from(diary:)) +
            symptoms.map(TimelineEntry.from(symptom:))
        let byKind = filter.map { kind in mapped.filter { $0.kind == kind } } ?? mapped
        let q = query.trimmingCharacters(in: .whitespaces)
        let byQuery = q.isEmpty ? byKind : byKind.filter { $0.title.localizedCaseInsensitiveContains(q) }
        return byQuery.sorted { $0.date > $1.date }
    }

    var body: some View {
        NavigationStack {
            content
                .navigationDestination(item: $route) { route in
                    switch route {
                    case .exports:           HealthExportListView()
                    case .reminders:         RemindersListView()
                    case .medicationLibrary: MedicationLibraryView()
                    }
                }
        }
    }

    private var content: some View {
        // 聚合(含血压配对 O(m²))+ 分类/搜索过滤在一次 body 内只算一次。原先 .isEmpty、分组、
        // 计数各调一遍 allEntries,等于全表聚合三次;搜索时每次按键都翻三倍,这里收敛成一次。
        let entries = allEntries
        let groups = TimelineGrouping.group(entries)
        return VStack(alignment: .leading, spacing: 0) {
            header(total: entries.count)
                .padding(.horizontal, 20)
                .padding(.top, 8)
                .padding(.bottom, 14)

            if reminderTotal > 0 {
                reminderBoard
                    .padding(.horizontal, 20)
                    .padding(.bottom, 10)
            }

            // 药品库入口:始终显示——它是「管理常用药」的浏览/管理目的地,空库时也要能找到来添加。
            medicationBoard
                .padding(.horizontal, 20)
                .padding(.bottom, 14)

            filterChips
                .padding(.bottom, searching ? 10 : 14)

            if searching {
                searchField
                    .padding(.horizontal, 20)
                    .padding(.bottom, 14)
            }

            if entries.isEmpty {
                emptyState
            } else {
                ScrollView(showsIndicators: false) {
                    LazyVStack(alignment: .leading, spacing: 18, pinnedViews: [.sectionHeaders]) {
                        ForEach(groups, id: \.section) { group in
                            Section {
                                VStack(spacing: 10) {
                                    ForEach(group.items) { entry in
                                        rowView(for: entry)
                                    }
                                }
                                .padding(.horizontal, 20)
                            } header: {
                                sectionHeader(group.section, count: group.items.count)
                            }
                        }
                    }
                    .padding(.bottom, 24)
                }
            }
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading)
        .background(Tj.Palette.sand.ignoresSafeArea())
        .sheet(item: $endingSymptom) { sym in
            SymptomEndSheet(symptom: sym)
        }
        .sheet(item: $selectedEntry) { entry in
            if let d = detail(for: entry) {
                TimelineEntryDetailView(detail: d)
            }
        }
        .sheet(item: $selectedGroup) { group in
            IndicatorSeriesDetailView(group: group)
        }
    }

    @ViewBuilder
    private func rowView(for entry: TimelineEntry) -> some View {
        if entry.kind == .symptom, entry.isOngoing,
           let sym = symptoms.first(where: { "symptom-\($0.persistentModelID)" == entry.id }) {
            // 进行中症状:点 → 标记结束 sheet(沿用原交互)
            Button {
                endingSymptom = sym
            } label: {
                TimelineRow(entry: entry)
            }
            .buttonStyle(.plain)
        } else {
            // 其余条目:指标 → 同类聚合详情(横向翻页 + 趋势);报告/日记/已结束症状 → 只读详情
            Button {
                guard let d = detail(for: entry) else { return }
                switch d {
                case .indicator(let i):           selectedGroup = IndicatorGroup.of(i)
                case .bloodPressure(let sys, _):  selectedGroup = IndicatorGroup.of(sys)
                default:                          selectedEntry = entry
                }
            } label: {
                TimelineRow(entry: entry)
            }
            .buttonStyle(.plain)
        }
    }

    /// 把时间线条目反查回源记录。逻辑统一收敛到 `TimelineDetail.resolve`(主页/档案库共用)。
    private func detail(for entry: TimelineEntry) -> TimelineDetail? {
        TimelineDetail.resolve(for: entry,
                               indicators: indicators, reports: reports,
                               diaries: diaries, symptoms: symptoms)
    }

    private func header(total: Int) -> some View {
        HStack(alignment: .lastTextBaseline) {
            Text("记录")
                .font(.tjTitle(26))
                .foregroundStyle(Tj.Palette.text)
            Text(total == 0 ? "" : String(appLoc: "\(total) 条"))
                .font(.tjScaled( 12))
                .foregroundStyle(Tj.Palette.text3)
            Spacer()
            if !exports.isEmpty {
                Button { route = .exports } label: {
                    HStack(spacing: 6) {
                        Image(systemName: "clock.arrow.circlepath")
                            .font(.tjScaled( 12, weight: .semibold))
                        Text("导出历史")
                            .font(.tjScaled( 13, weight: .semibold))
                    }
                    .foregroundStyle(Tj.Palette.paper)
                    .padding(.horizontal, 12)
                    .padding(.vertical, 7)
                    .background(Capsule().fill(Tj.Palette.ink))
                }
                .buttonStyle(.plain)
            }
            searchToggle
        }
    }

    private var searchToggle: some View {
        Button {
            withAnimation(.easeInOut(duration: 0.18)) {
                searching.toggle()
                if !searching { query = "" }
            }
        } label: {
            Image(systemName: searching ? "xmark" : "magnifyingglass")
                .font(.tjScaled( 14, weight: .semibold))
                .foregroundStyle(Tj.Palette.text)
                .frame(width: 32, height: 32)
                .background(Circle().fill(Tj.Palette.sand2))
        }
        .buttonStyle(.plain)
        .accessibilityLabel(searching ? String(appLoc: "关闭搜索") : String(appLoc: "搜索记录"))
    }

    private var searchField: some View {
        HStack(spacing: 8) {
            Image(systemName: "magnifyingglass")
                .font(.tjScaled( 13))
                .foregroundStyle(Tj.Palette.text3)
            TextField(String(appLoc: "搜索指标 / 报告 / 症状名"), text: $query)
                .textInputAutocapitalization(.never)
                .autocorrectionDisabled()
                .foregroundStyle(Tj.Palette.text)
                .tint(Tj.Palette.ink)
            if !query.isEmpty {
                Button { query = "" } label: {
                    Image(systemName: "xmark.circle.fill")
                        .foregroundStyle(Tj.Palette.text3)
                }
                .buttonStyle(.plain)
            }
        }
        .padding(.horizontal, 12)
        .padding(.vertical, 10)
        .background(
            RoundedRectangle(cornerRadius: Tj.Radius.sm, style: .continuous)
                .fill(Tj.Palette.paper)
        )
        .overlay(
            RoundedRectangle(cornerRadius: Tj.Radius.sm, style: .continuous)
                .strokeBorder(Tj.Palette.line, lineWidth: 1)
        )
    }

    // MARK: - 提醒任务汇总卡

    /// 两类提醒(自由 + 指标记录)合计,含已关闭。
    private var reminderTotal: Int { customReminders.count + metricReminders.count }
    private var reminderEnabledCount: Int {
        customReminders.filter(\.enabled).count + metricReminders.filter(\.enabled).count
    }

    /// 按 updatedAt 倒序合并,取前 3 条标题做预览(标题是用户数据,不本地化)。
    private var reminderTitlePreview: [String] {
        let merged: [(title: String, at: Date)] =
            customReminders.map { ($0.title, $0.updatedAt) } +
            metricReminders.map { ($0.displayName, $0.updatedAt) }
        return merged.sorted { $0.at > $1.at }.prefix(3).map(\.title)
    }

    private var reminderCountLabel: String {
        reminderEnabledCount == reminderTotal
            ? String(appLoc: "\(reminderTotal) 个提醒任务")
            : String(appLoc: "\(reminderTotal) 个提醒任务 · \(reminderEnabledCount) 个开启中")
    }

    private var reminderTitleLine: String {
        let joined = reminderTitlePreview.joined(separator: " · ")
        return reminderTotal > reminderTitlePreview.count ? joined + " …" : joined
    }

    /// 点击进提醒中心(RemindersListView)统一管理;卡片本身只展示。
    private var reminderBoard: some View {
        Button { route = .reminders } label: {
            HStack(spacing: 12) {
                ZStack {
                    Circle().fill(reminderEnabledCount > 0 ? Tj.Palette.amber.opacity(0.25) : Tj.Palette.sand2)
                    Image(systemName: "bell.fill")
                        .font(.tjScaled( 16))
                        .foregroundStyle(reminderEnabledCount > 0 ? Tj.Palette.ink : Tj.Palette.text3)
                }
                .frame(width: 36, height: 36)

                VStack(alignment: .leading, spacing: 2) {
                    Text(reminderCountLabel)
                        .font(.tjScaled( 15, weight: .semibold))
                        .foregroundStyle(Tj.Palette.text)
                        .lineLimit(1)
                    if !reminderTitlePreview.isEmpty {
                        Text(reminderTitleLine)
                            .font(.tjScaled( 12))
                            .foregroundStyle(Tj.Palette.text3)
                            .lineLimit(1)
                    }
                }

                Spacer(minLength: 0)

                Image(systemName: "chevron.right")
                    .font(.tjScaled( 12, weight: .semibold))
                    .foregroundStyle(Tj.Palette.text3)
            }
            .padding(14)
            .contentShape(Rectangle())
            .tjCard()
        }
        .buttonStyle(.plain)
    }

    // MARK: - 药品库入口卡

    /// 主标题:空库「药品库」,有药「药品库 · N 种常用药」。
    private var medicationCountLabel: String {
        medications.isEmpty
            ? String(appLoc: "药品库")
            : String(appLoc: "药品库 · \(medications.count) 种常用药")
    }

    /// 副标题:空库给引导文案;有药取前 3 个药名预览(药名是用户数据,不本地化)。
    private var medicationPreviewLine: String {
        if medications.isEmpty { return String(appLoc: "拍药盒或手动添加常用药") }
        let names = medications.prefix(3).map(\.name).joined(separator: " · ")
        return medications.count > 3 ? names + " …" : names
    }

    /// 点击进药品库(MedicationLibraryView,push 形态)统一管理;卡片本身只展示。
    private var medicationBoard: some View {
        Button { route = .medicationLibrary } label: {
            HStack(spacing: 12) {
                ZStack {
                    Circle().fill(medications.isEmpty ? Tj.Palette.sand2 : Tj.Palette.leafSoft)
                    Image(systemName: "pills.fill")
                        .font(.tjScaled( 16))
                        .foregroundStyle(medications.isEmpty ? Tj.Palette.text3 : Tj.Palette.ink)
                }
                .frame(width: 36, height: 36)

                VStack(alignment: .leading, spacing: 2) {
                    Text(medicationCountLabel)
                        .font(.tjScaled( 15, weight: .semibold))
                        .foregroundStyle(Tj.Palette.text)
                        .lineLimit(1)
                    Text(medicationPreviewLine)
                        .font(.tjScaled( 12))
                        .foregroundStyle(Tj.Palette.text3)
                        .lineLimit(1)
                }

                Spacer(minLength: 0)

                Image(systemName: "chevron.right")
                    .font(.tjScaled( 12, weight: .semibold))
                    .foregroundStyle(Tj.Palette.text3)
            }
            .padding(14)
            .contentShape(Rectangle())
            .tjCard()
        }
        .buttonStyle(.plain)
    }

    private var filterChips: some View {
        ScrollView(.horizontal, showsIndicators: false) {
            HStack(spacing: 8) {
                chip(label: String(appLoc: "全部"), selected: filter == nil) { filter = nil }
                ForEach(TimelineKind.allCases) { kind in
                    chip(label: kind.label, selected: filter == kind) {
                        filter = filter == kind ? nil : kind
                    }
                }
            }
            .padding(.horizontal, 20)
        }
    }

    private func chip(label: String, selected: Bool, action: @escaping () -> Void) -> some View {
        Button(action: action) {
            Text(label)
                .font(.tjScaled( 13, weight: selected ? .semibold : .regular))
                .foregroundStyle(selected ? Tj.Palette.paper : Tj.Palette.text)
                .padding(.horizontal, 14)
                .padding(.vertical, 8)
                .background(
                    Capsule().fill(selected ? Tj.Palette.ink : Tj.Palette.paper)
                )
                .overlay(
                    Capsule().strokeBorder(Tj.Palette.line, lineWidth: selected ? 0 : 1)
                )
        }
        .buttonStyle(.plain)
    }

    private func sectionHeader(_ section: DateSection, count: Int) -> some View {
        HStack {
            Text(section.label)
                .font(.tjScaled( 12, weight: .semibold))
                .tracking(0.5)
                .foregroundStyle(Tj.Palette.text2)
            Rectangle()
                .fill(Tj.Palette.lineSoft)
                .frame(height: 1)
            Text("\(count)")
                .font(.tjScaled( 11, design: .monospaced))
                .foregroundStyle(Tj.Palette.text3)
        }
        .padding(.horizontal, 20)
        .padding(.vertical, 8)
        .background(Tj.Palette.sand)
    }

    private var emptyState: some View {
        let q = query.trimmingCharacters(in: .whitespaces)
        let isSearchMiss = !q.isEmpty
        return VStack(spacing: 14) {
            Spacer()
            TjPlaceholder(label: isSearchMiss
                          ? String(appLoc: "没有匹配「\(q)」的记录")
                          : String(appLoc: "还没有任何记录\n点底部 + 号开始"))
                .frame(width: 240, height: 140)
            if !isSearchMiss {
                Text(filter == nil ? String(appLoc: "记录会按时间归类显示") : String(appLoc: "这个类别下没有记录"))
                    .font(.tjScaled( 13))
                    .foregroundStyle(Tj.Palette.text3)
            }
            Spacer()
        }
        .frame(maxWidth: .infinity)
    }
}

#Preview {
    ArchiveListView()
        .modelContainer(for: [
            Indicator.self, Report.self, DiaryEntry.self, Symptom.self, Asset.self,
            HealthExport.self, ChatTurn.self, UserProfile.self,
            MetricReminder.self, CustomMonitorMetric.self
        ], inMemory: true)
}
