import SwiftUI
import SwiftData

/// 「记录 · 药品库」管理页:我有哪些药的 master 清单(药名 / 规格 / 用法 / 原图)。
/// 拍药盒识别或手动录入入库;某次服用流水另走「写日记 · 用药」(带 `DiaryEntry.medicationTag` 的日记,含剂量 + 时间)。
/// 列表 / 增删改范式照搬 `CustomMetricsListView`;编辑表单照搬 `CustomReminderEditSheet`。
struct MedicationLibraryView: View {
    @Environment(\.modelContext) private var ctx
    @Environment(\.dismiss) private var dismiss

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

    /// sheet 形态(从「记录」拉起)补「完成」按钮;push 形态不补,靠返回键。
    var presentedAsSheet: Bool = false

    @State private var editingTarget: MedicationEditTarget?
    @State private var showScan = false

    var body: some View {
        ScrollView {
            VStack(alignment: .leading, spacing: 12) {
                hintBanner
                if medications.isEmpty {
                    emptyState
                } else {
                    ForEach(medications) { m in
                        Button {
                            editingTarget = MedicationEditTarget(medication: m)
                        } label: {
                            row(m)
                        }
                        .buttonStyle(.plain)
                    }
                }
            }
            .padding(.horizontal, 16)
            .padding(.top, 8)
            .padding(.bottom, 32)
        }
        .background(Tj.Palette.sand.ignoresSafeArea())
        .navigationTitle("药品库")
        .navigationBarTitleDisplayMode(.inline)
        .toolbar {
            if presentedAsSheet {
                ToolbarItem(placement: .topBarLeading) {
                    Button(String(appLoc: "完成")) { dismiss() }
                }
            }
            ToolbarItem(placement: .topBarTrailing) {
                HStack(spacing: 16) {
                    Button { showScan = true } label: {
                        Image(systemName: "camera")
                            .font(.tjScaled( 16, weight: .semibold))
                    }
                    .accessibilityLabel(String(appLoc: "拍药盒添加"))
                    Button { editingTarget = MedicationEditTarget(medication: nil) } label: {
                        Image(systemName: "plus")
                            .font(.tjScaled( 16, weight: .semibold))
                    }
                    .accessibilityLabel(String(appLoc: "手动添加"))
                }
            }
        }
        .sheet(item: $editingTarget) { target in
            MedicationEditSheet(existing: target.medication)
        }
        .fullScreenCover(isPresented: $showScan) {
            // 拍药盒 → 本地 OCR + LLM 识别 → 核对 → 入药品库(含原图)。
            MedicationScanFlow(
                onSave: { meds, images in
                    MedicationArchiver.archive(medications: meds, images: images, in: ctx)
                },
                onClose: { showScan = false }
            )
        }
    }

    // MARK: - subviews

    private var hintBanner: some View {
        HStack(spacing: 10) {
            Image(systemName: "info.circle.fill")
                .foregroundStyle(Tj.Palette.text3)
            Text("药品库是你的常用药清单。记录某次服用请到「写日记 · 用药」,可填剂量和时间。")
                .font(.tjScaled( 12))
                .foregroundStyle(Tj.Palette.text2)
                .fixedSize(horizontal: false, vertical: true)
            Spacer(minLength: 0)
        }
        .padding(12)
        .background(
            RoundedRectangle(cornerRadius: Tj.Radius.sm, style: .continuous)
                .fill(Tj.Palette.sand2.opacity(0.5))
        )
    }

    private var emptyState: some View {
        VStack(spacing: 14) {
            Spacer(minLength: 40)
            TjPlaceholder(label: String(appLoc: "药品库还是空的"))
                .frame(width: 220, height: 130)
            Text("右上角拍药盒或 + 手动添加")
                .font(.tjScaled( 12))
                .foregroundStyle(Tj.Palette.text3)
            Spacer()
        }
        .frame(maxWidth: .infinity)
    }

    private func row(_ m: Medication) -> some View {
        HStack(spacing: 12) {
            ZStack {
                Circle().fill(Tj.Palette.leafSoft)
                Image(systemName: "pills.fill")
                    .font(.tjScaled( 17, weight: .medium))
                    .foregroundStyle(Tj.Palette.ink)
            }
            .frame(width: 40, height: 40)

            VStack(alignment: .leading, spacing: 3) {
                Text(m.name)
                    .font(.tjScaled( 15, weight: .semibold))
                    .foregroundStyle(Tj.Palette.text)
                    .lineLimit(1)
                if !m.detailLine.isEmpty {
                    Text(m.detailLine)
                        .font(.tjScaled( 11))
                        .foregroundStyle(Tj.Palette.text3)
                        .lineLimit(1)
                }
            }

            Spacer(minLength: 8)

            if !m.assets.isEmpty {
                Text("📷 \(m.assets.count)")
                    .font(.tjScaled( 11))
                    .foregroundStyle(Tj.Palette.text3)
            }
            Image(systemName: "chevron.right")
                .font(.tjScaled( 11, weight: .medium))
                .foregroundStyle(Tj.Palette.text3)
        }
        .padding(14)
        .background(
            RoundedRectangle(cornerRadius: Tj.Radius.md, style: .continuous)
                .fill(Tj.Palette.paper)
        )
        .overlay(
            RoundedRectangle(cornerRadius: Tj.Radius.md, style: .continuous)
                .strokeBorder(Tj.Palette.lineSoft, lineWidth: 1)
        )
    }
}

