import SwiftUI
import WebKit

struct PageReaderView: View {
    let page: PageDTO
    @State private var webPage = WebPage()
    @State private var fullPage: PageDTO? = nil
    @State private var isLoadingPage = false
    @State private var comments: [CommentDTO] = []
    @State private var isLoadingComments = false
    @State private var showEditor = false
    @State private var isFetchingForEdit = false
    @State private var newComment = ""
    @State private var isPostingComment = false
    @State private var commentError: String? = nil
    @State private var commentsExpanded = false
    @AppStorage("showComments") private var showComments = true
    @Environment(\.colorScheme) private var colorScheme

    /// The resolved page — full version once fetched, summary until then.
    private var resolvedPage: PageDTO { fullPage ?? page }

    private var serverURL: String {
        UserDefaults.standard.string(forKey: "serverURL") ?? "https://bookstack.example.com"
    }

    var body: some View {
        VStack(spacing: 0) {
            // Page header
            VStack(alignment: .leading, spacing: 2) {
                Text(resolvedPage.name)
                    .font(.title2.bold())
                    .padding(.horizontal)
                    .padding(.top, 12)

                Text(String(format: L("library.updated"), resolvedPage.updatedAt.bookStackRelative))
                    .font(.footnote)
                    .foregroundStyle(.secondary)
                    .padding(.horizontal)
                    .padding(.bottom, 8)

                Divider()
            }

            // Web content — fills all space not taken by the comments inset
            WebView(webPage)
                .frame(maxWidth: .infinity, maxHeight: .infinity)
        }
        .safeAreaInset(edge: .bottom, spacing: 0) {
            // Comments panel sits above the tab bar, inside the safe area
            if showComments {
                VStack(spacing: 0) {
                    Divider()
                    // Header row — always visible, tap to expand/collapse
                    Button {
                        withAnimation(.easeInOut(duration: 0.2)) { commentsExpanded.toggle() }
                    } label: {
                        HStack {
                            Label(String(format: L("reader.comments"), comments.count),
                                  systemImage: "bubble.left.and.bubble.right")
                                .font(.subheadline.weight(.semibold))
                                .foregroundStyle(.primary)
                            Spacer()
                            Image(systemName: commentsExpanded ? "chevron.down" : "chevron.up")
                                .font(.caption.weight(.semibold))
                                .foregroundStyle(.secondary)
                        }
                        .padding(.horizontal)
                        .padding(.vertical, 10)
                    }
                    .buttonStyle(.plain)

                    // Expandable body
                    if commentsExpanded {
                        Divider()
                        commentsContent
                            .transition(.move(edge: .bottom).combined(with: .opacity))
                    }
                }
                .background(Color(.secondarySystemBackground))
            }
        }
        .navigationBarTitleDisplayMode(.inline)
        .toolbar {
            ToolbarItem(placement: .primaryAction) {
                Button {
                    Task { await openEditor() }
                } label: {
                    if isFetchingForEdit {
                        ProgressView().scaleEffect(0.7)
                    } else {
                        Image(systemName: "pencil")
                    }
                }
                .disabled(isFetchingForEdit)
                .accessibilityLabel(L("reader.edit"))
            }
            ToolbarItem(placement: .topBarTrailing) {
                Button {
                    let url = "\(serverURL)/books/\(resolvedPage.bookId)/page/\(resolvedPage.slug)"
                    let activity = UIActivityViewController(activityItems: [url], applicationActivities: nil)
                    if let window = UIApplication.shared.connectedScenes
                        .compactMap({ $0 as? UIWindowScene })
                        .first?.keyWindow {
                        window.rootViewController?.present(activity, animated: true)
                    }
                } label: {
                    Image(systemName: "square.and.arrow.up")
                }
                .accessibilityLabel(L("reader.share"))
            }
        }
        .fullScreenCover(isPresented: $showEditor) {
            NavigationStack {
                if let fullPage {
                    PageEditorView(mode: .edit(page: fullPage))
                }
            }
        }
        .task(id: page.id) {
            await loadFullPage()
            await loadComments()
        }
        .onChange(of: showEditor) { _, isShowing in
            // Reload page content after editor is dismissed
            if !isShowing { Task { await loadFullPage() } }
        }
        .onChange(of: colorScheme) {
            loadContent()
        }
    }

