import type { ParamFieldDef, StorageLoc, TaskTemplateDsl } from '../types'

export const SEED_AREAS = [
  { areaId: 'A-STOR', name: '原材料存储区', areaType: 'Storage', lineId: undefined as string | undefined },
  { areaId: 'A-LINE1', name: '一线线边', areaType: 'LineSide', lineId: 'L1' },
  { areaId: 'A-LINE2', name: '二线线边', areaType: 'LineSide', lineId: 'L2' },
  { areaId: 'A-BUF', name: '空箱缓冲', areaType: 'Buffer', lineId: undefined }
]

export function createSeedStorages(): StorageLoc[] {
  return [
    { storageId: 'S-01', areaId: 'A-STOR', areaType: 'Storage', storageType: 'Storage', status: 'FullContainer', materialAffinity: ['M001', 'M002'], disabled: false, allowInbound: true, allowOutbound: true, inboundAt: '2026-08-01T08:00:00Z', x: 10, y: 10, qty: 10 },
    { storageId: 'S-02', areaId: 'A-STOR', areaType: 'Storage', storageType: 'Storage', status: 'FullContainer', materialAffinity: ['M001'], disabled: false, allowInbound: true, allowOutbound: true, inboundAt: '2026-08-03T08:00:00Z', x: 12, y: 10, qty: 8 },
    { storageId: 'S-03', areaId: 'A-STOR', areaType: 'Storage', storageType: 'Storage', status: 'FullContainer', materialAffinity: ['M003'], disabled: false, allowInbound: true, allowOutbound: true, inboundAt: '2026-08-02T08:00:00Z', x: 20, y: 10, qty: 5 },
    { storageId: 'S-04', areaId: 'A-STOR', areaType: 'Storage', storageType: 'Storage', status: 'EmptyContainer', materialAffinity: ['M001'], disabled: false, allowInbound: true, allowOutbound: true, x: 11, y: 12, qty: 0 },
    { storageId: 'S-05', areaId: 'A-STOR', areaType: 'Storage', storageType: 'Storage', status: 'FullContainer', materialAffinity: ['M001'], disabled: true, allowInbound: false, allowOutbound: false, inboundAt: '2026-08-01T09:00:00Z', x: 15, y: 10, qty: 3 },
    { storageId: 'S-06', areaId: 'A-STOR', areaType: 'Storage', storageType: 'Storage', status: 'FullContainer', materialAffinity: ['M001'], disabled: false, allowInbound: true, allowOutbound: true, inboundAt: '2026-07-20T08:00:00Z', x: 30, y: 30, qty: 12 },
    { storageId: 'T-L1-01', areaId: 'A-LINE1', areaType: 'LineSide', storageType: 'LineSide', status: 'EmptyContainer', materialAffinity: [], disabled: false, lineId: 'L1', allowInbound: true, allowOutbound: true, x: 50, y: 10 },
    { storageId: 'T-L1-02', areaId: 'A-LINE1', areaType: 'LineSide', storageType: 'LineSide', status: 'EmptyContainer', materialAffinity: [], disabled: false, lineId: 'L1', allowInbound: true, allowOutbound: true, x: 52, y: 10 },
    { storageId: 'T-L1-03', areaId: 'A-LINE1', areaType: 'LineSide', storageType: 'LineSide', status: 'FullContainer', materialAffinity: ['M001'], disabled: false, lineId: 'L1', allowInbound: false, allowOutbound: true, x: 54, y: 10 },
    { storageId: 'T-L2-01', areaId: 'A-LINE2', areaType: 'LineSide', storageType: 'LineSide', status: 'EmptyContainer', materialAffinity: [], disabled: false, lineId: 'L2', allowInbound: true, allowOutbound: true, x: 50, y: 40 },
    { storageId: 'B-01', areaId: 'A-BUF', areaType: 'Buffer', storageType: 'Buffer', status: 'Empty', materialAffinity: [], disabled: false, allowInbound: true, allowOutbound: true, x: 5, y: 5 }
  ]
}

export const PARAM_FIELDS: ParamFieldDef[] = [
  { module: 'mes', path: 'call.materialCode', valueType: 'string', resolveMode: 'eventPayload', description: '叫料物料号' },
  { module: 'mes', path: 'call.qty', valueType: 'number', resolveMode: 'eventPayload', description: '叫料数量' },
  { module: 'aps', path: 'wo.lineId', valueType: 'string', resolveMode: 'eventPayload', description: '工单产线' },
  { module: 'wms', path: 'policy.lineSideZone', valueType: 'string', resolveMode: 'lookup', description: '产线对应线边库区' }
]

export const LOOKUP_TABLE: Record<string, string> = {
  'line:L1': 'A-LINE1',
  'line:L2': 'A-LINE2'
}

function andGroup(...compares: Array<{ left: string; op: string; right?: unknown; rightRef?: string }>) {
  return {
    type: 'group' as const,
    op: 'and' as const,
    children: compares.map((c) => ({
      type: 'compare' as const,
      left: { ref: c.left },
      op: c.op as 'eq',
      right: c.rightRef ? { ref: c.rightRef } : { const: c.right as never }
    }))
  }
}