/// `medication == nil` → 新建;否则编辑。`id` 用 UUID 让同一对象重开 sheet 也能刷新。
private struct MedicationEditTarget: Identifiable {
    let id = UUID()
    let medication: Medication?
}

/// 药品库的新建 / 编辑表单(范式同 `CustomReminderEditSheet`:本地 @State 暂存,保存才写库)。
private struct MedicationEditSheet: View {
    @Environment(\.modelContext) private var ctx
    @Environment(\.dismiss) private var dismiss

    /// nil = 新建模式。
    let existing: Medication?

    @State private var name = ""
    @State private var strength = ""
    @State private var usage = ""
    @State private var note = ""
    @State private var hydrated = false
    /// 点缩略图全屏查看的起始页;nil = 未打开查看器。
    @State private var viewerStart: PhotoIndex?
    /// 「记录一次服用」:嵌套拉起 MedicationLogSheet,预选当前药。
    @State private var showLog = false
    @State private var showDeleteConfirm = false

    private var isEditing: Bool { existing != nil }
    private var canSave: Bool {
        !name.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
    }

    var body: some View {
        NavigationStack {
            Form {
                if isEditing {
                    Section {
                        Button { showLog = true } label: {
                            HStack(spacing: 10) {
                                Image(systemName: "pills.circle.fill")
                                    .font(.tjScaled( 18))
                                    .foregroundStyle(Tj.Palette.ink)
                                Text("记录一次服用")
                                    .font(.tjScaled( 15, weight: .semibold))
                                    .foregroundStyle(Tj.Palette.text)
                                Spacer()
                                Image(systemName: "chevron.right")
                                    .font(.tjScaled( 12, weight: .medium))
                                    .foregroundStyle(Tj.Palette.text3)
                            }
                            .contentShape(Rectangle())
                        }
                        .buttonStyle(.plain)
                    } footer: {
                        Text("记某次吃药的剂量和时间,会进「记录 · 用药」时间线。不提供剂量建议。")
                    }
                }

                if let m = existing, !m.assets.isEmpty {
                    Section {
                        ScrollView(.horizontal, showsIndicators: false) {
                            HStack(spacing: 10) {
                                ForEach(Array(m.assets.enumerated()), id: \.offset) { idx, asset in
                                    Button {
                                        viewerStart = PhotoIndex(index: idx)
                                    } label: {
                                        MedicationAssetThumb(asset: asset)
                                    }
                                    .buttonStyle(.plain)
                                }
                            }
                            .padding(.vertical, 4)
                        }
                        .listRowInsets(EdgeInsets(top: 8, leading: 12, bottom: 8, trailing: 12))
                    } header: {
                        Text(String(appLoc: "原图\(m.assets.count)张"))
                    } footer: {
                        Text("点图片可放大查看。原图均存在本机加密目录,不上传。")
                    }
                }

                Section {
                    TextField(String(appLoc: "药名,如:缬沙坦胶囊"), text: $name)
                        .foregroundStyle(Tj.Palette.text)
                    TextField(String(appLoc: "规格,如:80mg×7粒"), text: $strength)
                        .foregroundStyle(Tj.Palette.text2)
                    TextField(String(appLoc: "用法,如:一日一次,一次一粒"), text: $usage)
                        .foregroundStyle(Tj.Palette.text2)
                } footer: {
                    Text("仅作清单记录,不提供任何用药或剂量建议。")
                }

                Section {
                    TextField(String(appLoc: "备注(可选)"), text: $note, axis: .vertical)
                        .lineLimit(1...3)
                        .foregroundStyle(Tj.Palette.text2)
                }

                if isEditing {
                    Section {
                        Button(role: .destructive) { showDeleteConfirm = true } label: {
                            Label(String(appLoc: "从药品库删除"), systemImage: "trash")
                        }
                    }
                }
            }
            .scrollContentBackground(.hidden)
            .background(Tj.Palette.sand.ignoresSafeArea())
            .navigationTitle(isEditing ? String(appLoc: "编辑药品") : String(appLoc: "添加药品"))
            .navigationBarTitleDisplayMode(.inline)
            .toolbar {
                ToolbarItem(placement: .topBarLeading) {
                    Button(String(appLoc: "取消")) { dismiss() }
                }
                ToolbarItem(placement: .topBarTrailing) {
                    Button(String(appLoc: "保存")) { save() }
                        .fontWeight(.semibold)
                        .disabled(!canSave)
                }
            }
            .onAppear(perform: hydrate)
            .fullScreenCover(item: $viewerStart) { start in
                if let m = existing {
                    MedicationPhotoViewer(assets: m.assets, startIndex: start.index)
                }
            }
            .sheet(isPresented: $showLog) {
                MedicationLogSheet(preselected: existing)
            }
            .alert(String(appLoc: "从药品库删除这种药?"), isPresented: $showDeleteConfirm) {
                Button(String(appLoc: "删除"), role: .destructive) { deleteMedication() }
                Button(String(appLoc: "取消"), role: .cancel) { }
            } message: {
                Text("关联的原图会一并永久删除,无法恢复。")
            }
        }
    }

