import type { PostImportSourceIssue } from '@/lib/postImportTypes'

const MAX_ROWS = 100
const MAX_URL_BYTES = 20 * 1024


const truncateUrl = (value: string): string =>
    value.length > 120 ? `${ value.slice (0, 117) }…` : value


const bytesize = (value: string): number =>
    new TextEncoder ().encode (value).length


const normaliseImportUrl = (value: string): string | null => {
    const trimmed = value.trim ()
    if (!(trimmed))
      return null

    try
    {
      const url = new URL (trimmed)
      if (!(url.protocol === 'http:' || url.protocol === 'https:'))
        return null
      if (!(url.host))
        return null

      url.hostname = url.hostname.toLowerCase ()
      if (url.pathname.endsWith ('/'))
        url.pathname = url.pathname.replace (/\/+$/, '')
      return url.toString ()
    }
    catch
    {
      return null
    }
}


export const countImportSourceLines = (source: string): number =>
    source
        .split (/\r\n|\n|\r/)
        .map (line => line.trim ())
        .filter (line => line !== '')
        .length


export const validateImportSource = (
    source: string,
): PostImportSourceIssue[] => {
    const lines = source.split (/\r\n|\n|\r/)
    const issues: PostImportSourceIssue[] = []
    const seen = new Map<string, number> ()
    let count = 0

    lines.forEach ((rawLine, index) => {
      const value = rawLine.trim ()
      if (!(value))
        return

      ++count
      const sourceRow = index + 1
      const displayUrl = truncateUrl (value)
      const normalised = normaliseImportUrl (value)
      if (count > MAX_ROWS)
        {
          issues.push ({
              sourceRow,
              message: `取込件数は ${ MAX_ROWS } 件までです．`,
              url: displayUrl })
          return
        }
      if (!(value.startsWith ('http://') || value.startsWith ('https://')))
        {
          issues.push ({
              sourceRow,
              message: 'HTTP または HTTPS の URL ではありません．',
              url: displayUrl })
          return
        }
      if (bytesize (value) > MAX_URL_BYTES)
        {
          issues.push ({
              sourceRow,
              message: 'URL が長すぎます．',
              url: displayUrl })
          return
        }
      if (normalised == null)
        {
          issues.push ({
              sourceRow,
              message: 'URL の形式が不正です．',
              url: displayUrl })
          return
        }
      const duplicateRow = seen.get (normalised)
      if (duplicateRow != null)
        {
          issues.push ({
              sourceRow,
              message: `${ duplicateRow } 行目と同じ URL です．`,
              url: displayUrl })
          return
        }
      seen.set (normalised, sourceRow)
    })

    return issues
}
