import SwiftUI

struct LibraryItemCell: View {
    @Environment(AppState.self) private var app
    let item: LibraryItem

    var body: some View {
        VStack(alignment: .leading, spacing: 2) {
            ZStack(alignment: .bottom) {
                ZStack(alignment: .topTrailing) {
                    cover
                    downloadBadge.padding(4)
                }
                CoverProgressBar(fraction: app.progressFraction(itemId: item.id, episodeId: item.episodeId))
                    .padding(.horizontal, 3)
                    .padding(.bottom, 3)
            }
            Text(item.title)
                #if os(iOS)
                .font(.system(size: 11, weight: .bold))
                #else
                .font(.headline)
                #endif
                .lineLimit(2)
                .multilineTextAlignment(.leading)
            Text(item.author)
                .font(.system(size: 9))
                .foregroundStyle(.secondary)
                .lineLimit(1)
        }
        // Ensure the cell fills its full grid column width
        .frame(maxWidth: .infinity, alignment: .leading)
        .contextMenu { downloadMenuItems }
    }

    // MARK: - Cover

    private var cover: some View {
        #if os(iOS)
        iOSCover
        #else
        macosCover
        #endif
    }

    #if os(iOS)
    private var iOSCover: some View {
        Color(.systemGray6)              // neutral bg for PNG transparent areas
            .frame(maxWidth: .infinity)  // explicitly fill the column width
            .aspectRatio(1, contentMode: .fit)
            .overlay {
                if let url = app.client.coverURL(itemId: item.id) {
                    AsyncImage(url: url) { image in
                        image.resizable().scaledToFill()
                    } placeholder: {
                        ProgressView().tint(.accentColor)
                    }
                    .clipped()          // clip image overflow before rounding
                } else {
                    Image(systemName: "book.closed")
                        .foregroundStyle(.secondary)
                }
            }
            .clipShape(RoundedRectangle(cornerRadius: 8))
    }
    #endif

    #if os(macOS)
    private var macosCover: some View {
        Group {
            if let url = app.client.coverURL(itemId: item.id) {
                AsyncImage(url: url) { phase in
                    switch phase {
                    case .empty:
                        Rectangle().fill(.quaternary)
                            .overlay(ProgressView().controlSize(.small))
                    case .success(let img):
                        img.resizable().aspectRatio(contentMode: .fill)
                    case .failure:
                        Rectangle().fill(.quaternary)
                            .overlay(Image(systemName: "book.closed").foregroundStyle(.secondary))
                    @unknown default:
                        Rectangle().fill(.quaternary)
                    }
                }
            } else {
                Rectangle().fill(.quaternary)
            }
        }
        .frame(width: 180, height: 180)
        .clipShape(RoundedRectangle(cornerRadius: 8))
    }
    #endif

    // MARK: - Download badge

    @ViewBuilder
    private var downloadBadge: some View {
        let state = app.downloads.state(for: item.downloadKey)
        switch state {
        case .downloaded:
            Image(systemName: "checkmark.circle.fill")
                .foregroundStyle(.white, .green)
                .font(.title3)
                .shadow(radius: 2)
        case .downloading(let p):
            DownloadProgressRing(progress: p)
                #if os(iOS)
                .frame(width: 26, height: 26)
                #else
                .frame(width: 32, height: 32)
                #endif
        case .failed:
            Image(systemName: "exclamationmark.circle.fill")
                .foregroundStyle(.white, .red)
                .font(.title3)
                .shadow(radius: 2)
        case .notDownloaded:
            EmptyView()
        }
    }

    // MARK: - Context menu

    @ViewBuilder
    private var downloadMenuItems: some View {
        let key = item.downloadKey
        let state = app.downloads.state(for: key)
        if item.isPodcastContainer {
            Text("Episoden zum Download in der Podcast-Ansicht auswählen")
        } else {
            switch state {
            case .notDownloaded, .failed:
                Button {
                    app.downloads.startDownload(item: item)
                } label: {
                    Label("Für Offline herunterladen", systemImage: "arrow.down.circle")
                }
            case .downloading:
                Button {
                    app.downloads.cancel(downloadKey: key)
                } label: {
                    Label("Download abbrechen", systemImage: "xmark.circle")
                }
            case .downloaded:
                Button(role: .destructive) {
                    app.downloads.delete(downloadKey: key)
                } label: {
                    Label("Heruntergeladene Dateien löschen", systemImage: "trash")
                }
            }
        }
    }
}

// MARK: - Shared components

struct CoverProgressBar: View {
    let fraction: Double

    var body: some View {
        if fraction > 0 {
            GeometryReader { geo in
                ZStack(alignment: .leading) {
                    RoundedRectangle(cornerRadius: 2, style: .continuous)
                        .fill(Color.black.opacity(0.55))
                        .frame(height: 4)
                    RoundedRectangle(cornerRadius: 2, style: .continuous)
                        .fill(Color.accentColor)
                        .frame(width: max(2, geo.size.width * fraction), height: 4)
                }
            }
            .frame(height: 4)
            .shadow(color: .black.opacity(0.35), radius: 1, y: 1)
        }
    }
}

struct DownloadProgressRing: View {
    let progress: Double

    var body: some View {
        ZStack {
            Circle()
                .fill(Color.black.opacity(0.75))
            Circle()
                .stroke(Color.white.opacity(0.25), lineWidth: 3)
                .padding(4)
            Circle()
                .trim(from: 0, to: max(0.03, min(progress, 1)))
                .stroke(Color.accentColor, style: StrokeStyle(lineWidth: 3, lineCap: .round))
                .rotationEffect(.degrees(-90))
                .padding(4)
                .animation(.easeInOut(duration: 0.25), value: progress)
            Image(systemName: "arrow.down")
                .font(.system(size: 10, weight: .bold))
                .foregroundStyle(.white)
        }
        .shadow(color: .black.opacity(0.4), radius: 3, x: 0, y: 1)
    }
}
