export type Rect = {
  x: number
  y: number
  width: number
  height: number
}

export type TextStyle = {
  fontFamily: string
  fontSize: number
  color: string
  fontWeight: '400' | '600' | '700'
  align: 'left' | 'center' | 'right'
}

export type CertificateTemplateConfig = {
  version: 1
  templateWidth: number
  templateHeight: number
  imageRect: Rect
  nameRect: Rect
  textStyle: TextStyle
  imageFit: 'cover'
}

export type StudentRow = {
  name: string
  rowNumber: number
}

export type GeneratedAsset = {
  fileName: string
  jpg?: Blob
}

export type IdPhotoBackground = 'blue' | 'white' | 'red' | 'custom'

export type IdPhotoSize = 'one-inch' | 'two-inch'

export type IdPhotoConfig = {
  background: IdPhotoBackground
  customColor?: string
  size: IdPhotoSize
  widthPx: number
  heightPx: number
}

export type IdPhotoCrop = {
  scale: number
  offsetX: number
  offsetY: number
  sourceRect?: Rect
}

export type BatchIssue = {
  name: string
  status: 'success' | 'skipped'
  message: string
}

export const DEFAULT_TEMPLATE_CONFIG: CertificateTemplateConfig = {
  version: 1,
  templateWidth: 2647,
  templateHeight: 3675,
  imageRect: {
    x: 1135 / 2647,
    y: 1371 / 3675,
    width: 386 / 2647,
    height: 576 / 3675
  },
  nameRect: {
    x: 986 / 2647,
    y: 2068 / 3675,
    width: 707 / 2647,
    height: 88 / 3675
  },
  textStyle: {
    fontFamily: 'serif',
    fontSize: 72,
    color: '#1f1b1c',
    fontWeight: '700',
    align: 'center'
  },
  imageFit: 'cover'
}

export const ID_PHOTO_BACKGROUND_COLORS: Record<Exclude<IdPhotoBackground, 'custom'>, string> = {
  blue: '#438EDB',
  white: '#FFFFFF',
  red: '#D91F2D'
}

export const ID_PHOTO_SIZE_PRESETS: Record<IdPhotoSize, Pick<IdPhotoConfig, 'widthPx' | 'heightPx'>> = {
  'one-inch': {
    widthPx: 295,
    heightPx: 413
  },
  'two-inch': {
    widthPx: 413,
    heightPx: 579
  }
}

export const DEFAULT_ID_PHOTO_CONFIG: IdPhotoConfig = {
  background: 'blue',
  size: 'one-inch',
  ...ID_PHOTO_SIZE_PRESETS['one-inch']
}

export const DEFAULT_ID_PHOTO_CROP: IdPhotoCrop = {
  scale: 1,
  offsetX: 0,
  offsetY: 0
}

export function resolveIdPhotoCrop(crop?: Partial<IdPhotoCrop>): IdPhotoCrop {
  const sourceRect =
    crop?.sourceRect &&
    crop.sourceRect.width > 0 &&
    crop.sourceRect.height > 0
      ? {
        x: Math.min(Math.max(Number(crop.sourceRect.x), 0), 1),
        y: Math.min(Math.max(Number(crop.sourceRect.y), 0), 1),
        width: Math.min(Math.max(Number(crop.sourceRect.width), 0.01), 1),
        height: Math.min(Math.max(Number(crop.sourceRect.height), 0.01), 1)
      }
      : undefined

  return {
    scale: Math.min(Math.max(Number(crop?.scale ?? DEFAULT_ID_PHOTO_CROP.scale), 0.75), 1.35),
    offsetX: Math.min(Math.max(Number(crop?.offsetX ?? DEFAULT_ID_PHOTO_CROP.offsetX), -0.35), 0.35),
    offsetY: Math.min(Math.max(Number(crop?.offsetY ?? DEFAULT_ID_PHOTO_CROP.offsetY), -0.35), 0.35),
    sourceRect: sourceRect
      ? {
        ...sourceRect,
        width: Math.min(sourceRect.width, 1 - sourceRect.x),
        height: Math.min(sourceRect.height, 1 - sourceRect.y)
      }
      : undefined
  }
}

export function resolveIdPhotoConfig(config?: Partial<IdPhotoConfig>): IdPhotoConfig {
  const size = config?.size === 'two-inch' ? 'two-inch' : 'one-inch'
  const background: IdPhotoBackground = ['blue', 'white', 'red', 'custom'].includes(
    String(config?.background)
  )
    ? (config?.background as IdPhotoBackground)
    : DEFAULT_ID_PHOTO_CONFIG.background
  const customColor = /^#[\da-f]{6}$/i.test(config?.customColor ?? '')
    ? config?.customColor
    : DEFAULT_ID_PHOTO_CONFIG.customColor

  return {
    background,
    customColor,
    size,
    ...ID_PHOTO_SIZE_PRESETS[size]
  }
}

export function idPhotoBackgroundColor(config: IdPhotoConfig) {
  return config.background === 'custom'
    ? config.customColor || ID_PHOTO_BACKGROUND_COLORS.blue
    : ID_PHOTO_BACKGROUND_COLORS[config.background]
}

export function idPhotoSizeLabel(size: IdPhotoSize) {
  return size === 'two-inch' ? '二寸' : '一寸'
}

export function idPhotoBackgroundLabel(background: IdPhotoBackground) {
  if (background === 'white') {
    return '白底'
  }

  if (background === 'red') {
    return '红底'
  }

  if (background === 'custom') {
    return '自定义底'
  }

  return '蓝底'
}

export function denormalizeRect(rect: Rect, width: number, height: number): Rect {
  return {
    x: rect.x * width,
    y: rect.y * height,
    width: rect.width * width,
    height: rect.height * height
  }
}

export function normalizeRect(rect: Rect, width: number, height: number): Rect {
  return {
    x: rect.x / width,
    y: rect.y / height,
    width: rect.width / width,
    height: rect.height / height
  }
}

export function sanitizeFileName(value: string) {
  return (
    [...value]
      .filter((character) => !'<>:"/\\|?*'.includes(character) && character.charCodeAt(0) >= 32)
      .join('')
      .trim() || '毕业证书'
  )
}

export function normalizeMatchName(value: string) {
  return value
    .replace(/\.[^.]+$/, '')
    .replace(/\s+/g, '')
    .trim()
    .toLowerCase()
}
