import { ref } from 'vue'
import * as fs from 'fs'
import * as path from 'path'
import { FilesHandle } from './FilesHandle'
import { ServiceSettings } from './ServiceSettings'

type ErrorMapValue = {
  description: string
  codes: Map<string, string>
}

export class TransitErrorCodeMap {
  private static instance: TransitErrorCodeMap
  private _errorMap = new Map<string, ErrorMapValue>()

  public static GetInstance(): TransitErrorCodeMap {
    if (!this.instance) {
      this.instance = new TransitErrorCodeMap()
    }
    return this.instance
  }

  private constructor() {
    this.initErrorMap()
  }

  private async initErrorMap() {
    const localFile = path.join(process.cwd(), 'errorMap.xml')
    const serverPath = path.join(ServiceSettings.ConfigFilePath, 'errorMap.xml')

    // 检查文件是否需要更新
    if (!fs.existsSync(localFile) || !(await FilesHandle.CheckMD5(localFile, serverPath))) {
      try {
        // 更新文件
        if (fs.existsSync(localFile)) {
          fs.unlinkSync(localFile)
        }
        const data = await FilesHandle.GetFileData(serverPath)
        fs.writeFileSync(localFile, data)
      } catch (e) {
        console.error('更新错误码映射文件失败:', e)
      }
    }

    // 读取配置文件
    try {
      const xmlData = fs.readFileSync(localFile, 'utf-8')
      const parser = new DOMParser()
      const document = parser.parseFromString(xmlData, 'text/xml')

      if (document.documentElement) {
        // 分类配置文件
        const categories = document.documentElement.getElementsByTagName('category')
        for (let i = 0; i < categories.length; i++) {
          const node = categories[i]
          const type = node.getAttribute('name')
          if (!type || this._errorMap.has(type)) continue

          const desc = node.getAttribute('value') || ''
          const codeMap = new Map<string, string>()

          const errors = node.getElementsByTagName('error')
          for (let j = 0; j < errors.length; j++) {
            const error = errors[j]
            const code = error.getAttribute('name')
            const value = error.getAttribute('value')
            if (code && value && !codeMap.has(code)) {
              codeMap.set(code, value)
            }
          }

          this._errorMap.set(type, {
            description: desc,
            codes: codeMap
          })
        }
      }
    } catch (e) {
      console.error('解析错误码映射文件失败:', e)
    }
  }

  /**
   * 获取错误代码指代的错误信息
   */
  public GetErrorMessage(errorCode: string, type?: string): string {
    const errorType = type || 'default'
    const dict = this._errorMap.get(errorType)
    
    if (!dict) {
      return `[${errorType}-${errorCode}]未知的错误代码类型`
    }

    let msg = dict.codes.get(errorCode) || '未知的错误代码'
    
    // 若找不到错误码，从default中再找一遍
    if (msg === '未知的错误代码' && errorType === 'agn') {
      const defaultDict = this._errorMap.get('default')
      if (defaultDict && defaultDict.codes.has(errorCode)) {
        msg = defaultDict.codes.get(errorCode)!
      }
    }

    return `[${dict.description}-${errorCode}]${msg}`
  }

  /**
   * 获取带域信息的错误代码指代的错误信息
   */
  public GetErrorMessageWithField(errorCode: string, errorFd: string, type?: string): string {
    const errorType = type || 'default'
    const dict = this._errorMap.get(errorType)
    
    if (!dict) {
      return `[${errorType}-${errorCode}]未知的错误代码类型(${errorFd})`
    }

    let msg = dict.codes.get(errorCode) || '未知的错误代码'
    
    // 若找不到错误码，从default中再找一遍
    if (msg === '未知的错误代码' && errorType === 'agn') {
      const defaultDict = this._errorMap.get('default')
      if (defaultDict && defaultDict.codes.has(errorCode)) {
        msg = defaultDict.codes.get(errorCode)!
      }
    }

    return `[${dict.description}-${errorCode}]${msg}(${errorFd})`
  }
}