    // MARK: - Comments UI

    @ViewBuilder
    private var commentsContent: some View {
        VStack(spacing: 0) {
            // Scrollable comment list — fixed height so layout is stable
            ScrollViewReader { proxy in
                ScrollView {
                    VStack(alignment: .leading, spacing: 0) {
                        if isLoadingComments {
                            ProgressView()
                                .frame(maxWidth: .infinity)
                                .padding()
                        } else if comments.isEmpty {
                            Text(L("reader.comments.empty"))
                                .font(.footnote)
                                .foregroundStyle(.secondary)
                                .frame(maxWidth: .infinity)
                                .padding()
                        } else {
                            ForEach(comments) { comment in
                                CommentRow(comment: comment)
                                    .padding(.horizontal)
                                    .id(comment.id)
                                Divider().padding(.leading, 54)
                            }
                        }
                    }
                    .frame(maxWidth: .infinity)
                }
                .frame(height: 180)
                .onChange(of: comments.count) {
                    if let last = comments.last {
                        withAnimation { proxy.scrollTo(last.id, anchor: .bottom) }
                    }
                }
            }

            // Input — always visible at the bottom of the panel
            Divider()
            VStack(spacing: 4) {
                if let err = commentError {
                    Text(err)
                        .font(.caption)
                        .foregroundStyle(.red)
                        .frame(maxWidth: .infinity, alignment: .leading)
                        .padding(.horizontal)
                        .padding(.top, 4)
                }
                HStack(alignment: .bottom, spacing: 8) {
                    TextField(L("reader.comment.placeholder"), text: $newComment, axis: .vertical)
                        .lineLimit(1...3)
                        .padding(8)
                        .background(Color(.tertiarySystemBackground), in: RoundedRectangle(cornerRadius: 10))

                    Button {
                        Task { await postComment() }
                    } label: {
                        if isPostingComment {
                            ProgressView().controlSize(.small)
                        } else {
                            Image(systemName: "paperplane.fill")
                                .foregroundStyle(newComment.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty ? Color.secondary : Color.accentColor)
                        }
                    }
                    .disabled(newComment.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty || isPostingComment)
                    .accessibilityLabel("Post comment")
                }
                .padding(.horizontal)
                .padding(.vertical, 8)
            }
            .background(Color(.secondarySystemBackground))
        }
    }

    // MARK: - Helpers

    private func loadFullPage() async {
        isLoadingPage = true
        AppLog(.info, "Loading page content for '\(page.name)' (id: \(page.id))", category: "Reader")
        do {
            fullPage = try await BookStackAPI.shared.fetchPage(id: page.id)
            AppLog(.info, "Page content loaded for '\(page.name)'", category: "Reader")
        } catch {
            AppLog(.warning, "Failed to load full page '\(page.name)': \(error.localizedDescription) — using summary", category: "Reader")
            fullPage = page
        }
        isLoadingPage = false
        loadContent()
    }

    private func openEditor() async {
        // Full page is already fetched by loadFullPage; if still loading, wait briefly
        if fullPage == nil {
            isFetchingForEdit = true
            fullPage = (try? await BookStackAPI.shared.fetchPage(id: page.id)) ?? page
            isFetchingForEdit = false
        }
        showEditor = true
    }

    private func loadContent() {
        let html = buildHTML(content: resolvedPage.html ?? "<p><em>\(L("reader.nocontent"))</em></p>")
        webPage.load(html: html, baseURL: URL(string: serverURL) ?? URL(string: "https://bookstack.example.com")!)
    }

    private func loadComments() async {
        isLoadingComments = true
        comments = (try? await BookStackAPI.shared.fetchComments(pageId: page.id)) ?? []
        isLoadingComments = false
        // Auto-expand if there are comments
        if !comments.isEmpty { commentsExpanded = true }
    }

