import json
import os
import mimetypes
import httpx
from tqdm import tqdm

# 0: 较高画质, 但有水印
# download_type = 0
# 1: 较低画质, 但无水印
download_type = 1


input_file = 'kaka新星-猫绒陷阱.json'
act_id = 109490
lottery_id = 109491
output_dir = 'output/'
headers = {
  'referer': 'https://www.bilibili.com/',
  'origin': 'https://www.bilibili.com',
  'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36 Edg/130.0.0.0'
}


def download(url, path, headers):
  name = os.path.basename(path)
  try:
    with httpx.stream(
      'GET',
      url,
      headers=headers,
      follow_redirects=True,
    ) as r:
      if r.status_code != 200:
        print(f'下载 {name} 失败: {r.status_code}')
        return False
      total = int(r.headers.get('Content-Length', '100'))
      bar = tqdm(total=total, unit='B', unit_scale=True)
      with open(path, 'wb') as f:
        for chunk in r.iter_raw():
          f.write(chunk)
          bar.n = r.num_bytes_downloaded
          bar.refresh()
      bar.close()
  except Exception as e:
    if os.path.isfile(path):
      os.remove(path)
    print(f'{name} 下载失败 {type(e).__name__}: {e}')
    return False
  else:
    print(f'下载 {name} 成功')
    return True


def get_cards(data):
  cards = []
  for i in data['item_list']:
    card = {
      'name': i['card_info']['card_name'],
      'image_url': i['card_info']['card_img'],
      'image_ext': '',
      'video_url': '',
      'video_ext': '',
    }
    if download_type == 0:
      card['image_url'] = i['card_info']['card_img_download']
    mime_type = mimetypes.guess_type(card['image_url'])[0]
    card['image_ext'] = mimetypes.guess_extension(mime_type)

    if i['card_info']['video_list']:
      card['video_url'] = i['card_info']['video_list'][0]
      if download_type == 0:
        card['video_url'] = i['card_info']['video_list_download'][0]
      mime_type = mimetypes.guess_type(card['video_url'])[0]
      card['video_ext'] = mimetypes.guess_extension(mime_type)
    cards.append(card)
  return cards


def download_cards(cards, out_dir):
  print(f'卡片数: {len(cards)}')
  fails = []
  for i, card in enumerate(cards):
    print(f'下载卡片 {i + 1} 图片')
    name = card['name']
    url = card['image_url']
    ext = card['image_ext']
    filename = f'{i + 1}_{name}{ext}'
    output = os.path.join(out_dir, filename)
    if not os.path.isfile(output):
      res = download(url, output, headers=headers)
      if not res:
        fails.append(filename)

    if url := card.get('video_url', ''):
      print(f'下载卡片 {i + 1} 视频')
      ext = card['video_ext']
      filename = f'{i + 1}_{name}{ext}'
      output = os.path.join(out_dir, filename)
      if not os.path.isfile(output):
        res = download(url, output, headers=headers)
        if not res:
          fails.append(filename)
  tip = '0 下载失败'
  if fails:
    tip = f'{len(fails)} 下载失败: {"、".join(fails)}'
  print(f'\n下载完成, {tip}')


def get_data():
  if act_id and lottery_id and not os.path.isfile(input_file):
    try:
      r = httpx.get(f'https://api.bilibili.com/x/vas/dlc_act/lottery_home_detail?act_id={act_id}&lottery_id={lottery_id}', headers=headers)
      res = r.json()
      if res.get('code', '') == 0:
        if not os.path.isfile(input_file):
          with open(input_file, 'w') as f:
            json.dump(res, f, indent=2, escape_ascii=False)
        return res
    except Exception:
      pass
  with open(input_file) as f:
    data = json.load(f)['data']
  return data


def main():
  data = get_data()

  lottery_name = data['name']
  cards = get_cards(data)

  out_dir = os.path.join(output_dir, lottery_name)
  os.makedirs(out_dir, exist_ok=True)

  download_cards(cards, out_dir)


if __name__ == '__main__':
  main()
