import Foundation
import Combine

// MARK: - ViewModel

@MainActor
final class ShareViewModel: ObservableObject {

    // MARK: Published state

    @Published var shelves:  [ShelfSummary]   = []
    @Published var books:    [BookSummary]    = []
    @Published var chapters: [ChapterSummary] = []

    @Published var selectedShelf:   ShelfSummary?
    @Published var selectedBook:    BookSummary?
    @Published var selectedChapter: ChapterSummary?

    @Published var pageTitle:     String = ""
    @Published var isLoading:     Bool   = false
    @Published var errorMessage:  String?
    @Published var isSaved:       Bool   = false

    // MARK: Read-only

    let sharedText:    String
    let isConfigured:  Bool
    let serverURL:     String

    // MARK: Private

    private let apiService: ShareAPIServiceProtocol
    private let defaults:   UserDefaults?

    private let lastShelfIDKey = "shareExtension.lastShelfID"
    private let lastBookIDKey  = "shareExtension.lastBookID"

    // MARK: Computed

    var isSaveDisabled: Bool {
        pageTitle.trimmingCharacters(in: .whitespaces).isEmpty
            || selectedBook == nil
            || isLoading
    }

    // MARK: - Init

    init(
        sharedText:   String,
        apiService:   ShareAPIServiceProtocol,
        serverURL:    String        = "",
        isConfigured: Bool          = true,
        defaults:     UserDefaults? = nil
    ) {
        self.sharedText   = sharedText
        self.isConfigured = isConfigured
        self.serverURL    = serverURL
        self.apiService   = apiService
        self.defaults     = defaults

        // Auto-populate title from the first non-empty line of the shared text.
        let firstLine = sharedText
            .components(separatedBy: .newlines)
            .first { !$0.trimmingCharacters(in: .whitespaces).isEmpty } ?? ""
        self.pageTitle = String(firstLine.prefix(100))
    }

    // MARK: - Actions

    /// Loads all shelves and restores the last used shelf/book selection.
    func loadShelves() async {
        isLoading    = true
        errorMessage = nil
        defer { isLoading = false }

        do {
            shelves = try await apiService.fetchShelves()

            // Restore last selected shelf
            let lastShelfID = defaults?.integer(forKey: lastShelfIDKey) ?? 0
            if lastShelfID != 0, let match = shelves.first(where: { $0.id == lastShelfID }) {
                await selectShelf(match)
            }
        } catch {
            errorMessage = error.localizedDescription
        }
    }

    func selectShelf(_ shelf: ShelfSummary) async {
        selectedShelf   = shelf
        selectedBook    = nil
        selectedChapter = nil
        books           = []
        chapters        = []
        defaults?.set(shelf.id, forKey: lastShelfIDKey)

        isLoading = true
        defer { isLoading = false }

        do {
            books = try await apiService.fetchBooks(shelfId: shelf.id)

            // Restore last selected book
            let lastBookID = defaults?.integer(forKey: lastBookIDKey) ?? 0
            if lastBookID != 0, let match = books.first(where: { $0.id == lastBookID }) {
                await selectBook(match)
            }
        } catch {
            errorMessage = error.localizedDescription
        }
    }

    func selectBook(_ book: BookSummary) async {
        selectedBook    = book
        selectedChapter = nil
        chapters        = []
        defaults?.set(book.id, forKey: lastBookIDKey)

        isLoading = true
        defer { isLoading = false }

        do {
            chapters = try await apiService.fetchChapters(bookId: book.id)
        } catch {
            errorMessage = error.localizedDescription
        }
    }

    func savePage() async {
        guard let book = selectedBook,
              !pageTitle.trimmingCharacters(in: .whitespaces).isEmpty else { return }

        isLoading    = true
        errorMessage = nil
        defer { isLoading = false }

        do {
            _ = try await apiService.createPage(
                bookId:    book.id,
                chapterId: selectedChapter?.id,
                title:     pageTitle.trimmingCharacters(in: .whitespaces),
                markdown:  sharedText
            )
            isSaved = true
        } catch {
            errorMessage = error.localizedDescription
        }
    }
}
