import { bilibiliApi, getJson, getJsonWithCredentials } from '@/core/ajax'
import { Toast } from '@/core/toast'
import { getFriendlyTitle } from '@/core/utils/title'
import { SubtitleConverterConfig } from '../subtitle-converter'

export interface SubtitleSettings {
  bilingual: boolean
  color: string
  fade: boolean
  fontsize: string
  lan: string
  opacity: number
  position: string
  scale: boolean
  shadow: string
}
export interface SubtitleInfo {
  id: number
  id_str: string
  lan: string
  lan_doc: string
  is_lock: boolean
  subtitle_url: string
  type: number
  ai_type: number
  ai_status: number
}
export type SubtitleDownloadType = 'json' | 'ass'
export const getSubtitleConfig = async (): Promise<[SubtitleConverterConfig, string]> => {
  const { SubtitleConverter, SubtitleSize, SubtitleLocation } = await import(
    '../subtitle-converter'
  )
  const { playerAgent } = await import('@/components/video/player-agent')
  const subtitleSettings = playerAgent.getPlayerConfig<null, SubtitleSettings>('subtitle', null)
  if (!subtitleSettings) {
    return [SubtitleConverter.defaultConfig, '']
  }
  const language = subtitleSettings.lan
  const title = getFriendlyTitle(true)
  const fontSizeMapping: { [key: number]: number } = {
    0.6: SubtitleSize.VerySmall,
    0.8: SubtitleSize.Small,
    1: SubtitleSize.Medium,
    1.3: SubtitleSize.Large,
    1.6: SubtitleSize.VeryLarge,
  }
  const size = fontSizeMapping[subtitleSettings.fontsize]
  const color = parseInt(subtitleSettings.color).toString(16)
  const { opacity } = subtitleSettings

  const positions = {
    bc: SubtitleLocation.BottomCenter,
    bl: SubtitleLocation.BottomLeft,
    br: SubtitleLocation.BottomRight,
    tc: SubtitleLocation.TopCenter,
    tl: SubtitleLocation.TopLeft,
    tr: SubtitleLocation.TopRight,
    'bottom-center': SubtitleLocation.BottomCenter,
    'bottom-left': SubtitleLocation.BottomLeft,
    'bottom-right': SubtitleLocation.BottomRight,
    'top-center': SubtitleLocation.TopCenter,
    'top-left': SubtitleLocation.TopLeft,
    'top-right': SubtitleLocation.TopRight,
  }
  const subtitleLocation = positions[subtitleSettings.position]

  const video = playerAgent.query.video.element.sync() as HTMLVideoElement
  const config: SubtitleConverterConfig = {
    title,
    height: video.videoHeight,
    width: video.videoWidth,
    color,
    location: subtitleLocation,
    opacity,
    size,
    boxPadding: 1,
    boxMargin: 32,
  }
  return [config, language]
}
export const getSubtitleList = async (aid: string, cid: string | number) => {
  const data = await bilibiliApi(
    getJsonWithCredentials(`https://api.bilibili.com/x/player/wbi/v2?aid=${aid}&cid=${cid}`),
  )
  return lodash.get(data, 'subtitle.subtitles', []) as SubtitleInfo[]
}
export const getSubtitleBlob = async (
  type: SubtitleDownloadType,
  input: {
    aid?: string
    cid?: string
    title?: string
    language?: string
  } = {},
) => {
  const {
    aid = unsafeWindow.aid,
    cid = unsafeWindow.cid,
    title = getFriendlyTitle(true),
    language: languageOverride,
  } = input
  if (!aid || !cid) {
    throw new Error('未找到视频 AID 和 CID')
  }
  const subtitles = await getSubtitleList(aid, cid)
  if (subtitles.length === 0) {
    Toast.info('当前视频没有字幕.', '下载字幕', 3000)
    return null
  }
  const [config, language] = await getSubtitleConfig()
  const subtitle = subtitles.find(s => s.lan === (languageOverride ?? language)) || subtitles[0]
  const json = await getJson(subtitle.subtitle_url)
  const rawData = json.body
  switch (type) {
    case 'ass': {
      const { SubtitleConverter } = await import('../subtitle-converter')
      const converter = new SubtitleConverter({ ...config, title })
      const assText = await converter.convertToAss(rawData)
      return new Blob([assText], {
        type: 'text/ass',
      })
    }
    default:
    case 'json': {
      return new Blob([JSON.stringify(rawData, undefined, 2)], {
        type: 'text/json',
      })
    }
  }
}
