import SwiftUI

struct EntryListView: View {
    @Bindable var vm: ReaderViewModel
    var isCardView: Bool = true

    // Scroll-based read tracking — all driven from per-row GeometryReader
    @State private var lastKnownMinY: [Int: CGFloat] = [:]  // entry.id → last minY
    @State private var trackingActive = false
    @State private var scrollingDown = false
    @State private var cumulativeDown: CGFloat = 0
    @State private var cumulativeUp: CGFloat = 0
    @State private var markedByScroll: Set<Int> = []

    // Viewport height — measured once from screen bounds.
    // Safe because this view only appears on iPhone in portrait/landscape.
    private var viewportHeight: CGFloat { UIScreen.main.bounds.height }

    // Fixed threshold — per-entry deltas are small (~1-2pt each),
    // so 100pt accumulates after scrolling roughly one screenful.
    private let activationThreshold: CGFloat = 100

    var body: some View {
        if vm.isLoading && vm.entries.isEmpty {
            LoadingView()
                .frame(maxWidth: .infinity, maxHeight: .infinity)
        } else if vm.entries.isEmpty {
            EmptyStateView(
                icon: "newspaper",
                title: "No articles",
                subtitle: vm.currentFilter == .starred
                    ? "Star articles to save them here"
                    : "All caught up!"
            )
            .frame(maxWidth: .infinity, maxHeight: .infinity)
        } else {
            ScrollView {
                if isCardView {
                    cardLayout
                } else {
                    listLayout
                }
            }
            .coordinateSpace(name: "readerScroll")
            .onAppear {
                // Reset on every appear (including back from article)
                trackingActive = false
                scrollingDown = false
                cumulativeDown = 0
                cumulativeUp = 0
                lastKnownMinY.removeAll()
            }
            .refreshable {
                await vm.refresh()
            }
            .navigationDestination(for: ReaderEntry.self) { entry in
                ArticleView(entry: entry, vm: vm)
            }
        }
    }

    // MARK: - Scroll-Read Tracking (per-row GeometryReader)

    private func scrollTracked(_ entry: ReaderEntry, content: some View) -> some View {
        content
            .background(
                GeometryReader { geo in
                    let frame = geo.frame(in: .named("readerScroll"))
                    Color.clear
                        .onChange(of: frame.minY) { _, newMinY in
                            let entryId = entry.id
                            let entryHeight = frame.height
                            guard entryHeight > 0 else { return }

                            // --- Scroll direction + activation ---
                            let prevMinY = lastKnownMinY[entryId]
                            if let prev = prevMinY {
                                let delta = prev - newMinY // positive = scrolling down
                                if delta > 0 {
                                    cumulativeDown += delta
                                    cumulativeUp = 0 // reset upward counter
                                    if cumulativeDown > activationThreshold {
                                        trackingActive = true
                                    }
                                    scrollingDown = true
                                } else if delta < -0.5 {
                                    cumulativeUp += -delta
                                    // Only flip direction after 30pt of upward scroll
                                    // (prevents jitter from tiny floating point noise)
                                    if cumulativeUp > 30 {
                                        scrollingDown = false
                                    }
                                }
                            }
                            lastKnownMinY[entryId] = newMinY

                            // --- Mark-as-read ---
                            // LazyVStack destroys views at ~maxY=0, so use maxY<30.
                            guard trackingActive,
                                  scrollingDown,
                                  !entry.isRead,
                                  !markedByScroll.contains(entryId),
                                  frame.maxY < 30 else { return }

                            markedByScroll.insert(entryId)

                            if let idx = vm.entries.firstIndex(where: { $0.id == entryId }) {
                                vm.entries[idx].status = "read"
                            }

                            Task {
                                let api = ReaderAPI()
                                try? await api.markEntries(ids: [entryId], status: "read")
                                vm.counters = try? await api.getCounters()
                            }
                        }
                }
            )
    }

    // MARK: - Card Layout

    private var cardLayout: some View {
        LazyVStack(spacing: 12) {
            ForEach(vm.entries) { entry in
                scrollTracked(entry,
                    content: NavigationLink(value: entry) {
                        EntryCardView(entry: entry)
                    }
                    .buttonStyle(.plain)
                    .contentShape(Rectangle())
                    .contextMenu {
                        entryContextMenu(entry: entry, vm: vm)
                    }
                )
            }

            loadMoreTrigger

            Spacer(minLength: 80)
        }
        .padding(.horizontal)
        .padding(.top, 4)
    }

    // MARK: - List Layout

    private var listLayout: some View {
        LazyVStack(spacing: 0) {
            ForEach(vm.entries) { entry in
                scrollTracked(entry,
                    content: NavigationLink(value: entry) {
                        EntryRowView(entry: entry)
                    }
                    .buttonStyle(.plain)
                    .contentShape(Rectangle())
                    .contextMenu {
                        entryContextMenu(entry: entry, vm: vm)
                    }
                )

                Divider()
                    .padding(.leading, 36)
            }

            loadMoreTrigger

            Spacer(minLength: 80)
        }
    }

    private var loadMoreTrigger: some View {
        Group {
            if vm.isLoadingMore {
                ProgressView()
                    .padding()
            } else {
                Color.clear
                    .frame(height: 1)
                    .onAppear {
                        Task { await vm.loadMore() }
                    }
            }
        }
    }
}

