/**
 * Webhook event preview generator (Phase 4.5 / CEO plan v1 polish).
 *
 * <p>При schema definition'е admin видит какой shape JSON event получит
 * downstream consumer. Это важно для integrators (Альтум, Геопортал, etc) —
 * перед published'ом нового справочника они хотят посмотреть payload.
 *
 * <p>Функции генерируют sample envelope + payload для трёх record event
 * types + двух definition event types. Sample data заполняется placeholder'ами
 * на основе schema property types (string → "sample-string", number → 42, etc).
 *
 * <p>Output не отправляется в Kafka — это pure client-side preview. Backend
 * shapes (см. ordinis-events-api/src/main/java/.../events/) — единственный
 * source of truth; preview обновляется вместе с DTOs если schema меняется.
 */
import type { DataScope, JsonSchema } from '@/api/client'

const SAMPLE_UUID = '00000000-0000-0000-0000-000000000000'
const SAMPLE_TIMESTAMP = '2026-05-08T12:00:00+03:00'

/** Generate a placeholder value for one schema property based on type. */
const sampleValueFor = (prop: JsonSchema | undefined): unknown => {
  if (!prop) return null
  if (prop.enum && prop.enum.length > 0) return prop.enum[0]
  if (prop['x-localized']) return { 'ru-RU': 'Пример', 'en-US': 'Sample' }
  if (prop.type === 'integer') return 42
  if (prop.type === 'number') return 3.14
  if (prop.type === 'boolean') return true
  if (prop.type === 'array') {
    return [sampleValueFor(prop.items)]
  }
  if (prop.type === 'object' && prop.properties) {
    const out: Record<string, unknown> = {}
    for (const [k, v] of Object.entries(prop.properties)) {
      out[k] = sampleValueFor(v)
    }
    return out
  }
  // string fallback
  if (prop.format === 'date') return '2026-01-01'
  if (prop.format === 'date-time') return SAMPLE_TIMESTAMP
  if (prop['x-references']) return 'REF-001'
  return 'sample'
}

/** Build sample data record matching the schema's properties. */
export const sampleDataFor = (schema: JsonSchema): Record<string, unknown> => {
  const out: Record<string, unknown> = {}
  if (!schema.properties) return out
  for (const [key, prop] of Object.entries(schema.properties)) {
    out[key] = sampleValueFor(prop)
  }
  return out
}

type EnvelopeOptions = {
  dictionaryName: string
  dataScope: DataScope
  bundle: string
  eventType: string
}

const envelope = <T>(opts: EnvelopeOptions, payload: T) => ({
  eventId: SAMPLE_UUID,
  occurredAt: SAMPLE_TIMESTAMP,
  schemaVersion: '1.0.0',
  bundle: opts.bundle,
  dictionaryName: opts.dictionaryName,
  dataScope: opts.dataScope,
  traceId: 'sample-trace-id',
  spanId: 'sample-span-id',
  payload: { type: opts.eventType, ...payload },
})

export type EventPreview = {
  /** "RecordCreated" / "RecordUpdated" / "RecordDeleted" / "DefinitionCreated" / "DefinitionUpdated". */
  eventType: string
  /** Прозрачное название для UI tab. */
  label: string
  /** Краткое описание когда это событие fires. */
  description: string
  /** Topic name pattern в Kafka. */
  topic: string
  /** Полный JSON envelope + payload. */
  envelope: unknown
}

/** Генерирует все 5 sample events для текущей schema. */
export const generateEventPreviews = (
  dictionaryName: string,
  dataScope: DataScope,
  bundle: string,
  schema: JsonSchema,
  businessKeyField?: string,
): EventPreview[] => {
  const sampleData = sampleDataFor(schema)
  const businessKey =
    businessKeyField && typeof sampleData[businessKeyField] === 'string'
      ? (sampleData[businessKeyField] as string)
      : 'BK-001'
  const opts = (eventType: string): EnvelopeOptions => ({
    dictionaryName,
    dataScope,
    bundle,
    eventType,
  })
  const topic = `ordinis.${dictionaryName}.${dataScope.toLowerCase()}`

  return [
    {
      eventType: 'RecordCreated',
      label: 'Record Created',
      description: 'Новая запись добавлена в справочник',
      topic,
      envelope: envelope(opts('RecordCreated'), {
        recordId: SAMPLE_UUID,
        businessKey,
        data: sampleData,
        geometryWkt: null,
        validFrom: SAMPLE_TIMESTAMP,
        validTo: '9999-12-31T23:59:59Z',
        createdAt: SAMPLE_TIMESTAMP,
        createdBy: 'admin@example.org',
      }),
    },
    {
      eventType: 'RecordUpdated',
      label: 'Record Updated',
      description: 'Создана новая версия записи (старая закрыта validTo=now)',
      topic,
      envelope: envelope(opts('RecordUpdated'), {
        recordId: SAMPLE_UUID,
        previousRecordId: '11111111-1111-1111-1111-111111111111',
        businessKey,
        data: sampleData,
        previousData: { ...sampleData, _previous: true },
        geometryWkt: null,
        validFrom: SAMPLE_TIMESTAMP,
        validTo: '9999-12-31T23:59:59Z',
        updatedAt: SAMPLE_TIMESTAMP,
        updatedBy: 'admin@example.org',
      }),
    },
    {
      eventType: 'RecordDeleted',
      label: 'Record Deleted (closed)',
      description: 'Запись закрыта (valid_to = now). Реального DELETE нет — для audit',
      topic,
      envelope: envelope(opts('RecordDeleted'), {
        recordId: SAMPLE_UUID,
        businessKey,
        closedAt: SAMPLE_TIMESTAMP,
        deletedAt: SAMPLE_TIMESTAMP,
        deletedBy: 'admin@example.org',
        reason: 'manual close — example reason',
      }),
    },
    {
      eventType: 'DefinitionCreated',
      label: 'Definition Created',
      description: 'Справочник создан / реrgистрирован в каталоге',
      topic: `ordinis.definitions`,
      envelope: envelope(opts('DefinitionCreated'), {
        dictionaryId: SAMPLE_UUID,
        name: dictionaryName,
        displayName: dictionaryName,
        description: 'Sample dictionary description',
        scope: dataScope,
        schemaJson: schema,
        schemaVersion: '1.0.0',
        bundle,
        supportedLocales: ['ru-RU', 'en-US'],
        defaultLocale: 'ru-RU',
        createdAt: SAMPLE_TIMESTAMP,
        createdBy: 'admin@example.org',
      }),
    },
    {
      eventType: 'DefinitionUpdated',
      label: 'Definition Updated',
      description: 'Schema справочника изменена (новый schemaVersion)',
      topic: `ordinis.definitions`,
      envelope: envelope(opts('DefinitionUpdated'), {
        dictionaryId: SAMPLE_UUID,
        name: dictionaryName,
        displayName: dictionaryName,
        description: 'Updated dictionary description',
        scope: dataScope,
        schemaJson: schema,
        previousSchemaJson: { ...schema, _previous: true },
        schemaVersion: '1.1.0',
        bundle,
        supportedLocales: ['ru-RU', 'en-US'],
        defaultLocale: 'ru-RU',
        updatedAt: SAMPLE_TIMESTAMP,
        updatedBy: 'admin@example.org',
      }),
    },
  ]
}