    private func postComment() async {
        let text = newComment.trimmingCharacters(in: .whitespacesAndNewlines)
        guard !text.isEmpty else { return }
        isPostingComment = true
        commentError = nil
        AppLog(.info, "Posting comment on page '\(page.name)' (id: \(page.id))", category: "Reader")
        do {
            try await BookStackAPI.shared.postComment(pageId: page.id, text: text)
            newComment = ""
            AppLog(.info, "Comment posted on '\(page.name)' — reloading", category: "Reader")
            await loadComments()
        } catch let e as BookStackError {
            commentError = e.localizedDescription
            AppLog(.error, "Failed to post comment on '\(page.name)': \(e.localizedDescription)", category: "Reader")
        } catch {
            commentError = error.localizedDescription
            AppLog(.error, "Failed to post comment on '\(page.name)': \(error.localizedDescription)", category: "Reader")
        }
        isPostingComment = false
    }

    private func buildHTML(content: String) -> String {
        let isDark = colorScheme == .dark
        let bg = isDark ? "#1c1c1e" : "#ffffff"
        let fg = isDark ? "#f2f2f7" : "#000000"
        let codeBg = isDark ? "#2c2c2e" : "#f2f2f7"
        let border = isDark ? "#3a3a3c" : "#d1d1d6"

        return """
        <!DOCTYPE html>
        <html>
        <head>
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <meta name="color-scheme" content="light dark">
        <style>
        * { box-sizing: border-box; }
        body {
            font-family: -apple-system, sans-serif;
            font-size: 16px;
            line-height: 1.6;
            padding: 16px;
            max-width: 800px;
            margin: 0 auto;
            background-color: \(bg);
            color: \(fg);
        }
        img { max-width: 100%; height: auto; border-radius: 6px; }
        pre {
            overflow-x: auto;
            padding: 14px;
            background: \(codeBg);
            border-radius: 10px;
            font-size: 14px;
        }
        code {
            font-family: "SF Mono", "Menlo", monospace;
            font-size: 14px;
            background: \(codeBg);
            padding: 2px 5px;
            border-radius: 4px;
        }
        pre code { background: transparent; padding: 0; }
        a { color: #0a84ff; text-decoration: none; }
        a:hover { text-decoration: underline; }
        blockquote {
            border-left: 4px solid #0a84ff;
            margin: 16px 0;
            padding: 8px 16px;
            color: #8e8e93;
        }
        table { border-collapse: collapse; width: 100%; margin: 16px 0; }
        th, td { border: 1px solid \(border); padding: 10px 12px; text-align: left; }
        th { background: \(codeBg); font-weight: 600; }
        h1, h2, h3, h4, h5, h6 { line-height: 1.3; }
        hr { border: none; border-top: 1px solid \(border); margin: 24px 0; }
        </style>
        </head>
        <body>\(content)</body>
        </html>
        """
    }
}

// MARK: - Comment Row

struct CommentRow: View {
    let comment: CommentDTO

    var body: some View {
        HStack(alignment: .top, spacing: 10) {
            Circle()
                .fill(.blue.gradient)
                .frame(width: 32, height: 32)
                .overlay {
                    Text(comment.createdBy.name.prefix(1).uppercased())
                        .font(.footnote.bold())
                        .foregroundStyle(.white)
                }
                .accessibilityHidden(true)

            VStack(alignment: .leading, spacing: 4) {
                HStack {
                    Text(comment.createdBy.name)
                        .font(.footnote.bold())
                    Spacer()
                    Text(comment.createdAt.bookStackRelative)
                        .font(.caption)
                        .foregroundStyle(.tertiary)
                }
                Text(comment.html.strippingHTML)
                    .font(.footnote)
                    .foregroundStyle(.secondary)
            }
        }
        .padding(.vertical, 4)
    }
}

#Preview {
    NavigationStack {
        PageReaderView(page: .mock)
    }
}
