import { ref, computed, Ref } from 'vue'
import { useStorage } from '@vueuse/core'
import { List } from 'linqts'
import { NTime, useMessage, useNotification } from 'naive-ui'
import { h } from 'vue'

import {
  DanmakuUserInfo,
  EventDataTypes,
  EventModel,
  QueueSortType,
  SongRequestFrom,
  SongRequestInfo,
  SongRequestStatus,
  SongsInfo
} from '@/api/api-models'
import {
  QueryGetAPI,
  QueryPostAPI,
  QueryPostAPIWithParams
} from '@/api/query'
import { SONG_REQUEST_API_URL } from '@/data/constants'
import { AddBiliBlackList, useAccount } from '@/api/account'

export const useLiveRequest = defineStore('songRequest', () => {
  const accountInfo = useAccount()

  const localActiveSongs = useStorage('SongRequest.ActiveSongs', [] as SongRequestInfo[])
  const isWarnMessageAutoClose = useStorage('SongRequest.Settings.WarnMessageAutoClose', false)
  const isReverse = useStorage('SongRequest.Settings.Reverse', false)
  const defaultPrefix = useStorage('Settings.SongRequest.DefaultPrefix', '点播')

  const isLoading = ref(false)
  const originSongs = ref<SongRequestInfo[]>([])
  const updateKey = ref(0)
  const filterSongName = ref('')
  const filterSongNameContains = ref(false)
  const filterName = ref('')
  const filterNameContains = ref(false)
  const newSongName = ref('')
  const selectedSong = ref<SongsInfo>()
  const isLrcLoading = ref('')

  const configCanEdit = computed(() => {
    return accountInfo.value != null && accountInfo.value?.id !== undefined
  })

  const songs = computed(() => {
    let result = new List(originSongs.value).Where((s) => {
      if (filterName.value) {
        if (filterNameContains.value) {
          if (!s?.user?.name.toLowerCase().includes(filterName.value.toLowerCase())) {
            return false
          }
        } else if (s?.user?.name.toLowerCase() !== filterName.value.toLowerCase()) {
          return false
        }
      } else if (filterSongName.value) {
        if (filterSongNameContains.value) {
          if (!s?.songName.toLowerCase().includes(filterSongName.value.toLowerCase())) {
            return false
          }
        } else if (s?.songName.toLowerCase() !== filterSongName.value.toLowerCase()) {
          return false
        }
      }
      return true
    })

    const settings = accountInfo.value?.settings?.songRequest || {}

    switch (settings.sortType) {
      case QueueSortType.TimeFirst: {
        result = result.ThenBy((q) => q.createAt)
        break
      }
      case QueueSortType.GuardFirst: {
        result = result
          .OrderBy((q) => (q.user?.guard_level == 0 || q.user?.guard_level == null ? 4 : q.user.guard_level))
          .ThenBy((q) => q.createAt)
        break
      }
      case QueueSortType.PaymentFist: {
        result = result.OrderByDescending((q) => q.price ?? 0).ThenBy((q) => q.createAt)
        break
      }
      case QueueSortType.FansMedalFirst: {
        result = result.OrderByDescending((q) => q.user?.fans_medal_level ?? 0).ThenBy((q) => q.createAt)
        break
      }
    }

    if ((configCanEdit.value && settings.isReverse) || (!configCanEdit.value && isReverse.value)) {
      return result.Reverse().ToArray()
    } else {
      return result.ToArray()
    }
  })

  const activeSongs = computed(() => {
    return (accountInfo.value?.id ? songs.value : localActiveSongs.value)
      .sort((a, b) => b.status - a.status)
      .filter((song) => {
        return song.status == SongRequestStatus.Waiting || song.status == SongRequestStatus.Singing
      })
  })

  const historySongs = computed(() => {
    return (accountInfo.value?.id ? songs.value : localActiveSongs.value)
      .sort((a, b) => a.status - b.status)
      .filter((song) => {
        return song.status == SongRequestStatus.Finish || song.status == SongRequestStatus.Cancel
      })
  })

  const STATUS_MAP = {
    [SongRequestStatus.Waiting]: '等待中',
    [SongRequestStatus.Singing]: '处理中',
    [SongRequestStatus.Finish]: '已处理',
    [SongRequestStatus.Cancel]: '已取消',
  }

  async function getAllSong() {
    if (accountInfo.value?.id) {
      try {
        const data = await QueryGetAPI<SongRequestInfo[]>(SONG_REQUEST_API_URL + 'get-all', {
          id: accountInfo.value.id,
        })
        if (data.code == 200) {
          console.log('[SONG-REQUEST] 已获取所有数据')
          return new List(data.data).OrderByDescending((s) => s.createAt).ToArray()
        } else {
          window.$message.error('无法获取数据: ' + data.message)
          return []
        }
      } catch (err) {
        window.$message.error('无法获取数据')
      }
      return []
    } else {
      return localActiveSongs.value
    }
  }

  async function initData() {
    originSongs.value = await getAllSong()
  }

  async function addSong(danmaku: EventModel) {
    console.log(
      `[SONG-REQUEST] 收到 [${danmaku.uname}] 的点播${danmaku.type == EventDataTypes.SC ? 'SC' : '弹幕'}: ${danmaku.msg}`,
    )

    const settings = accountInfo.value?.settings?.songRequest || {}

    if (settings.enableOnStreaming && accountInfo.value?.streamerInfo?.isStreaming != true) {
      window.$notification.info({
        title: `${danmaku.uname} 点播失败`,
        description: '当前未在直播中, 无法添加点播请求. 或者关闭设置中的仅允许直播时加入',
        meta: () => h(NTime, { type: 'relative', time: Date.now(), key: updateKey.value }),
      })
      return
    }

    if (accountInfo.value?.id) {
      await QueryPostAPI<SongRequestInfo>(SONG_REQUEST_API_URL + 'try-add', danmaku).then((data) => {
        if (data.code == 200) {
          window.$message.success(`[${danmaku.uname}] 添加曲目: ${data.data.songName}`)
          if (data.message != 'EventFetcher') originSongs.value.unshift(data.data)
        } else {
          const time = Date.now()
          window.$notification.warning({
            title: danmaku.uname + ' 点播失败',
            description: data.message,
            duration: isWarnMessageAutoClose.value ? 3000 : 0,
            meta: () => h(NTime, { type: 'relative', time: time, key: updateKey.value }),
          })
          console.log(`[SONG-REQUEST] [${danmaku.uname}] 添加曲目失败: ${data.message}`)
        }
      })
    } else {
      const songData = {
        songName: danmaku.msg.trim().substring(settings.orderPrefix?.length || defaultPrefix.value.length),
        song: undefined,
        status: SongRequestStatus.Waiting,
        from: danmaku.type == EventDataTypes.Message ? SongRequestFrom.Danmaku : SongRequestFrom.SC,
        scPrice: danmaku.type == EventDataTypes.SC ? danmaku.price : 0,
        user: {
          name: danmaku.uname,
          uid: danmaku.uid,
          oid: danmaku.open_id,
          face: danmaku.uface,
          fans_medal_level: danmaku.fans_medal_level,
          fans_medal_name: danmaku.fans_medal_name,
          fans_medal_wearing_status: danmaku.fans_medal_wearing_status,
          guard_level: danmaku.guard_level,
        } as DanmakuUserInfo,
        createAt: Date.now(),
        isInLocal: true,
        id: songs.value.length == 0 ? 1 : new List(songs.value).Max((s) => s.id) + 1,
      } as SongRequestInfo

      localActiveSongs.value.unshift(songData)
      window.$message.success(`[${danmaku.uname}] 添加: ${songData.songName}`)
    }
  }

  async function addSongManual() {
    if (!newSongName.value) {
      window.$message.error('请输入名称')
      return
    }

    if (accountInfo.value?.id) {
      await QueryPostAPIWithParams<SongRequestInfo>(SONG_REQUEST_API_URL + 'add', {
        name: newSongName.value,
      }).then((data) => {
        if (data.code == 200) {
          window.$message.success(`已手动添加: ${data.data.songName}`)
          originSongs.value.unshift(data.data)
          newSongName.value = ''
          console.log(`[SONG-REQUEST] 已手动添加: ${data.data.songName}`)
        } else {
          window.$message.error(`手动添加失败: ${data.message}`)
        }
      })
    } else {
      const songData = {
        songName: newSongName.value,
        song: undefined,
        status: SongRequestStatus.Waiting,
        from: SongRequestFrom.Manual,
        scPrice: undefined,
        user: undefined,
        createAt: Date.now(),
        isInLocal: true,
        id: songs.value.length == 0 ? 1 : new List(songs.value).Max((s) => s.id) + 1,
      } as SongRequestInfo

      localActiveSongs.value.unshift(songData)
      window.$message.success(`已手动添加: ${songData.songName}`)
      newSongName.value = ''
    }
  }

  async function updateSongStatus(song: SongRequestInfo, status: SongRequestStatus) {
    if (!configCanEdit.value) {
      song.status = status
      return
    }

    isLoading.value = true
    let statusString = ''
    let statusString2 = ''

    switch (status) {
      case SongRequestStatus.Waiting:
        statusString = 'active'
        statusString2 = '等待中'
        break
      case SongRequestStatus.Cancel:
        statusString = 'cancel'
        statusString2 = '已取消'
        break
      case SongRequestStatus.Finish:
        statusString = 'finish'
        statusString2 = '已完成'
        break
      case SongRequestStatus.Singing:
        statusString = 'singing'
        statusString2 = '处理中'
        break
    }

    await QueryGetAPI(SONG_REQUEST_API_URL + statusString, {
      id: song.id,
    })
      .then((data) => {
        if (data.code == 200) {
          console.log(`[SONG-REQUEST] 更新状态: ${song.songName} -> ${statusString}`)
          song.status = status
          if (status > SongRequestStatus.Singing) {
            song.finishAt = Date.now()
          }
          window.$message.success(`已更新状态为: ${statusString2}`)
        } else {
          console.log(`[SONG-REQUEST] 更新状态失败: ${data.message}`)
          window.$message.error(`更新状态失败: ${data.message}`)
        }
      })
      .catch((err) => {
        window.$message.error(`更新状态失败`)
      })
      .finally(() => {
        isLoading.value = false
      })
  }

  async function deleteSongs(values: SongRequestInfo[]) {
    isLoading.value = true

    try {
      const data = await QueryPostAPI(
        SONG_REQUEST_API_URL + 'del',
        values.map((s) => s.id),
      )

      if (data.code == 200) {
        window.$message.success('删除成功')
        originSongs.value = originSongs.value.filter((s) => !values.includes(s))
      } else {
        window.$message.error('删除失败: ' + data.message)
      }
    } catch (err) {
      window.$message.error('删除失败')
    } finally {
      isLoading.value = false
    }
  }

  async function deactiveAllSongs() {
    isLoading.value = true

    try {
      const data = await QueryGetAPI(SONG_REQUEST_API_URL + 'deactive')

      if (data.code == 200) {
        window.$message.success('已全部取消')
        songs.value.forEach((s) => {
          if (s.status <= SongRequestStatus.Singing) {
            s.status = SongRequestStatus.Cancel
          }
        })
      } else {
        window.$message.error('取消失败: ' + data.message)
      }
    } catch (err) {
      window.$message.error('取消失败')
    } finally {
      isLoading.value = false
    }
  }

  async function updateActive() {
    if (!accountInfo.value?.id) return

    try {
      const data = await QueryGetAPI<SongRequestInfo[]>(SONG_REQUEST_API_URL + 'get-active', {
        id: accountInfo.value?.id,
      })

      if (data.code == 200) {
        data.data.forEach((item) => {
          const song = originSongs.value.find((s) => s.id == item.id)
          if (song) {
            if (song.status != item.status) song.status = item.status
          } else {
            originSongs.value.unshift(item)
            if (item.from == SongRequestFrom.Web) {
              window.$message.success(`[${item.user?.name}] 直接从网页歌单点播: ${item.songName}`)
            }
          }
        })
      } else {
        window.$message.error('无法获取点播队列: ' + data.message)
      }
    } catch (err) {
      console.error('[SONG-REQUEST] 更新活跃歌曲失败', err)
    }
  }

  async function blockUser(item: SongRequestInfo) {
    if (item.from != SongRequestFrom.Danmaku) {
      window.$message.error(`[${item.user?.name}] 不是来自弹幕的用户`)
      return
    }

    if (item.user) {
      try {
        const data = await AddBiliBlackList(item.user.uid, item.user.name)

        if (data.code == 200) {
          window.$message.success(`[${item.user?.name}] 已添加到黑名单`)
          updateSongStatus(item, SongRequestStatus.Cancel)
        } else {
          window.$message.error(data.message)
        }
      } catch (err) {
        window.$message.error('添加黑名单失败')
      }
    }
  }

  function checkMessage(msg: string) {
    if (accountInfo.value?.settings?.enableFunctions?.includes(6) != true) {
      return false
    }

    const prefix = accountInfo.value?.settings?.songRequest?.orderPrefix || defaultPrefix.value
    return msg.trim().toLowerCase().startsWith(prefix.toLowerCase())
  }

  function getSCColor(price: number): string {
    if (price === 0) return `#2a60b2`
    if (price > 0 && price < 30) return `#2a60b2`
    if (price >= 30 && price < 50) return `#2a60b2`
    if (price >= 50 && price < 100) return `#427d9e`
    if (price >= 100 && price < 500) return `#c99801`
    if (price >= 500 && price < 1000) return `#e09443`
    if (price >= 1000 && price < 2000) return `#e54d4d`
    if (price >= 2000) return `#ab1a32`
    return ''
  }

  function getGuardColor(level: number | null | undefined): string {
    if (level) {
      switch (level) {
        case 1: return 'rgb(122, 4, 35)'
        case 2: return 'rgb(157, 155, 255)'
        case 3: return 'rgb(104, 136, 241)'
      }
    }
    return ''
  }

  function onGetDanmaku(danmaku: EventModel) {
    if (checkMessage(danmaku.msg)) {
      addSong(danmaku)
    }
  }

  function onGetSC(danmaku: EventModel) {
    const settings = accountInfo.value?.settings?.songRequest || {}

    if (settings.allowSC && checkMessage(danmaku.msg)) {
      addSong(danmaku)
    }
  }

  let updateActiveTimer: any = null

  function startUpdateTimer() {
    stopUpdateTimer()
    updateActiveTimer = setInterval(() => {
      updateActive()
    }, 2000)
  }

  function stopUpdateTimer() {
    if (updateActiveTimer) {
      clearInterval(updateActiveTimer)
      updateActiveTimer = null
    }
  }

  let updateKeyTimer: any = null

  function startUpdateKeyTimer() {
    stopUpdateKeyTimer()
    updateKeyTimer = setInterval(() => {
      updateKey.value++
    }, 1000)
  }

  function stopUpdateKeyTimer() {
    if (updateKeyTimer) {
      clearInterval(updateKeyTimer)
      updateKeyTimer = null
    }
  }

  async function init() {
    await initData()
    startUpdateKeyTimer()
    startUpdateTimer()
  }

  function dispose() {
    stopUpdateKeyTimer()
    stopUpdateTimer()
  }

  return {
    // 状态
    isLoading,
    originSongs,
    songs,
    activeSongs,
    historySongs,
    newSongName,
    selectedSong,
    isLrcLoading,
    filterSongName,
    filterSongNameContains,
    filterName,
    filterNameContains,
    updateKey,
    STATUS_MAP,
    isWarnMessageAutoClose,
    isReverse,
    defaultPrefix,

    // 计算
    configCanEdit,

    // 方法
    init,
    dispose,
    addSong,
    addSongManual,
    updateSongStatus,
    deleteSongs,
    deactiveAllSongs,
    updateActive,
    blockUser,
    checkMessage,
    onGetDanmaku,
    onGetSC,
    getSCColor,
    getGuardColor
  }
})