import {
  type BlockLike,
  type DurableBlockCodec,
  type DurableFencePayloadInput,
} from './durableMarkdownBlocks'

export const GUANGHU_PORTAL_BLOCK_TYPE = 'guanghuPortalBlock'

const TOKEN_PREFIX = '@@TOLARIA_GUANGHU_PORTAL:'
const TOKEN_SUFFIX = '@@'

export interface GuanghuPortalPayload {
  source: string
  title: string
  target: string
  description: string
  status: string
}

function isRecord(value: unknown): value is Record<string, unknown> {
  return typeof value === 'object' && value !== null && !Array.isArray(value)
}

function readString(record: Record<string, unknown>, key: string): string {
  const value = record[key]
  return typeof value === 'string' ? value : ''
}

function decodePayload(payload: unknown): GuanghuPortalPayload | null {
  if (!isRecord(payload)) return null
  const source = readString(payload, 'source')
  const title = readString(payload, 'title')
  const target = readString(payload, 'target')
  if (!source || !title || !target) return null
  return {
    source,
    title,
    target,
    description: readString(payload, 'description'),
    status: readString(payload, 'status'),
  }
}

function readFenceMetadata(info: string): Record<string, never> | null {
  return info.trim().toLowerCase() === 'guanghu-portal' ? {} : null
}

function buildPayload({ lines, start, end }: DurableFencePayloadInput): GuanghuPortalPayload {
  const source = lines.slice(start, end + 1).join('')
  const body = lines.slice(start + 1, end).join('').trim()
  try {
    const decoded = decodePayload({ ...JSON.parse(body), source })
    if (decoded) return decoded
  } catch {
    // Invalid card data remains visible as an ordinary code block.
  }
  return { source, title: '光湖入口', target: '', description: body, status: '配置错误' }
}

function buildBlock(block: BlockLike, payload: GuanghuPortalPayload): BlockLike {
  if (!payload.target) return block
  return {
    ...block,
    type: GUANGHU_PORTAL_BLOCK_TYPE,
    props: {
      ...(block.props ?? {}),
      source: payload.source,
      title: payload.title,
      target: payload.target,
      description: payload.description,
      status: payload.status,
    },
    content: undefined,
    children: [],
  }
}

function isPortalBlock(block: BlockLike): boolean {
  return block.type === GUANGHU_PORTAL_BLOCK_TYPE
    && typeof block.props?.source === 'string'
    && typeof block.props?.target === 'string'
}

export const guanghuPortalMarkdownCodec: DurableBlockCodec = {
  tokenPrefix: TOKEN_PREFIX,
  tokenSuffix: TOKEN_SUFFIX,
  readFenceMetadata,
  buildPayload,
  decodePayload,
  buildBlock: (block, payload) => buildBlock(block, payload as GuanghuPortalPayload),
  isBlock: isPortalBlock,
  serializeBlock: block => block.props?.source ?? '',
}
