/**
 * TdtSource - 天地图 WMTS 栅格瓦片源（MapLibre GL 适配）
 *
 * 提供将天地图 WMTS 服务转换为 maplibregl 栅格瓦片源配置的工具函数。
 * 替代原有 GeoScene 项目中的 TdtLayer.js，通过自定义 tiles URL 模板
 * 实现天地图六种底图/注记样式的地图加载。
 *
 * @module map/sources/tdt-source
 */

import type { RasterSourceSpecification, RasterLayerSpecification } from 'maplibre-gl'

// ============================================================
// 常量定义
// ============================================================

/**
 * 天地图样式中文名称映射
 */
export const TDT_STYLE_NAMES: Record<string, string> = {
  vec: '矢量底图',
  img: '影像底图',
  ter: '地形晕渲',
  cva: '矢量注记',
  cia: '影像注记',
  cta: '地形注记',
} as const

/**
 * 天地图子域列表（用于负载均衡）
 */
export const TDT_SUBDOMAINS: string[] = ['0', '1', '2', '3', '4', '5', '6', '7']

/**
 * 天地图默认瓦片服务器地址
 */
export const TDT_DEFAULT_URL = 'https://t{s}.tianditu.gov.cn'

/**
 * 天地图 WMTS 地址模板
 *
 * 占位符说明：
 * - `{style}`: 图层样式（vec/img/ter/cva/cia/cta）
 * - `{matrix}`: 瓦片矩阵集标识（c=经纬度，w=墨卡托）
 * - `{z}`: 缩放级别（TILEMATRIX）
 * - `{y}`: 瓦片行号（TILEROW）
 * - `{x}`: 瓦片列号（TILECOL）
 * - `{s}`: 子域编号（负载均衡）
 */
export const TDT_WMTS_TEMPLATE =
  '/{style}_{matrix}/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER={style}&STYLE=default&TILEMATRIXSET={matrix}&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&FORMAT=tiles'

// ============================================================
// 类型定义
// ============================================================

/**
 * 天地图图层样式类型
 *
 * - `vec`: 矢量底图
 * - `img`: 影像底图
 * - `ter`: 地形晕渲
 * - `cva`: 矢量注记（中文注记叠加层）
 * - `cia`: 影像注记（中文注记叠加层）
 * - `cta`: 地形注记（中文注记叠加层）
 */
export type TdtStyle = 'vec' | 'img' | 'ter' | 'cva' | 'cia' | 'cta'

/**
 * 天地图瓦片矩阵集类型
 *
 * - `c`: 经纬度投影（EPSG:4490 / CGCS2000）
 * - `w`: Web 墨卡托投影（EPSG:3857）
 */
export type TdtMatrix = 'c' | 'w'

/**
 * 天地图暗色主题效果 CSS filter
 *
 * 当 theme 为 'dark' 时，通过 canvas 渲染后应用此 CSS 滤镜
 */
export const TDT_DARK_THEME_FILTER =
  'invert(82%) sepia(80%) hue-rotate(180deg) saturate(340%)'

/**
 * 天地图瓦片源配置选项
 */
export interface TdtSourceOptions {
  /**
   * 天地图图层样式
   * @defaultValue 'vec'
   */
  style?: TdtStyle

  /**
   * 瓦片矩阵集
   *
   * - `'c'`: 经纬度投影（CGCS2000），适合国内应用
   * - `'w'`: Web 墨卡托投影，适合与 OSM 等国际底图叠加
   *
   * @defaultValue 'c'
   */
  matrix?: TdtMatrix

  /**
   * 天地图 API 密钥（tk 参数）
   *
   * 注册地址：https://console.tiangong.gov.cn/
   *
   * @defaultValue ''（不传则不追加 tk 参数）
   */
  tk?: string

  /**
   * 天地图瓦片服务器地址
   * @defaultValue 'https://t{s}.tianditu.gov.cn'
   */
  url?: string

  /**
   * 子域列表（负载均衡用）
   * @defaultValue ['0', '1', '2', '3', '4', '5', '6', '7']
   */
  subdomains?: string[]

  /**
   * 最小缩放级别
   * @defaultValue 0
   */
  minzoom?: number

  /**
   * 最大缩放级别（天地图在线瓦片最高 18 级）
   * @defaultValue 18
   */
  maxzoom?: number

  /**
   * 瓦片大小（像素）
   * @defaultValue 256
   */
  tileSize?: number

  /**
   * 图层属性（visible、opacity 等）
   */
  layer?: Partial<Omit<RasterLayerSpecification, 'id' | 'type' | 'source'>>
}

/**
 * 天地图源创建结果
 */
export interface TdtSourceResult {
  /**
   * 源 ID（由 style 和 matrix 拼接生成）
   */
  sourceId: string

  /**
   * MapLibre 源配置（可直接传入 map.addSource）
   */
  source: RasterSourceSpecification

  /**
   * MapLibre 图层配置（可直接传入 map.addLayer）
   */
  layer: RasterLayerSpecification
}

// ============================================================
// 内部工具函数
// ============================================================

/**
 * 构建天地图 WMTS 瓦片 URL 模板
 *
 * 将 {style}/{matrix}/{tk}/{s} 等参数注入 URL 模板，
 * 保留 {z}/{x}/{y} 占位符供 MapLibre 运行时替换。
 *
 * @param options - 源配置选项
 * @returns 完整的瓦片 URL 模板字符串
 */