// MARK: - Card View

struct EntryCardView: View {
    let entry: ReaderEntry

    var body: some View {
        VStack(alignment: .leading, spacing: 0) {
            if let thumbURL = entry.thumbnailURL {
                AsyncImage(url: thumbURL) { phase in
                    switch phase {
                    case .success(let image):
                        image
                            .resizable()
                            .aspectRatio(contentMode: .fill)
                            .frame(height: 180)
                            .clipped()
                    default:
                        Rectangle()
                            .fill(Color.surfaceCard)
                            .frame(height: 180)
                    }
                }
            }

            VStack(alignment: .leading, spacing: 8) {
                HStack(spacing: 6) {
                    if !entry.isRead {
                        Circle()
                            .fill(Color.accentWarm)
                            .frame(width: 6, height: 6)
                    }

                    Text(entry.feedName)
                        .font(.caption.weight(.semibold))
                        .foregroundStyle(Color.accentWarm)
                        .lineLimit(1)

                    Spacer()

                    if !entry.timeAgo.isEmpty {
                        Text(entry.timeAgo)
                            .font(.caption)
                            .foregroundStyle(Color.textTertiary)
                    }
                }

                Text(entry.displayTitle)
                    .font(.subheadline.weight(entry.isRead ? .medium : .bold))
                    .foregroundStyle(entry.isRead ? Color.textSecondary : Color.textPrimary)
                    .lineLimit(3)

                HStack(spacing: 8) {
                    if let author = entry.author, !author.isEmpty {
                        Text(author)
                            .font(.caption)
                            .foregroundStyle(Color.textTertiary)
                            .lineLimit(1)
                    }

                    Spacer()

                    Label(entry.readingTimeText, systemImage: "clock")
                        .font(.caption)
                        .foregroundStyle(Color.textTertiary)

                    if entry.starred {
                        Image(systemName: "star.fill")
                            .font(.caption)
                            .foregroundStyle(.orange)
                    }
                }
            }
            .padding(14)
        }
        .background(Color.surfaceCard)
        .clipShape(RoundedRectangle(cornerRadius: 14))
        .shadow(color: .black.opacity(0.04), radius: 6, y: 2)
    }
}

// MARK: - List Row View

struct EntryRowView: View {
    let entry: ReaderEntry

    var body: some View {
        HStack(alignment: .top, spacing: 12) {
            Circle()
                .fill(entry.isRead ? Color.clear : Color.accentWarm)
                .frame(width: 8, height: 8)
                .padding(.top, 6)

            VStack(alignment: .leading, spacing: 4) {
                Text(entry.displayTitle)
                    .font(.subheadline.weight(entry.isRead ? .regular : .semibold))
                    .foregroundStyle(entry.isRead ? Color.textSecondary : Color.textPrimary)
                    .lineLimit(2)

                HStack(spacing: 6) {
                    Text(entry.feedName)
                        .font(.caption.weight(.medium))
                        .foregroundStyle(Color.accentWarm)
                        .lineLimit(1)

                    if !entry.timeAgo.isEmpty {
                        Text("\u{2022}")
                            .font(.caption2)
                            .foregroundStyle(Color.textTertiary)
                        Text(entry.timeAgo)
                            .font(.caption)
                            .foregroundStyle(Color.textTertiary)
                    }

                    Text("\u{2022}")
                        .font(.caption2)
                        .foregroundStyle(Color.textTertiary)
                    Text(entry.readingTimeText)
                        .font(.caption)
                        .foregroundStyle(Color.textTertiary)
                }

                if let author = entry.author, !author.isEmpty {
                    Text(author)
                        .font(.caption)
                        .foregroundStyle(Color.textTertiary)
                        .lineLimit(1)
                }
            }

            Spacer()

            if let thumbURL = entry.thumbnailURL {
                AsyncImage(url: thumbURL) { phase in
                    switch phase {
                    case .success(let image):
                        image
                            .resizable()
                            .aspectRatio(contentMode: .fill)
                            .frame(width: 56, height: 56)
                            .clipShape(RoundedRectangle(cornerRadius: 8))
                    default:
                        EmptyView()
                    }
                }
            } else if entry.starred {
                Image(systemName: "star.fill")
                    .font(.caption)
                    .foregroundStyle(.orange)
                    .padding(.top, 4)
            }
        }
        .padding(.horizontal, 16)
        .padding(.vertical, 12)
    }
}

// MARK: - Shared Context Menu

@ViewBuilder
private func entryContextMenu(entry: ReaderEntry, vm: ReaderViewModel) -> some View {
    Button {
        Task { await vm.toggleRead(entry) }
    } label: {
        Label(
            entry.isRead ? "Mark Unread" : "Mark Read",
            systemImage: entry.isRead ? "envelope.badge" : "envelope.open"
        )
    }

    Button {
        Task { await vm.toggleStar(entry) }
    } label: {
        Label(
            entry.starred ? "Unstar" : "Star",
            systemImage: entry.starred ? "star.slash" : "star"
        )
    }

    if entry.url != nil {
        Button {
            Task { await vm.saveToBrain(entry) }
        } label: {
            Label("Save to Brain", systemImage: "brain")
        }
    }
}
