import { defineStore } from 'pinia'
import API from '@api'
import type {
  BaseBook,
  Book,
  BookChapter,
  BookProgress,
  SeachBook,
} from '@/book'
import type { webReadConfig } from '@/web'
import { ElMessage } from 'element-plus/es'

const default_config: webReadConfig = {
  theme: 0,
  font: 0,
  fontSize: 18,
  readWidth: 800,
  infiniteLoading: false,
  customFontName: '',
  jumpDuration: 1000,
  spacing: {
    paragraph: 1,
    line: 0.8,
    letter: 0,
  },
}
let webReadConfigLoadedDate: Date | undefined

export const useBookStore = defineStore('book', {
  state: () => {
    return {
      searchBooks: [] as SeachBook[],
      shelf: [] as Book[],
      catalog: [] as BookChapter[],
      readingBook: { chapterPos: 0, chapterIndex: 0 } as BaseBook & {
        chapterPos: number
        chapterIndex: number
        isSeachBook?: boolean
      },
      popCataVisible: false,
      contentLoading: true,
      showContent: false,
      config: default_config,
      miniInterface: false,
      readSettingsVisible: false,
    }
  },
  getters: {
    bookProgress: (state): BookProgress | undefined => {
      if (state.catalog.length == 0) return
      const { chapterIndex, chapterPos, name, author } = state.readingBook
      const title = state.catalog[chapterIndex]?.title
      if (!title) return
      return {
        name,
        author,
        durChapterIndex: chapterIndex,
        durChapterPos: chapterPos,
        durChapterTime: new Date().getTime(),
        durChapterTitle: title,
      }
    },
    theme: state => {
      return state.config.theme
    },
    isNight: state => state.config.theme == 6,
  },
  actions: {
    /** 从后端加载书架书籍,优先返回内存缓存 */
    async loadBookShelf(): Promise<Book[]> {
      const fetchBookshellf_promise = API.getBookShelf().then(resp => {
        console.log('API.getBookShelf数据返回')
        const { isSuccess, data, errorMsg } = resp.data
        if (isSuccess === true) {
          if (
            this.shelf.length !== data.length &&
            this.shelf.length > 0 &&
            data.length > 0
          ) {
            ElMessage.info(`书架数据已更新`)
          }
          this.shelf = data.sort((a, b) => {
            const x = a['durChapterTime'] || 0
            const y = b['durChapterTime'] || 0
            return y - x
          })
        } else {
          if (errorMsg.includes('还没有添加小说') && this.shelf.length > 0) {
            ElMessage.info('当前书架上的书籍已经被删除')
            return (this.shelf = [])
          }
          ElMessage.error(errorMsg ?? '后端返回格式错误!')
        }
        console.log('书架数据已更新')
        return this.shelf
      })

      if (this.shelf.length > 0) {
        // bookshelf data fetched before:do not await
        console.log('返回缓存书架数据')
        return this.shelf
      } else {
        console.log('从阅读后端获取书架数据...')
        return await fetchBookshellf_promise
      }
    },
    /** 从后端加载书籍目录,优先返回内存缓存 */
    async loadWebCatalog(
      book: typeof this.readingBook,
    ): Promise<BookChapter[]> {
      const { bookUrl, name, chapterIndex } = book
      const fetchChapterList_promise = API.getChapterList(
        bookUrl as string,
      ).then(res => {
        const { isSuccess, data, errorMsg } = res.data
        if (isSuccess === false) {
          ElMessage.error(errorMsg)
          throw new Error()
        }
        if (
          bookUrl === this.readingBook.bookUrl &&
          data.length !== this.catalog.length &&
          data.length > 0 &&
          this.catalog.length > 0
        ) {
          ElMessage.info(`书籍${name}: 章节目录已更新`)
        }
        this.catalog = data
        console.log(`书籍${name}: 章节目录已更新`)
        return this.catalog
      })
      if (
        bookUrl === this.readingBook.bookUrl &&
        this.catalog.length > 0 &&
        this.catalog.length - 1 >= chapterIndex
      ) {
        console.log(`返回书籍《${name}》 缓存的章节目录`)
        return this.catalog
      } else {
        console.log(`从阅读后端获取书籍《${name}》 章节目录数据...`)
        return await fetchChapterList_promise
      }
    },
    setPopCataVisible(visible: boolean) {
      this.popCataVisible = visible
    },
    setContentLoading(loading: boolean) {
      this.contentLoading = loading
    },
    setReadingBook(readingBook: typeof this.readingBook) {
      this.readingBook = readingBook
    },
    /** 只从从后端加载一次web阅读配置 */
    async loadWebConfig() {
      if (webReadConfigLoadedDate === undefined) {
        const _config = await API.getReadConfig()
        webReadConfigLoadedDate = new Date()
        console.log(
          `${this.$id}.loadWebConfig: ${webReadConfigLoadedDate.toLocaleString()}成功加载阅读配置`,
        )
        return this.setConfig(_config)
      }
      console.log(
        `${this.$id}.loadWebConfig: 已于${webReadConfigLoadedDate.toLocaleString()}成功加载`,
      )
    },
    setConfig(config?: webReadConfig) {
      this.config = Object.assign({}, this.config, config)
    },
    setReadSettingsVisible(visible: boolean) {
      this.readSettingsVisible = visible
    },
    setShowContent(visible: boolean) {
      this.showContent = visible
    },
    setMiniInterface(mini: boolean) {
      this.miniInterface = mini
    },
    async setSearchBooks(books: SeachBook[]) {
      books.forEach(book => {
        const isSeachBook = this.shelf.every(
          item => item.bookUrl !== book.bookUrl,
        )
        if (isSeachBook === true) {
          this.searchBooks.push(book)
        }
      })
    },
    clearSearchBooks() {
      this.searchBooks = []
    },
    /** 1.保存进度到app 2.修改内存中的数据*/
    async saveBookProgress() {
      if (!this.bookProgress) return Promise.resolve()
      const { bookUrl } = this.readingBook
      const shelfRaw = toRaw(this.shelf)
      const findIndex = shelfRaw.findIndex(book => book.bookUrl === bookUrl)
      if (findIndex > -1) {
        this.shelf[findIndex] = Object.assign(
          {},
          shelfRaw[findIndex],
          this.bookProgress,
        )
      }
      // 直接关闭浏览器时 http请求可能被取消
      // return API.saveBookProgress(this.bookProgress)
      return API.saveBookProgressWithBeacon(this.bookProgress)
    },
  },
})