function buildTileUrlTemplate(options: TdtSourceOptions): string {
  const {
    url = TDT_DEFAULT_URL,
    style = 'vec',
    matrix = 'c',
    tk = '',
  } = options

  let template = TDT_WMTS_TEMPLATE
    .replace(/\{style\}/g, style)
    .replace(/\{matrix\}/g, matrix)

  // 拼接基础 URL
  let fullUrl = url + template

  // 追加 tk 参数（需编码）
  if (tk) {
    fullUrl += '&tk=' + encodeURIComponent(tk)
  }

  return fullUrl
}

// ============================================================
// 公开 API
// ============================================================

/**
 * 生成天地图源 ID
 *
 * 格式为 `tdt-{style}-{matrix}`，例如 `tdt-vec-c`。
 *
 * @param style - 图层样式
 * @param matrix - 瓦片矩阵集
 * @returns 源 ID 字符串
 */
export function getTdtSourceId(style: TdtStyle = 'vec', matrix: TdtMatrix = 'c'): string {
  return `tdt-${style}-${matrix}`
}

/**
 * 生成天地图图层 ID
 *
 * @param style - 图层样式
 * @param matrix - 瓦片矩阵集
 * @returns 图层 ID 字符串
 */
export function getTdtLayerId(style: TdtStyle = 'vec', matrix: TdtMatrix = 'c'): string {
  return `tdt-layer-${style}-${matrix}`
}

/**
 * 创建天地图栅格瓦片源与图层配置
 *
 * 返回 MapLibre GL 兼容的 source 和 layer 配置对象，
 * 可用于 `map.addSource()` 和 `map.addLayer()`。
 *
 * @param options - 天地图源配置选项
 * @returns 包含 source、layer 及 ID 的配置对象
 *
 * @example
 * ```ts
 * import { createTdtSource } from '@/map/sources/tdt-source'
 *
 * // 创建矢量底图源
 * const { sourceId, source, layer } = createTdtSource({
 *   style: 'vec',
 *   matrix: 'c',
 *   tk: 'your-tianditu-key',
 * })
 *
 * map.addSource(sourceId, source)
 * map.addLayer(layer)
 *
 * // 叠加矢量注记层
 * const annotation = createTdtSource({
 *   style: 'cva',
 *   matrix: 'c',
 *   tk: 'your-tianditu-key',
 * })
 * map.addSource(annotation.sourceId, annotation.source)
 * map.addLayer(annotation.layer)
 * ```
 */
export function createTdtSource(options: TdtSourceOptions = {}): TdtSourceResult {
  const {
    style = 'vec',
    matrix = 'c',
    subdomains = TDT_SUBDOMAINS,
    minzoom = 0,
    maxzoom = 18,
    tileSize = 256,
    layer: layerOptions = {},
  } = options

  const sourceId = getTdtSourceId(style, matrix)
  const layerId = getTdtLayerId(style, matrix)
  const tileUrl = buildTileUrlTemplate(options)
  const title = TDT_STYLE_NAMES[style] ?? style

  // ----------------------------------------------------------
  // 构建源配置
  // ----------------------------------------------------------
  const source: RasterSourceSpecification = {
    type: 'raster',
    tiles: [tileUrl],
    tileSize,
    minzoom,
    maxzoom,
    attribution:
      '&copy; <a href="https://www.tianditu.gov.cn" target="_blank">天地图</a>',
  }

  // ----------------------------------------------------------
  // 构建图层配置
  // ----------------------------------------------------------
  const layer: RasterLayerSpecification = {
    id: layerId,
    type: 'raster',
    source: sourceId,
    minzoom,
    maxzoom,
    metadata: {
      title,
      style,
      matrix,
      type: 'TdtLayer',
    },
    ...layerOptions,
  } as RasterLayerSpecification

  return { sourceId, source, layer }
}

/**
 * 创建天地图底图+注记的完整图层组
 *
 * 同时创建底图图层（vec/img/ter）和对应的中文注记图层（cva/cia/cta），
 * 注记图层会自动放置在底图图层之上。
 *
 * @param style - 底图样式（vec/img/ter），注记自动匹配
 * @param options - 共享的源配置（tk、matrix 等）
 * @returns 包含底图和注记两个 TdtSourceResult 的数组
 *
 * @example
 * ```ts
 * const [basemap, annotation] = createTdtLayerGroup('vec', { tk: 'your-key' })
 * // 先加底图，再加注记（注记在上层）
 * map.addSource(basemap.sourceId, basemap.source)
 * map.addLayer(basemap.layer)
 * map.addSource(annotation.sourceId, annotation.source)
 * map.addLayer(annotation.layer)
 * ```
 */
export function createTdtLayerGroup(
  style: 'vec' | 'img' | 'ter',
  options: Omit<TdtSourceOptions, 'style'> = {}
): [TdtSourceResult, TdtSourceResult] {
  const annotationStyleMap: Record<'vec' | 'img' | 'ter', TdtStyle> = {
    vec: 'cva',
    img: 'cia',
    ter: 'cta',
  }

  const basemap = createTdtSource({ ...options, style })
  const annotation = createTdtSource({
    ...options,
    style: annotationStyleMap[style],
  })

  return [basemap, annotation]
}
