import Foundation
import Observation

@Observable
final class LibraryViewModel {

    var shelves: [ShelfDTO] = []
    var books: [BookDTO] = []
    var chapters: [ChapterDTO] = []
    var pages: [PageDTO] = []

    var isLoadingShelves: Bool = false
    var isLoadingBooks: Bool = false
    var isLoadingContent: Bool = false

    var error: BookStackError? = nil

    // MARK: - Shelves

    func loadShelves() async {
        isLoadingShelves = true
        error = nil
        books = []
        chapters = []
        pages = []
        AppLog(.info, "Loading shelves", category: "Library")
        do {
            shelves = try await BookStackAPI.shared.fetchShelves()
            AppLog(.info, "Loaded \(shelves.count) shelf(ves)", category: "Library")
        } catch let e as BookStackError {
            AppLog(.error, "Failed to load shelves: \(e.localizedDescription)", category: "Library")
            error = e
        } catch {
            AppLog(.error, "Failed to load shelves: \(error.localizedDescription)", category: "Library")
            self.error = .unknown(error.localizedDescription)
        }
        isLoadingShelves = false
    }

    // MARK: - Books

    func loadBooks() async {
        isLoadingBooks = true
        error = nil
        shelves = []
        chapters = []
        pages = []
        do {
            books = try await BookStackAPI.shared.fetchBooks()
        } catch let e as BookStackError {
            error = e
        } catch {
            self.error = .unknown(error.localizedDescription)
        }
        isLoadingBooks = false
    }

    func loadBooksForShelf(shelfId: Int) async {
        isLoadingBooks = true
        error = nil
        shelves = []
        chapters = []
        pages = []
        do {
            let shelfDetail = try await BookStackAPI.shared.fetchShelf(id: shelfId)
            books = shelfDetail.books
        } catch let e as BookStackError {
            error = e
        } catch {
            self.error = .unknown(error.localizedDescription)
        }
        isLoadingBooks = false
    }

    // MARK: - Chapters + Pages

    func loadChaptersAndPages(bookId: Int) async {
        isLoadingContent = true
        error = nil
        shelves = []
        books = []
        AppLog(.info, "Loading chapters and pages for book \(bookId)", category: "Library")
        do {
            async let chaptersTask = BookStackAPI.shared.fetchChapters(bookId: bookId)
            async let pagesTask = BookStackAPI.shared.fetchPages(bookId: bookId)
            let (ch, pg) = try await (chaptersTask, pagesTask)
            chapters = ch
            pages = pg
            AppLog(.info, "Loaded \(ch.count) chapter(s), \(pg.count) page(s) for book \(bookId)", category: "Library")
        } catch let e as BookStackError {
            AppLog(.error, "Failed to load book \(bookId) content: \(e.localizedDescription)", category: "Library")
            error = e
        } catch {
            AppLog(.error, "Failed to load book \(bookId) content: \(error.localizedDescription)", category: "Library")
            self.error = .unknown(error.localizedDescription)
        }
        isLoadingContent = false
    }

    // MARK: - Delete

    func deletePage(id: Int) async {
        do {
            try await BookStackAPI.shared.deletePage(id: id)
            pages.removeAll { $0.id == id }
        } catch let e as BookStackError {
            error = e
        } catch {
            self.error = .unknown(error.localizedDescription)
        }
    }

    func deleteBook(id: Int) async {
        do {
            try await BookStackAPI.shared.deleteBook(id: id)
            books.removeAll { $0.id == id }
        } catch let e as BookStackError {
            error = e
        } catch {
            self.error = .unknown(error.localizedDescription)
        }
    }
}
