import { z } from 'zod'
import type { AdminCategoryRecord } from '@/lib/api/types'

export const defaultPerPage = 10
export const categoryPreviewWidth = 300
export const categoryPreviewHeight = 260
export const metaTitleMinLength = 50
export const metaTitleMaxLength = 60
export const metaDescriptionMinLength = 120
export const metaDescriptionMaxLength = 160

export type CategorySort = 'newest' | 'oldest' | 'name-asc' | 'name-desc' | 'order-asc'

export const categoryFormSchema = z.object({
  name: z.string().min(2, 'Kategori adı en az 2 karakter olmalıdır'),
  slug: z.string().min(2, 'Slug en az 2 karakter olmalıdır'),
  description: z.string().optional(),
  includes: z.array(z.string()).default([]),
  requirements: z.array(z.string()).default([]),
  scope: z.array(z.string()).default([]),
  image: z.string().optional(),
  isActive: z.boolean(),
  metaTitle: z
    .string()
    .max(
      metaTitleMaxLength,
      `Meta title en fazla ${metaTitleMaxLength} karakter olabilir`
    )
    .optional(),
  metaDescription: z
    .string()
    .max(
      metaDescriptionMaxLength,
      `Meta description en fazla ${metaDescriptionMaxLength} karakter olabilir`
    )
    .optional(),
})

export type CategoryFormInput = z.input<typeof categoryFormSchema>
export type CategoryFormValues = z.output<typeof categoryFormSchema>

export type CategoryDescriptionParts = {
  overviewHtml: string
  includes: string[]
  requirements: string[]
  scope: string[]
}

export type SeoCounterTone = 'good' | 'warning' | 'danger'

export const categorySectionLabels = {
  includes: 'Fiyata Dahil Olanlar',
  requirements: 'Gereksinimler',
  scope: 'Kapsam',
} as const

export function slugifyCategoryName(value: string) {
  return value
    .toLocaleLowerCase('tr')
    .replace(/ı/g, 'i')
    .replace(/ğ/g, 'g')
    .replace(/ü/g, 'u')
    .replace(/ş/g, 's')
    .replace(/ö/g, 'o')
    .replace(/ç/g, 'c')
    .replace(/[^a-z0-9]+/g, '-')
    .replace(/^-+|-+$/g, '')
}

export function escapeHtml(value: string) {
  return value.replace(/[&<>"']/g, (character) => {
    switch (character) {
      case '&':
        return '&amp;'
      case '<':
        return '&lt;'
      case '>':
        return '&gt;'
      case '"':
        return '&quot;'
      case "'":
        return '&#39;'
      default:
        return character
    }
  })
}

export function sanitizeRichTextHtml(value: string) {
  if (typeof DOMParser === 'undefined') {
    return value.trim()
  }

  const parser = new DOMParser()
  const document = parser.parseFromString(`<div>${value}</div>`, 'text/html')
  const root = document.body.firstElementChild as HTMLElement | null

  if (!root) {
    return ''
  }

  const allowedTags = new Set([
    'P',
    'BR',
    'STRONG',
    'B',
    'EM',
    'I',
    'U',
    'UL',
    'OL',
    'LI',
    'H2',
    'H3',
    'H4',
  ])

  const sanitizeNode = (node: Node) => {
    for (const child of Array.from(node.childNodes)) {
      if (child.nodeType === Node.COMMENT_NODE) {
        child.remove()
        continue
      }

      if (child.nodeType !== Node.ELEMENT_NODE) {
        continue
      }

      const element = child as HTMLElement
      sanitizeNode(element)

      if (!allowedTags.has(element.tagName)) {
        while (element.firstChild) {
          element.parentNode?.insertBefore(element.firstChild, element)
        }
        element.remove()
        continue
      }

      for (const attribute of Array.from(element.attributes)) {
        element.removeAttribute(attribute.name)
      }
    }
  }

  sanitizeNode(root)

  return root.innerHTML.replace(/(<br\s*\/?>\s*){3,}/g, '<br><br>').trim()
}

export function parseCategoryDescription(
  value: string | null | undefined
): CategoryDescriptionParts {
  const source = value?.trim() ?? ''

  if (!source) {
    return {
      overviewHtml: '',
      includes: [],
      requirements: [],
      scope: [],
    }
  }

  if (typeof DOMParser === 'undefined') {
    return {
      overviewHtml: source,
      includes: [],
      requirements: [],
      scope: [],
    }
  }

  const parser = new DOMParser()
  const document = parser.parseFromString(source, 'text/html')
  const overviewNode = document.querySelector(
    '[data-category-section="overview"]'
  )
  const hasStructuredSections = Boolean(
    overviewNode || document.querySelector('[data-category-list]')
  )

  if (!hasStructuredSections) {
    return {
      overviewHtml: source,
      includes: [],
      requirements: [],
      scope: [],
    }
  }

  const extractList = (key: keyof typeof categorySectionLabels) =>
    Array.from(document.querySelectorAll(`[data-category-list="${key}"] li`))
      .map((item) => item.textContent?.trim() ?? '')
      .filter(Boolean)

  return {
    overviewHtml: overviewNode?.innerHTML.trim() ?? '',
    includes: extractList('includes'),
    requirements: extractList('requirements'),
    scope: extractList('scope'),
  }
}

export function composeCategoryDescription(parts: CategoryDescriptionParts) {
  const overviewHtml = sanitizeRichTextHtml(parts.overviewHtml)
  const sections = (
    Object.entries(categorySectionLabels) as Array<
      [keyof typeof categorySectionLabels, string]
    >
  )
    .map(([key, title]) => {
      const items = parts[key].map((item) => item.trim()).filter(Boolean)

      if (!items.length) {
        return ''
      }

      return `<section data-category-list="${key}"><h3>${title}</h3><ul>${items
        .map((item) => `<li>${escapeHtml(item)}</li>`)
        .join('')}</ul></section>`
    })
    .filter(Boolean)

  return [
    overviewHtml
      ? `<section data-category-section="overview">${overviewHtml}</section>`
      : '',
    ...sections,
  ]
    .filter(Boolean)
    .join('')
}

export function getCategoryFormDefaults(
  category: AdminCategoryRecord | null
): CategoryFormInput {
  const descriptionParts = parseCategoryDescription(category?.description)

  return {
    name: category?.name ?? '',
    slug: category?.slug ?? '',
    description: descriptionParts.overviewHtml,
    includes: descriptionParts.includes,
    requirements: descriptionParts.requirements,
    scope: descriptionParts.scope,
    image: category?.image ?? '',
    isActive: category?.isActive ?? true,
    metaTitle: category?.metaTitle ?? '',
    metaDescription: category?.metaDescription ?? '',
  }
}

export function getSeoCounter(length: number, min: number, max: number) {
  if (length === 0) {
    return {
      tone: 'warning' as SeoCounterTone,
      text: `Önerilen aralık ${min}-${max} karakter.`,
    }
  }

  if (length < min) {
    return {
      tone: 'warning' as SeoCounterTone,
      text: `${length} karakter. En az ${min} hedefleyin.`,
    }
  }

  if (length > max) {
    return {
      tone: 'danger' as SeoCounterTone,
      text: `${length} karakter. ${max} üstüne çıkınca sonuçlar kesilebilir.`,
    }
  }

  return {
    tone: 'good' as SeoCounterTone,
    text: `${length} karakter. SEO için ideal aralıkta.`,
  }
}
