/**
 * TUS协议头部验证器
 * 
 * 该模块实现了TUS协议中各种HTTP头部的验证逻辑
 * TUS是一个用于可恢复文件上传的开放协议
 * 
 * @version 1.0.0
 * @see https://tus.io/protocols/resumable-upload.html
 */

import { Metadata, TUS_VERSION, TUS_RESUMABLE } from "../utils"


/** 验证器函数类型定义,接收可选的字符串值,返回布尔值表示验证结果 */
type validator = (value?: string) => boolean

/**
 * TUS协议头部验证器映射表
 * 包含了所有TUS协议规定的HTTP头部的验证规则
 */
export const validators = new Map<string, validator>([
  [
    'upload-offset',
    /**
     * Upload-Offset头部验证
     * 用于指示资源内的字节偏移量
     * 必须是非负整数
     */
    (value) => {
      const n = Number(value)
      return Number.isInteger(n) && String(n) === value && n >= 0
    },
  ],
  [
    'upload-length',
    /**
     * Upload-Length头部验证
     * 表示整个上传文件的字节大小
     * 必须是非负整数
     */
    (value) => {
      const n = Number(value)
      return Number.isInteger(n) && String(n) === value && n >= 0
    },
  ],
  [
    'upload-defer-length',
    /**
     * Upload-Defer-Length头部验证
     * 表示上传大小当前未知,将在后续传输
     * 值必须为1,如果长度未延迟则必须省略此头部
     */
    (value) => value === '1',
  ],
  [
    'upload-metadata',
    /**
     * Upload-Metadata头部验证
     * 必须由一个或多个逗号分隔的键值对组成
     * 键和值必须用空格分隔
     * 键不能包含空格和逗号且不能为空
     * 键应该是ASCII编码,值必须是Base64编码
     * 所有键必须唯一
     */
    (value) => {
      try {
        Metadata.parse(value)
        return true
      } catch {
        return false
      }
    },
  ],
  [
    'x-forwarded-proto',
    /**
     * X-Forwarded-Proto头部验证
     * 用于标识客户端与服务器之间的协议
     * 仅允许http或https
     */
    (value) => {
      if (value === 'http' || value === 'https') {
        return true
      }
      return false
    },
  ],
  [
    'tus-version',
    /**
     * Tus-Version头部验证
     * 服务器支持的协议版本列表
     * 必须按服务器偏好排序,第一个是最优先的
     */
    (value) => {
      return TUS_VERSION.includes(value as any)
    },
  ],
  [
    'tus-resumable',
    /**
     * Tus-Resumable头部验证
     * 除OPTIONS请求外的每个请求和响应都必须包含
     * 值必须是客户端或服务器使用的协议版本
     */
    (value) => value === TUS_RESUMABLE,
  ],
  ['content-type', (value) => value === 'application/offset+octet-stream'],
  [
    'upload-concat',
    /**
     * Upload-Concat头部验证
     * 用于部分上传和最终上传的创建请求
     * 部分上传值必须为partial
     * 最终上传值必须以final开头,后跟分号和空格分隔的部分上传URL列表
     */
    (value) => {
      if (!value) return false
      const valid_partial = value === 'partial'
      const valid_final = value.startsWith('final;')
      return valid_partial || valid_final
    },
  ],
])

/**
 * 验证HTTP头部值是否符合TUS协议规范
 * @param name 头部名称
 * @param value 头部值
 * @returns 验证是否通过
 */
export function validateHeader(name: string, value?: string): boolean {
  const lowercaseName = name.toLowerCase()
  if (!validators.has(lowercaseName)) {
    return true
  }
  return validators.get(lowercaseName)!(value)
}