import { ValidationError } from '../errors/dify-error'
import { isRecord } from '../internal/type-guards'

const MAX_STRING_LENGTH = 10000
const MAX_LIST_LENGTH = 1000
const MAX_DICT_LENGTH = 100

export function ensureNonEmptyString(value: unknown, name: string): asserts value is string {
  if (typeof value !== 'string' || value.trim().length === 0) {
    throw new ValidationError(`${name} must be a non-empty string`)
  }
  if (value.length > MAX_STRING_LENGTH) {
    throw new ValidationError(`${name} exceeds maximum length of ${MAX_STRING_LENGTH} characters`)
  }
}

/**
 * Validates optional string fields that must be non-empty when provided.
 * Use this for fields like `name` that are optional but should not be empty strings.
 *
 * For filter parameters that accept empty strings (e.g., `keyword: ""`),
 * use `validateParams` which allows empty strings for optional params.
 */
export function ensureOptionalString(value: unknown, name: string): void {
  if (value === undefined || value === null) {
    return
  }
  if (typeof value !== 'string' || value.trim().length === 0) {
    throw new ValidationError(`${name} must be a non-empty string when set`)
  }
  if (value.length > MAX_STRING_LENGTH) {
    throw new ValidationError(`${name} exceeds maximum length of ${MAX_STRING_LENGTH} characters`)
  }
}

export function ensureOptionalInt(value: unknown, name: string): void {
  if (value === undefined || value === null) {
    return
  }
  if (!Number.isInteger(value)) {
    throw new ValidationError(`${name} must be an integer when set`)
  }
}

export function ensureOptionalBoolean(value: unknown, name: string): void {
  if (value === undefined || value === null) {
    return
  }
  if (typeof value !== 'boolean') {
    throw new ValidationError(`${name} must be a boolean when set`)
  }
}

export function ensureStringArray(value: unknown, name: string): void {
  if (!Array.isArray(value) || value.length === 0) {
    throw new ValidationError(`${name} must be a non-empty string array`)
  }
  if (value.length > MAX_LIST_LENGTH) {
    throw new ValidationError(`${name} exceeds maximum size of ${MAX_LIST_LENGTH} items`)
  }
  value.forEach((item) => {
    if (typeof item !== 'string' || item.trim().length === 0) {
      throw new ValidationError(`${name} must contain non-empty strings`)
    }
  })
}

export function ensureOptionalStringArray(value: unknown, name: string): void {
  if (value === undefined || value === null) {
    return
  }
  ensureStringArray(value, name)
}

export function ensureRating(value: unknown): void {
  if (value === undefined || value === null) {
    return
  }
  if (value !== 'like' && value !== 'dislike') {
    throw new ValidationError("rating must be either 'like' or 'dislike'")
  }
}

export function validateParams(params: Record<string, unknown>): void {
  Object.entries(params).forEach(([key, value]) => {
    if (value === undefined || value === null) {
      return
    }

    // Only check max length for strings; empty strings are allowed for optional params
    // Required fields are validated at method level via ensureNonEmptyString
    if (typeof value === 'string') {
      if (value.length > MAX_STRING_LENGTH) {
        throw new ValidationError(
          `Parameter '${key}' exceeds maximum length of ${MAX_STRING_LENGTH} characters`,
        )
      }
    } else if (Array.isArray(value)) {
      if (value.length > MAX_LIST_LENGTH) {
        throw new ValidationError(
          `Parameter '${key}' exceeds maximum size of ${MAX_LIST_LENGTH} items`,
        )
      }
    } else if (isRecord(value)) {
      if (Object.keys(value).length > MAX_DICT_LENGTH) {
        throw new ValidationError(
          `Parameter '${key}' exceeds maximum size of ${MAX_DICT_LENGTH} items`,
        )
      }
    }

    if (key === 'user' && typeof value !== 'string') {
      throw new ValidationError(`Parameter '${key}' must be a string`)
    }
    if ((key === 'page' || key === 'limit' || key === 'page_size') && !Number.isInteger(value)) {
      throw new ValidationError(`Parameter '${key}' must be an integer`)
    }
    if (key === 'files' && !Array.isArray(value) && typeof value !== 'object') {
      throw new ValidationError(`Parameter '${key}' must be a list or dict`)
    }
    if (key === 'rating' && value !== 'like' && value !== 'dislike') {
      throw new ValidationError(`Parameter '${key}' must be 'like' or 'dislike'`)
    }
  })
}