    private func hydrate() {
        guard !hydrated else { return }
        hydrated = true
        if let m = existing {
            name = m.name
            strength = m.strength
            usage = m.usage
            note = m.note ?? ""
        }
    }

    private func save() {
        guard canSave else { return }
        let n = name.trimmingCharacters(in: .whitespacesAndNewlines)
        let s = strength.trimmingCharacters(in: .whitespacesAndNewlines)
        let u = usage.trimmingCharacters(in: .whitespacesAndNewlines)
        let nt = note.trimmingCharacters(in: .whitespacesAndNewlines)
        if let m = existing {
            m.name = n
            m.strength = s
            m.usage = u
            m.note = nt.isEmpty ? nil : nt
            m.updatedAt = .now
        } else {
            let med = Medication(name: n, strength: s, usage: u, note: nt.isEmpty ? nil : nt)
            ctx.insert(med)
        }
        try? ctx.save()
        dismiss()
    }

    private func deleteMedication() {
        guard let m = existing else { return }
        // 先删 Vault 里的 JPEG(cascade 只删 Asset 记录,文件要手动 unlink,§6 永久删除)。
        for a in m.assets {
            try? FileVault.shared.remove(relativePath: a.relativePath)
        }
        ctx.delete(m)
        try? ctx.save()
        dismiss()
    }
}

// MARK: - 原图查看

/// 全屏查看器的起始页载体(`.fullScreenCover(item:)` 需 Identifiable)。
private struct PhotoIndex: Identifiable {
    let id = UUID()
    let index: Int
}

/// 药品库行内 / 编辑表单里的方形缩略图。原图从加密 Vault 同步读取(数量少,与 EvidenceImagePage 同款)。
private struct MedicationAssetThumb: View {
    let asset: Asset

    var body: some View {
        VaultImage(relativePath: asset.relativePath, maxPixel: 500) { img in
            Image(uiImage: img).resizable().scaledToFill()
        } placeholder: { isLoading in
            if isLoading {
                Tj.Palette.paper
            } else {
                TjPlaceholder(label: String(appLoc: "原图无法读取"))
            }
        }
        .frame(width: 150, height: 150)
        .clipped()
        .clipShape(RoundedRectangle(cornerRadius: Tj.Radius.sm, style: .continuous))
        .overlay(
            RoundedRectangle(cornerRadius: Tj.Radius.sm, style: .continuous)
                .strokeBorder(Tj.Palette.lineSoft, lineWidth: 1)
        )
    }
}

/// 全屏翻页查看药品原图(看清药盒小字)。
private struct MedicationPhotoViewer: View {
    @Environment(\.dismiss) private var dismiss
    let assets: [Asset]
    @State private var selection: Int

    init(assets: [Asset], startIndex: Int) {
        self.assets = assets
        _selection = State(initialValue: min(max(startIndex, 0), max(assets.count - 1, 0)))
    }

    var body: some View {
        ZStack(alignment: .topTrailing) {
            Color.black.ignoresSafeArea()

            TabView(selection: $selection) {
                ForEach(Array(assets.enumerated()), id: \.offset) { idx, asset in
                    VaultImage(relativePath: asset.relativePath, maxPixel: 2000) { img in
                        Image(uiImage: img).resizable().scaledToFit()
                    } placeholder: { isLoading in
                        if isLoading {
                            ProgressView().tint(.white)
                        } else {
                            TjPlaceholder(label: String(appLoc: "原图无法读取"))
                        }
                    }
                    .tag(idx)
                }
            }
            .tabViewStyle(.page(indexDisplayMode: assets.count > 1 ? .automatic : .never))
            .ignoresSafeArea()

            Button { dismiss() } label: {
                Image(systemName: "xmark")
                    .font(.tjScaled( 16, weight: .semibold))
                    .foregroundStyle(.white)
                    .frame(width: 36, height: 36)
                    .background(Circle().fill(.black.opacity(0.4)))
            }
            .padding(.trailing, 18)
            .padding(.top, 14)
        }
    }
}

#Preview {
    NavigationStack {
        MedicationLibraryView(presentedAsSheet: true)
    }
    .modelContainer(for: [Medication.self, Asset.self], inMemory: true)
}
