import type { Doc } from "./_generated/dataModel"

export type AutomationTrigger =
  | "TICKET_CREATED"
  | "STATUS_CHANGED"
  | "PRIORITY_CHANGED"
  | "QUEUE_CHANGED"
  | "COMMENT_ADDED"
  | "TICKET_RESOLVED"

export type AutomationConditionOperator = "AND" | "OR"

export type AutomationConditionField =
  | "companyId"
  | "queueId"
  | "categoryId"
  | "subcategoryId"
  | "priority"
  | "status"
  | "channel"
  | "formTemplate"
  | "chatEnabled"
  | "tag"

export type AutomationConditionComparator =
  | "eq"
  | "neq"
  | "in"
  | "not_in"
  | "contains"
  | "not_contains"
  | "is_true"
  | "is_false"

export type AutomationCondition = {
  field: AutomationConditionField
  op: AutomationConditionComparator
  value?: unknown
}

export type AutomationConditionGroup = {
  op: AutomationConditionOperator
  conditions: AutomationCondition[]
}

export type TicketForAutomation = Pick<
  Doc<"tickets">,
  | "tenantId"
  | "status"
  | "priority"
  | "channel"
  | "queueId"
  | "companyId"
  | "categoryId"
  | "subcategoryId"
  | "tags"
  | "formTemplate"
  | "chatEnabled"
>

function normalizeId(value: unknown): string | null {
  if (!value) return null
  return String(value)
}

function normalizeString(value: unknown): string | null {
  if (typeof value !== "string") return null
  const trimmed = value.trim()
  return trimmed.length > 0 ? trimmed : null
}

function normalizeStringArray(value: unknown): string[] {
  if (!Array.isArray(value)) return []
  return value.map((item) => normalizeString(item)).filter((item): item is string => Boolean(item))
}

function normalizeBoolean(value: unknown): boolean | null {
  if (typeof value === "boolean") return value
  return null
}

function compareValue(actual: string | null, op: AutomationConditionComparator, expected: unknown): boolean {
  if (op === "eq") return actual === normalizeId(expected)
  if (op === "neq") return actual !== normalizeId(expected)
  if (op === "in") {
    const list = normalizeStringArray(expected).map((v) => v)
    return actual !== null && list.includes(actual)
  }
  if (op === "not_in") {
    const list = normalizeStringArray(expected).map((v) => v)
    return actual === null || !list.includes(actual)
  }
  return false
}

export function evaluateAutomationConditions(
  ticket: TicketForAutomation,
  group: AutomationConditionGroup | null | undefined
): boolean {
  if (!group || !Array.isArray(group.conditions) || group.conditions.length === 0) return true
  const op = group.op === "OR" ? "OR" : "AND"

  const results = group.conditions.map((condition) => {
    const field = condition.field
    const operator = condition.op

    if (field === "companyId") return compareValue(normalizeId(ticket.companyId), operator, condition.value)
    if (field === "queueId") return compareValue(normalizeId(ticket.queueId), operator, condition.value)
    if (field === "categoryId") return compareValue(normalizeId(ticket.categoryId), operator, condition.value)
    if (field === "subcategoryId") return compareValue(normalizeId(ticket.subcategoryId), operator, condition.value)
    if (field === "priority") return compareValue(normalizeString(ticket.priority), operator, condition.value)
    if (field === "status") return compareValue(normalizeString(ticket.status), operator, condition.value)
    if (field === "channel") return compareValue(normalizeString(ticket.channel), operator, condition.value)
    if (field === "formTemplate") return compareValue(normalizeString(ticket.formTemplate), operator, condition.value)

    if (field === "chatEnabled") {
      const expectedBool = normalizeBoolean(condition.value)
      if (operator === "is_true") return ticket.chatEnabled === true
      if (operator === "is_false") return ticket.chatEnabled !== true
      if (operator === "eq") return expectedBool !== null ? Boolean(ticket.chatEnabled) === expectedBool : false
      if (operator === "neq") return expectedBool !== null ? Boolean(ticket.chatEnabled) !== expectedBool : false
      return false
    }

    if (field === "tag") {
      const tag = normalizeString(condition.value)
      if (!tag) return false
      const has = (ticket.tags ?? []).includes(tag)
      if (operator === "contains" || operator === "eq") return has
      if (operator === "not_contains" || operator === "neq") return !has
      return false
    }

    return false
  })

  return op === "OR" ? results.some(Boolean) : results.every(Boolean)
}
