import SwiftUI

struct ArticleView: View {
    let entry: ReaderEntry
    @Bindable var vm: ReaderViewModel
    @State private var currentEntry: ReaderEntry
    @State private var isFetchingFull = false
    @State private var savedToBrain = false
    @State private var articleContent = ""

    init(entry: ReaderEntry, vm: ReaderViewModel) {
        self.entry = entry
        self.vm = vm
        _currentEntry = State(initialValue: entry)
        _articleContent = State(initialValue: entry.articleHTML)
    }

    var body: some View {
        Group {
            if articleContent.isEmpty {
                VStack {
                    Spacer()
                    ProgressView()
                        .controlSize(.regular)
                    Text("Loading article...")
                        .font(.caption)
                        .foregroundStyle(Color.textTertiary)
                        .padding(.top, 8)
                    Spacer()
                }
                .frame(maxWidth: .infinity, maxHeight: .infinity)
            } else {
                ArticleWebView(html: ArticleHTMLBuilder.build(
                    title: currentEntry.displayTitle,
                    url: currentEntry.url,
                    feedName: currentEntry.feedName,
                    author: currentEntry.author,
                    timeAgo: currentEntry.timeAgo,
                    readingTime: currentEntry.readingTimeText,
                    body: articleContent
                ))
                .ignoresSafeArea(edges: .bottom)
            }
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .background(Color.canvas)
        .navigationBarTitleDisplayMode(.inline)
        .toolbar {
            ToolbarItemGroup(placement: .topBarTrailing) {
                // Save to Brain
                if currentEntry.url != nil {
                    Button {
                        Task { await saveToBrain() }
                    } label: {
                        Image(systemName: savedToBrain ? "brain.filled.head.profile" : "brain.head.profile")
                            .foregroundStyle(savedToBrain ? Color.emerald : Color.textTertiary)
                    }
                }
            }
        }
        .task {
            let entryId = entry.id
            if let idx = vm.entries.firstIndex(where: { $0.id == entryId }),
               !vm.entries[idx].isRead {
                vm.entries[idx].status = "read"
            }
            currentEntry = vm.entries.first(where: { $0.id == entryId }) ?? currentEntry

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

            do {
                let fullEntry = try await ReaderAPI().getEntry(id: entryId)
                let fullHTML = fullEntry.articleHTML

                if !fullHTML.isEmpty && fullHTML.count > articleContent.count {
                    articleContent = fullHTML
                }

                var merged = fullEntry
                if let local = vm.entries.first(where: { $0.id == entryId }) {
                    merged.status = local.status
                    merged.starred = local.starred
                }
                currentEntry = merged
            } catch {}
        }
    }

    private func saveToBrain() async {
        let success = await vm.saveToBrain(currentEntry)
        if success {
            savedToBrain = true
        }
    }
}

// MARK: - HTML Builder

enum ArticleHTMLBuilder {
    private static let css = """
    * { box-sizing: border-box; }
    body {
        font-family: -apple-system, system-ui, sans-serif;
        font-size: 17px;
        line-height: 1.6;
        color: #1f1f1f;
        padding: 0 16px 60px;
        margin: 0;
        background: transparent;
        -webkit-text-size-adjust: 100%;
    }
    @media (prefers-color-scheme: dark) {
        body { color: #ede8e1; }
        a { color: #c79e40 !important; }
        pre, code { background: #1e1c1a !important; }
        blockquote { border-left-color: #c79e40; color: #9a9590; }
        td, th { border-color: #333; }
        .article-meta { color: #8a8580; }
        .article-title a { color: #ede8e1 !important; }
    }
    .article-header {
        padding: 16px 0 12px;
        border-bottom: 1px solid rgba(128,128,128,0.2);
        margin-bottom: 16px;
    }
    .article-title {
        font-size: 24px; font-weight: 700;
        line-height: 1.25; margin: 0 0 8px;
    }
    .article-title a {
        color: inherit;
        text-decoration: none;
        -webkit-tap-highlight-color: rgba(139,105,20,0.15);
    }
    .article-title a:active {
        opacity: 0.6;
    }
    .external-icon {
        font-size: 16px;
        opacity: 0.4;
        vertical-align: super;
        margin-left: 4px;
    }
    .article-meta {
        font-size: 13px; color: #8B6914; line-height: 1.4;
    }
    img { max-width: 100%; height: auto; max-height: 600px; object-fit: contain; border-radius: 8px; margin: 12px 0; }
    a { color: #8B6914; }
    h1, h2, h3, h4 { line-height: 1.3; margin-top: 24px; margin-bottom: 8px; }
    pre, code { background: #f5f0e8; border-radius: 6px; padding: 2px 6px; font-size: 15px; overflow-x: auto; }
    pre { padding: 12px; }
    pre code { padding: 0; background: none; }
    blockquote { border-left: 3px solid #8B6914; margin-left: 0; padding-left: 16px; color: #666; }
    figure { margin: 16px 0; }
    figcaption { font-size: 14px; color: #888; text-align: center; margin-top: 4px; }
    table { width: 100%; border-collapse: collapse; margin: 12px 0; }
    td, th { border: 1px solid #ddd; padding: 8px; text-align: left; }
    """

    static func build(
        title: String,
        url: String?,
        feedName: String,
        author: String?,
        timeAgo: String,
        readingTime: String,
        body: String
    ) -> String {
        let safeTitle = title
            .replacingOccurrences(of: "<", with: "&lt;")
            .replacingOccurrences(of: ">", with: "&gt;")
        let safeFeed = feedName
            .replacingOccurrences(of: "<", with: "&lt;")

        var metaParts = [safeFeed]
        if let author, !author.isEmpty { metaParts.append("by \(author)") }
        if !timeAgo.isEmpty { metaParts.append(timeAgo) }
        metaParts.append("\(readingTime) read")
        let meta = metaParts.joined(separator: " &middot; ")

        // Title is tappable link to original article (if URL exists)
        let titleHTML: String
        if let url, !url.isEmpty {
            let safeURL = url.replacingOccurrences(of: "\"", with: "&quot;")
            titleHTML = """
            <a href="\(safeURL)">\(safeTitle)<span class="external-icon">&nearr;</span></a>
            """
        } else {
            titleHTML = safeTitle
        }

        return """
        <!DOCTYPE html>
        <html>
        <head>
        <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
        <meta name="color-scheme" content="light dark">
        <style>\(css)</style>
        </head>
        <body>
        <div class="article-header">
        <h1 class="article-title">\(titleHTML)</h1>
        <div class="article-meta">\(meta)</div>
        </div>
        <div id="article-body">\(optimizeImages(body))</div>
        </body>
        </html>
        """
    }

    /// Add loading="lazy" and decoding="async" to all <img> tags.
    /// This tells WebKit to decode images off the main thread and
    /// only when they approach the viewport, preventing scroll freezes
    /// from large/mismatched-type images (e.g. WebP served as .jpeg).
    private static let imgTagRegex = try! NSRegularExpression(
        pattern: #"<img(?![^>]*loading=)([^>]*)>"#,
        options: .caseInsensitive
    )

    private static func optimizeImages(_ html: String) -> String {
        let range = NSRange(html.startIndex..., in: html)
        return imgTagRegex.stringByReplacingMatches(
            in: html,
            range: range,
            withTemplate: #"<img loading="lazy" decoding="async"$1>"#
        )
    }
}
