import SwiftUI

struct TagebuchView: View {
    @Environment(ActiveDogStore.self) private var activeDog

    @State private var entries: [DiaryEntry] = []
    @State private var isLoading = false
    @State private var errorMessage: String?
    @State private var showAdd = false

    var body: some View {
        content
            .navigationTitle("Tagebuch")
            .navigationBarTitleDisplayMode(.inline)
            .toolbar {
                ToolbarItem(placement: .topBarTrailing) {
                    Button { showAdd = true } label: {
                        Image(systemName: "plus")
                    }
                    .disabled(activeDog.activeDog == nil)
                }
            }
            .sheet(isPresented: $showAdd) {
                if let dog = activeDog.activeDog {
                    AddDiaryEntrySheet(dogId: dog.id) { await load() }
                }
            }
            .task {
                if activeDog.dogs.isEmpty { await activeDog.loadDogs() }
                await load()
            }
            .refreshable { await load() }
    }

    @ViewBuilder
    private var content: some View {
        if activeDog.activeDog == nil {
            ContentUnavailableView(
                "Noch kein Hund",
                systemImage: "pawprint",
                description: Text("Lege deinen ersten Hund in der PWA an, dann kannst du Tagebucheinträge anlegen.")
            )
        } else if isLoading && entries.isEmpty {
            ProgressView()
        } else if let errorMessage, entries.isEmpty {
            ContentUnavailableView("Konnte nicht laden", systemImage: "wifi.slash", description: Text(errorMessage))
        } else if entries.isEmpty {
            ContentUnavailableView(
                "Noch keine Einträge",
                systemImage: "book",
                description: Text("Tippe oben rechts auf +, um deinen ersten Eintrag anzulegen.")
            )
        } else if let dog = activeDog.activeDog {
            List(entries) { entry in
                NavigationLink {
                    DiaryDetailView(dogId: dog.id, entry: entry) {
                        await load()
                    }
                } label: {
                    DiaryRow(entry: entry)
                }
            }
            .listStyle(.plain)
        }
    }

    private func load() async {
        guard let dog = activeDog.activeDog else { return }
        isLoading = true
        errorMessage = nil
        defer { isLoading = false }
        do {
            entries = try await APIClient.shared.get("/api/dogs/\(dog.id)/diary?limit=50")
        } catch let decodingError as DecodingError {
            errorMessage = Self.describe(decodingError)
            print("Tagebuch decode error: \(decodingError)")
        } catch {
            errorMessage = error.localizedDescription
        }
    }

    private static func describe(_ error: DecodingError) -> String {
        switch error {
        case .typeMismatch(let type, let ctx):
            return "Feldtyp falsch (\(type)) bei „\(ctx.codingPath.map(\.stringValue).joined(separator: "."))"
        case .valueNotFound(let type, let ctx):
            return "Feld fehlt (\(type)) bei „\(ctx.codingPath.map(\.stringValue).joined(separator: "."))"
        case .keyNotFound(let key, let ctx):
            return "Key fehlt: \(key.stringValue) bei „\(ctx.codingPath.map(\.stringValue).joined(separator: "."))"
        case .dataCorrupted(let ctx):
            return "Datenfehler bei „\(ctx.codingPath.map(\.stringValue).joined(separator: ".")): \(ctx.debugDescription)"
        @unknown default:
            return String(describing: error)
        }
    }
}

private struct DiaryRow: View {
    let entry: DiaryEntry

    var body: some View {
        VStack(alignment: .leading, spacing: 8) {
            HStack(alignment: .firstTextBaseline) {
                if entry.isMilestoneFlag || entry.typ == "meilenstein" {
                    Image(systemName: "star.fill").foregroundStyle(.orange)
                }
                if let titel = entry.titel, !titel.isEmpty {
                    Text(titel).font(.headline)
                } else {
                    Text("Eintrag").font(.headline).foregroundStyle(.secondary)
                }
                Spacer()
                if let datum = entry.datum {
                    Text(DiaryUtil.format(datum))
                        .font(.caption.monospacedDigit())
                        .foregroundStyle(.secondary)
                }
            }
            if let text = entry.text, !text.isEmpty {
                Text(text)
                    .font(.subheadline)
                    .lineLimit(3)
                    .foregroundStyle(.secondary)
            }
            if let loc = entry.locationName, !loc.isEmpty {
                Label(loc, systemImage: "mappin.and.ellipse")
                    .font(.caption)
                    .foregroundStyle(.tertiary)
            }
            if let media = entry.mediaItems, !media.isEmpty {
                ScrollView(.horizontal, showsIndicators: false) {
                    HStack(spacing: 6) {
                        ForEach(media) { m in
                            AsyncImage(url: URL(string: "https://banyaro.app\(m.url)")) { phase in
                                switch phase {
                                case .success(let img): img.resizable().scaledToFill()
                                default: Rectangle().fill(.gray.opacity(0.15))
                                }
                            }
                            .frame(width: 80, height: 80)
                            .clipShape(RoundedRectangle(cornerRadius: 8))
                        }
                    }
                }
            }
        }
        .padding(.vertical, 6)
    }
}

enum DiaryUtil {
    static func format(_ str: String) -> String {
        let parser = DateFormatter()
        parser.locale = Locale(identifier: "en_US_POSIX")
        parser.dateFormat = "yyyy-MM-dd"
        if let d = parser.date(from: String(str.prefix(10))) {
            let out = DateFormatter()
            out.locale = Locale(identifier: "de_DE")
            out.dateStyle = .medium
            return out.string(from: d)
        }
        return str
    }
}
