import { string } from 'alga-js'
import fetchHelper from './fetchHelper'
import { relabelServiceToken, isRelabelOrder } from './relabelOrderHelper'

/**
 * Order roadmap — shared data access for `orders/[id]/roadmap.get.ts` and
 * `orders/[id]/roadmap/push-step.post.ts`.
 *
 * The roadmap is the staff checklist on the order edit page for orders that
 * need extra work before they can ship: Amazon-FBA relabel orders
 * (C_Order.isRelabelByFulfillmentProvider → codes in C_OrderLine.printLabelCode)
 * and orders with BOM positions (M_Product.IsBOM / isJtlBom → m_production
 * linked via C_OrderLine_ID). Each step can be pushed to a mobile worker as a
 * ticket (R_Request linked via C_Order_ID) — see pushTask.ts.
 */

export const menuTypeFromEvent = (event: any): string => {
  const roleCookie = getCookie(event, 'logship_role')
  try {
    const role = roleCookie ? JSON.parse(roleCookie) : null
    return role?.FrontendMenu?.id || role?.FrontendMenu || 'Menu'
  } catch {
    return 'Menu'
  }
}

export const isBomProduct = (prod: any) => {
  const v = prod?.IsBOM ?? prod?.isBOM
  const j = prod?.isJtlBom ?? prod?.IsJtlBom
  return v === true || v === 'Y' || j === true || j === 'Y'
}

export interface RoadmapOrder {
  id: number
  documentNo: string
  docStatusId: string
  organizationId: number | null
  organization: string
  partnerId: number | null
  isRelabel: boolean
}

export const fetchRoadmapOrder = async (event: any, token: any, orderId: number | string): Promise<RoadmapOrder | null> => {
  const id = Number(orderId)
  if (!Number.isFinite(id) || id <= 0) return null
  // Service token: the relabel column is hidden from limited roles (column
  // security) — same reasoning as relabelOrderHelper.fetchRelabelOrder.
  const o: any = await fetchHelper(event, `models/c_order/${id}`, 'GET', relabelServiceToken(token), null)
  if (!o?.id) return null
  return {
    id: Number(o.id),
    documentNo: o.DocumentNo || '',
    docStatusId: o.DocStatus?.id || o.DocStatus || '',
    organizationId: o.AD_Org_ID?.id ?? null,
    organization: o.AD_Org_ID?.identifier || '',
    partnerId: o.C_BPartner_ID?.id ?? null,
    isRelabel: isRelabelOrder(o)
  }
}

export interface RoadmapLine {
  id: number
  line: number
  productId: number | null
  sku: string
  product: string
  qtyOrdered: number
  qtyDelivered: number
  isBom: boolean
  printLabelCode: string
  isActive: boolean
}

/**
 * Product lines of the order with the BOM flag of their product and the FBA
 * label code. One bounded list with a to-one $expand (allowed — only child
 * tables must not be expanded over lists). `isJtlBom` is a custom column; if
 * the instance doesn't have it the $select is retried without it.
 */
export const fetchRoadmapLines = async (event: any, token: any, orderId: number | string): Promise<RoadmapLine[]> => {
  const id = Number(orderId)
  if (!Number.isFinite(id) || id <= 0) return []
  const readToken = relabelServiceToken(token)
  const filter = string.urlEncode(`C_Order_ID eq ${id}`)
  const load = async (expandSelect: string) => {
    const expand = string.urlEncode(`m_product_id($select=${expandSelect})`)
    const res: any = await fetchHelper(event, `models/c_orderline?$filter=${filter}&$expand=${expand}&$orderby=Line&$top=500`, 'GET', readToken, null)
    return res?.records || []
  }
  let records: any[] = []
  try {
    records = await load('Name,SKU,Value,IsBOM,isJtlBom')
  } catch {
    records = await load('Name,SKU,Value,IsBOM')
  }
  return records
    .filter((l: any) => l?.M_Product_ID?.id)
    .map((l: any) => ({
      id: Number(l.id),
      line: Number(l.Line) || 0,
      productId: l.M_Product_ID?.id ?? null,
      sku: l.M_Product_ID?.SKU || l.M_Product_ID?.Value || '',
      product: String(l.M_Product_ID?.Name || l.M_Product_ID?.identifier || '').replace(/^-1_/, ''),
      qtyOrdered: Number(l.QtyEntered ?? l.QtyOrdered ?? 0) || 0,
      qtyDelivered: Number(l.QtyDelivered ?? 0) || 0,
      isBom: isBomProduct(l.M_Product_ID),
      printLabelCode: String(l?.printLabelCode ?? l?.PrintLabelCode ?? '').trim(),
      isActive: l?.IsActive !== false
    }))
}

export interface RoadmapTicket {
  id: number
  documentNo: string
  summary: string
  created: string
  statusId: number | null
  status: string
  isClosed: boolean
  isComplete: boolean
  salesRepId: number | null
  salesRep: string
  requestTypeId: number | null
  requestType: string
  productionId: number | null
  productId: number | null
  isPushedTask: boolean
  pushedTaskAt: string | null
  taskStatus: string
}

/**
 * Tickets linked to the order (R_Request.C_Order_ID), newest first, with the
 * push-task state. No $select on purpose: the custom columns
 * (IsPushedTask/PushedTaskAt) may not exist on every instance and REST simply
 * omits columns that are NULL/absent. Open/closed joins r_status.IsClosed
 * (same as orders/[id]/requests.get.ts).
 */
export const fetchRoadmapTickets = async (event: any, token: any, orderId: number | string): Promise<RoadmapTicket[]> => {
  const id = Number(orderId)
  if (!Number.isFinite(id) || id <= 0) return []
  const res: any = await fetchHelper(event, `models/r_request?$filter=${string.urlEncode('C_Order_ID eq ' + id)}&$orderby=${string.urlEncode('Created desc')}&$top=200`, 'GET', token, null)

  const statusClosed: Record<number, boolean> = {}
  try {
    const stRes: any = await fetchHelper(event, 'models/r_status?$top=200', 'GET', token, null)
    for (const st of (stRes?.records || [])) statusClosed[st.id] = st.IsClosed === true
  } catch {} // non-fatal — isClosed then relies on Processed / IsComplete alone

  return (res?.records || []).map((r: any): RoadmapTicket => {
    const statusId = r.R_Status_ID?.id ?? null
    const isComplete = r.IsComplete === true || r.isComplete === true || r.IsComplete === 'Y'
    return {
      id: Number(r.id),
      documentNo: r.DocumentNo || '',
      summary: r.Summary || '',
      created: r.Created || '',
      statusId,
      status: r.R_Status_ID?.identifier || '',
      isClosed: (statusId != null && statusClosed[statusId] === true) || r.Processed === true || isComplete,
      isComplete,
      salesRepId: r.SalesRep_ID?.id ?? null,
      salesRep: r.SalesRep_ID?.identifier || '',
      requestTypeId: r.R_RequestType_ID?.id ?? null,
      requestType: r.R_RequestType_ID?.identifier || '',
      productionId: r.M_Production_ID?.id ?? null,
      productId: r.M_Product_ID?.id ?? null,
      isPushedTask: !!(r.IsPushedTask ?? r.isPushedTask),
      pushedTaskAt: r.PushedTaskAt ?? r.pushedTaskAt ?? null,
      taskStatus: String(r.TaskStatus?.id ?? r.TaskStatus ?? '')
    }
  })
}

// A ticket the roadmap may still reuse for a push: not closed / completed.
export const isOpenTicket = (t: RoadmapTicket | null | undefined) => !!t && !t.isClosed && !t.isComplete
