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 parseImportUrl = (value: string): URL | null => {
    const trimmed = value.trim ()
    if (!(trimmed))
      return null

    try
    {
      return new URL (trimmed)
    }
    catch
    {
      return null
    }
}


const normaliseImportUrl = (url: URL): string => {
  url.hostname = url.hostname.toLowerCase ()
  if (url.pathname.endsWith ('/'))
    url.pathname = url.pathname.replace (/\/+$/, '')
  return url.toString ()
}


export const extractImportSourceUrls = (source: string): string[] =>
    source
        .split (/\r\n|\n|\r/)
        .map (line => line.trim ())
        .filter (line => line !== '')


export const countImportSourceLines = (source: string): number =>
    extractImportSourceUrls (source).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)
      if (count > MAX_ROWS)
        {
          issues.push ({
              sourceRow,
              message: `取込件数は ${ MAX_ROWS } 件までです．`,
              url: displayUrl })
          return
        }
      if (bytesize (value) > MAX_URL_BYTES)
        {
          issues.push ({
              sourceRow,
              message: 'URL が長すぎます．',
              url: displayUrl })
          return
        }
      const parsed = parseImportUrl (value)
      if (parsed == null)
        {
          issues.push ({
              sourceRow,
              message: 'URL の形式が不正です．',
              url: displayUrl })
          return
        }
      if (!(parsed.protocol === 'http:' || parsed.protocol === 'https:'))
        {
          issues.push ({
              sourceRow,
              message: 'HTTP または HTTPS の URL ではありません．',
              url: displayUrl })
          return
        }
      if (!(parsed.host))
        {
          issues.push ({
              sourceRow,
              message: 'URL の形式が不正です．',
              url: displayUrl })
          return
        }
      const normalised = normaliseImportUrl (parsed)
      const duplicateRow = seen.get (normalised)
      if (duplicateRow != null)
        {
          issues.push ({
              sourceRow,
              message: `${ duplicateRow } 行目と同じ URL です．`,
              url: displayUrl })
          return
        }
      seen.set (normalised, sourceRow)
    })

    return issues
}
