import { toIdempiereDate } from './idempiereDate'
import { sendFcmToUser } from './fcmNotifier'
import { sendPushToUser } from './pushNotifier'

/**
 * Push an existing ticket (r_request) to a mobile worker as a priority task.
 *
 * Shared by `requests/requests/[id]/push-task.post.ts` (ticket detail view) and
 * `orders/[id]/roadmap/push-step.post.ts` (order roadmap). One round trip on the
 * ticket: SalesRep_ID → worker, IsPushedTask/PushedTaskAt flagged, TaskStatus '0'
 * (= not started; push-task-status.post.ts moves it on). Then the dispatcher's
 * note is stored as an INTERNAL chat entry ("[Anweisung] …", never shown to the
 * merchant) and both push channels fire in parallel (native FCM for the
 * Capacitor app, web push for the PWA).
 *
 * Returns `{ status: 200, pushedTaskAt }` or `{ status: 500, message }` when the
 * ticket write failed (e.g. the custom columns IsPushedTask/PushedTaskAt don't
 * exist yet) — in that case nothing is pushed.
 */
export interface PushTaskOpts {
  targetUserId: number
  targetUserName?: string
  note?: string
}

export const pushTicketToWorker = async (event: any, token: any, ticketId: number | string, opts: PushTaskOpts) => {
  const id = Number(ticketId)
  const targetUserId = Number(opts?.targetUserId)
  if (!Number.isFinite(id) || id <= 0 || !Number.isFinite(targetUserId) || targetUserId <= 0) {
    return { status: 400, message: 'targetUserId ist erforderlich' }
  }

  const ticket: any = await event.context.fetch(
    `models/r_request/${id}?$select=DocumentNo,Name,Summary,AD_Org_ID`, 'GET', token, null
  )
  if (!ticket?.id) return { status: 404, message: 'Ticket nicht gefunden' }

  const docNo = ticket.DocumentNo || String(id)
  const subject = String(ticket.Name || '').trim() || String(ticket.Summary || '').trim().slice(0, 140)
  const note = (typeof opts?.note === 'string' ? opts.note.trim() : '').slice(0, 1000)
  const targetUserName = (typeof opts?.targetUserName === 'string' ? opts.targetUserName.trim() : '').slice(0, 120)
  const pushedTaskAt = toIdempiereDate(new Date())

  try {
    await event.context.fetch(`models/r_request/${id}`, 'PUT', token, {
      SalesRep_ID: { id: targetUserId, tableName: 'AD_User' },
      isPushedTask: true,
      pushedTaskAt,
      // Standard R_Request list column: '0' = not started. Flips to '2' when the
      // worker starts the timer (push-task-status.post.ts) → desktop "In Arbeit".
      TaskStatus: { id: '0' },
      tableName: 'R_Request'
    })
  } catch (e: any) {
    console.error('[push-task] ticket update failed (IsPushedTask/PushedTaskAt missing in iDempiere?):', e?.message)
    return {
      status: 500,
      message: 'Aufgabe konnte nicht gepusht werden — evtl. fehlen die Felder IsPushedTask/PushedTaskAt in iDempiere.'
    }
  }

  // Internal instruction note — fail-soft, the push itself already went out.
  if (note) {
    try {
      await event.context.fetch('models/r_requestupdate', 'POST', token, {
        AD_Org_ID: { id: ticket?.AD_Org_ID?.id, tableName: 'AD_Org' },
        R_Request_ID: { id, tableName: 'R_Request' },
        ConfidentialTypeEntry: { id: 'I' },
        isActive: true,
        qtySpent: 0,
        qtyInvoiced: 0,
        result: `[Anweisung] für ${targetUserName || 'Mitarbeiter'}\n${note}`,
        tableName: 'R_RequestUpdate'
      })
    } catch (e: any) {
      console.warn('[push-task] instruction note failed:', e?.message)
    }
  }

  const title = `📌 Neue priorisierte Aufgabe — #${docNo}`
  const pushBody = [subject, note].filter(Boolean).join('\n').slice(0, 400) || 'Ihnen wurde eine Aufgabe zugewiesen.'
  const data = { type: 'pushed_task', ticketId: String(id), docNo }

  await Promise.allSettled([
    sendFcmToUser(targetUserId, { title, body: pushBody, data }),
    sendPushToUser(targetUserId, {
      title,
      body: pushBody,
      data,
      url: `/mobile/tasks?pushedTaskId=${id}`,
      icon: '/favicon.ico',
      badge: '/favicon.ico',
      topic: `pushed-task-${id}`
    })
  ])

  return { status: 200, message: '', pushedTaskAt, docNo }
}
