/**
 * Slug Validation Utilities
 *
 * Stellt sicher, dass Slugs innerhalb eines Tenants eindeutig sind.
 */

import type { Payload, Where } from 'payload'
import type { Config } from '@/payload-types'

type CollectionSlug = keyof Config['collections']
type LocaleType = 'de' | 'en' | 'all' | undefined

export interface SlugValidationOptions {
  /** Collection slug */
  collection: CollectionSlug
  /** Field name for slug (default: 'slug') */
  slugField?: string
  /** Field name for tenant (default: 'tenant') */
  tenantField?: string
  /** Whether to check per locale (default: false) */
  perLocale?: boolean
}

/**
 * Validates that a slug is unique within a tenant
 *
 * @throws Error if slug already exists for this tenant
 */
export async function validateUniqueSlug(
  payload: Payload,
  data: Record<string, unknown>,
  options: SlugValidationOptions & {
    existingId?: number | string
    locale?: string
  }
): Promise<void> {
  const {
    collection,
    slugField = 'slug',
    tenantField = 'tenant',
    perLocale = false,
    existingId,
    locale,
  } = options

  const slug = data[slugField]
  const tenantId = data[tenantField]

  // Skip if no slug provided
  if (!slug || typeof slug !== 'string') {
    return
  }

  // Build where clause
  const conditions: Where[] = [{ [slugField]: { equals: slug } }]

  // Add tenant filter if tenant is set
  if (tenantId) {
    conditions.push({ [tenantField]: { equals: tenantId } })
  }

  // Exclude current document when updating
  if (existingId) {
    conditions.push({ id: { not_equals: existingId } })
  }

  const where: Where = conditions.length > 1 ? { and: conditions } : conditions[0]

  // Determine locale for query
  const queryLocale: LocaleType = perLocale && locale ? (locale as LocaleType) : undefined

  // Check for existing documents with same slug
  const existing = await payload.find({
    collection,
    where,
    limit: 1,
    depth: 0,
    locale: queryLocale,
  })

  if (existing.totalDocs > 0) {
    const tenantInfo = tenantId ? ` für diesen Tenant` : ''
    throw new Error(`Der Slug "${slug}" existiert bereits${tenantInfo}. Bitte wählen Sie einen anderen.`)
  }
}

/**
 * Creates a beforeValidate hook for slug uniqueness
 */
export function createSlugValidationHook(options: SlugValidationOptions) {
  return async ({
    data,
    req,
    operation,
    originalDoc,
  }: {
    data?: Record<string, unknown>
    req: { payload: Payload; locale?: string }
    operation: 'create' | 'update'
    originalDoc?: { id?: number | string }
  }) => {
    if (!data) return data

    await validateUniqueSlug(req.payload, data, {
      ...options,
      existingId: operation === 'update' ? originalDoc?.id : undefined,
      locale: req.locale,
    })

    return data
  }
}

/**
 * Generates a unique slug by appending a number if necessary
 */
export async function generateUniqueSlug(
  payload: Payload,
  baseSlug: string,
  options: SlugValidationOptions & {
    existingId?: number | string
    tenantId?: number | string
  }
): Promise<string> {
  const { collection, slugField = 'slug', tenantField = 'tenant', existingId, tenantId } = options

  let slug = baseSlug
  let counter = 1
  let isUnique = false

  while (!isUnique && counter < 100) {
    const conditions: Where[] = [{ [slugField]: { equals: slug } }]

    if (tenantId) {
      conditions.push({ [tenantField]: { equals: tenantId } })
    }

    if (existingId) {
      conditions.push({ id: { not_equals: existingId } })
    }

    const where: Where = conditions.length > 1 ? { and: conditions } : conditions[0]

    const existing = await payload.find({
      collection,
      where,
      limit: 1,
      depth: 0,
    })

    if (existing.totalDocs === 0) {
      isUnique = true
    } else {
      slug = `${baseSlug}-${counter}`
      counter++
    }
  }

  return slug
}