export function createPresetTemplates(): TaskTemplateDsl[] {
  const sourceHard = {
    id: 'src-hard',
    severity: 'hard' as const,
    expr: andGroup(
      { left: 'wcs.disabled', op: 'eq', right: false },
      { left: 'wcs.storageType', op: 'eq', right: 'Storage' },
      { left: 'wcs.materialAffinity', op: 'contains', rightRef: 'context.materialCode' },
      { left: 'wcs.status', op: 'in', right: ['FullContainer'] },
      { left: 'wcs.allowOutbound', op: 'eq', right: true }
    )
  }
  const sourceSoftNear = {
    id: 'src-soft-near',
    severity: 'soft' as const,
    expr: andGroup(
      { left: 'wcs.x', op: 'lt', right: 25 }
    )
  }
  const targetHard = {
    id: 'tgt-hard',
    severity: 'hard' as const,
    expr: andGroup(
      { left: 'wcs.disabled', op: 'eq', right: false },
      { left: 'wcs.storageType', op: 'eq', right: 'LineSide' },
      { left: 'wcs.lineId', op: 'eq', rightRef: 'context.lineId' },
      { left: 'wcs.status', op: 'eq', right: 'EmptyContainer' },
      { left: 'wcs.allowInbound', op: 'eq', right: true }
    )
  }
  const targetSoftZone = {
    id: 'tgt-soft-zone',
    severity: 'soft' as const,
    expr: andGroup(
      { left: 'wcs.areaId', op: 'eq', rightRef: 'context.preferZone' }
    )
  }

  const base = (id: string, name: string, priority: number): TaskTemplateDsl => ({
    schemaVersion: 1,
    id,
    name,
    published: true,
    meta: { priority, mutexGroup: 'line-side-replenish', routeMode: 'single_winner' },
    trigger: {
      type: 'event',
      source: 'mes.materialCall',
      idempotency: { keyMode: 'eventId', onTerminalHit: 'reject' },
      merge: { windowMs: 0, keyFrom: [] }
    },
    bindings: [
      { as: 'materialCode', from: 'mes.call.materialCode', required: true, resolve: 'eventPayload' },
      { as: 'qty', from: 'mes.call.qty', required: false, resolve: 'eventPayload', default: 1 },
      { as: 'lineId', from: 'aps.wo.lineId', required: true, resolve: 'eventPayload' },
      {
        as: 'preferZone',
        from: 'wms.policy.lineSideZone',
        required: false,
        resolve: 'lookup',
        key: { template: 'line:{lineId}', args: { lineId: 'context.lineId' } },
        onError: 'default',
        default: 'A-LINE1',
        cacheTtlSec: 60
      }
    ],
    locationStrategies: {
      source: {
        filterGroups: [sourceHard, sourceSoftNear],
        degradeChain: [
          { attempt: 0, requireGroups: ['src-hard', 'src-soft-near'] },
          { attempt: 1, requireGroups: ['src-hard'], drop: ['src-soft-near'] }
        ],
        scores: [
          { id: 's-fifo', function: 'fifo_age', weight: 1, params: { timeField: 'inboundAt' } },
          { id: 's-near', function: 'nearer_to_ref', weight: 2, params: { refX: 50, refY: 10, metric: 'euclid' } }
        ],
        allocate: { mode: 'first', topN: 5 }
      },
      target: {
        filterGroups: [targetHard, targetSoftZone],
        degradeChain: [
          { attempt: 0, requireGroups: ['tgt-hard', 'tgt-soft-zone'] },
          { attempt: 1, requireGroups: ['tgt-hard'], drop: ['tgt-soft-zone'] }
        ],
        scores: [
          { id: 't-near', function: 'nearer_to_ref', weight: 1, params: { refX: 50, refY: 10, metric: 'euclid' } }
        ],
        allocate: { mode: 'first', topN: 5 }
      }
    },
    blueprint: {
      taskType: 'transport',
      slots: { from: 'source', to: 'target' },
      options: { autoDispatch: true, priority: 50 }
    },
    policy: {
      reservationTtlSec: 120,
      allocateMaxAttempts: 5,
      allocateBackoffMs: [0, 0, 0, 0, 0],
      onNoCandidate: 'raise_alert',
      onRealityDrift: 'fail',
      onDispatchReject: 'compensate'
    }
  })

  const a = base('tpl-line-replenish-A', '线边补料-A（高优先）', 200)
  const b = base('tpl-line-replenish-B', '线边补料-B（低优先）', 100)
  // B 更宽：源不要求 FullContainer，仅 soft 更松
  b.locationStrategies.source.filterGroups = [
    {
      id: 'src-hard',
      severity: 'hard',
      expr: andGroup(
        { left: 'wcs.disabled', op: 'eq', right: false },
        { left: 'wcs.materialAffinity', op: 'contains', rightRef: 'context.materialCode' }
      )
    }
  ]
  b.locationStrategies.source.degradeChain = [{ attempt: 0, requireGroups: ['src-hard'] }]
  return [a, b]
}

export const DEMO_EVENT = {
  eventId: 'evt-demo-001',
  source: 'mes.materialCall',
  payload: { materialCode: 'M001', qty: 1, lineId: 'L1', priority: 50 }
}
