// OCPP 1.6-J over WebSocket protocol types

export const OCPP_MESSAGE_TYPE = {
  CALL: 2,
  CALLRESULT: 3,
  CALLERROR: 4,
} as const

// [MessageTypeId, UniqueId, Action, Payload]
export type OcppCall = [2, string, string, Record<string, unknown>]
// [MessageTypeId, UniqueId, Payload]
export type OcppCallResult = [3, string, Record<string, unknown>]
// [MessageTypeId, UniqueId, ErrorCode, ErrorDescription, ErrorDetails]
export type OcppCallError = [4, string, OcppErrorCode, string, Record<string, unknown>]

export type OcppMessage = OcppCall | OcppCallResult | OcppCallError

// OCPP 1.6-J Section 7.3.2 ErrorCode
export type OcppErrorCode =
  | 'NotImplemented'
  | 'NotSupported'
  | 'InternalError'
  | 'ProtocolError'
  | 'SecurityError'
  | 'FormationViolation'
  | 'PropertyConstraintViolation'
  | 'OccurenceConstraintViolation'
  | 'TypeConstraintViolation'
  | 'GenericError'

/** Per-connection mutable state shared across all action handlers */
export type OcppConnectionContext = {
  chargePointIdentifier: string
  isRegistered: boolean
}

export type OcppCallResultMessage = [3, string, Record<string, unknown>]
export type OcppCallErrorMessage = [4, string, OcppErrorCode, string, Record<string, unknown>]

export type CommandChannelStatus = 'online' | 'unavailable' | 'offline'

// ---------------------------------------------------------------------------
// Action payload types (OCPP 1.6-J Section 4.x)
// ---------------------------------------------------------------------------

// Section 4.2 BootNotification
export type BootNotificationRequest = {
  chargePointVendor: string        // CiString20Type, required
  chargePointModel: string         // CiString20Type, required
  chargePointSerialNumber?: string // CiString25Type
  chargeBoxSerialNumber?: string   // CiString25Type
  firmwareVersion?: string         // CiString50Type
  iccid?: string                   // CiString20Type
  imsi?: string                    // CiString20Type
  meterType?: string               // CiString25Type
  meterSerialNumber?: string       // CiString25Type
}

export type BootNotificationResponse = {
  currentTime: string               // UTC ISO 8601
  interval: number                  // heartbeat interval in seconds
  status: 'Accepted' | 'Pending' | 'Rejected'
}

// Section 4.8 Heartbeat
export type HeartbeatRequest = Record<string, never>

export type HeartbeatResponse = {
  currentTime: string
}

// Section 4.6 StatusNotification
export type StatusNotificationRequest = {
  connectorId: number   // 0 = whole charge point / main controller
  errorCode: string     // ChargePointErrorCode
  status: string        // ChargePointStatus
  timestamp?: string    // optional, UTC ISO 8601
  info?: string         // CiString50Type
  vendorId?: string     // CiString255Type
  vendorErrorCode?: string // CiString50Type
}

export type StatusNotificationResponse = Record<string, never>

// Section 4.1 Authorize
export type AuthorizeRequest = {
  idTag: string         // CiString20Type
}

export type IdTagInfo = {
  status: 'Accepted' | 'Blocked' | 'Expired' | 'Invalid' | 'ConcurrentTx'
  expiryDate?: string
  parentIdTag?: string
}

export type AuthorizeResponse = {
  idTagInfo: IdTagInfo
}

// Section 4.3 StartTransaction
export type StartTransactionRequest = {
  connectorId: number     // ≥1
  idTag: string           // CiString20Type
  meterStart: number      // Wh
  timestamp: string       // UTC ISO 8601
  reservationId?: number
}

export type StartTransactionResponse = {
  transactionId: number
  idTagInfo: IdTagInfo
}

// Section 4.4 StopTransaction
export type StopTransactionRequest = {
  transactionId: number
  meterStop: number       // Wh
  timestamp: string       // UTC ISO 8601
  reason?: string
  idTag?: string          // CiString20Type, optional (staff override)
  transactionData?: MeterValue[]
}

export type StopTransactionResponse = {
  idTagInfo?: IdTagInfo
}

// Section 4.7 MeterValues
export type SampledValue = {
  value: string
  context?: string
  format?: string
  measurand?: string
  phase?: string
  location?: string
  unit?: string
}

export type MeterValue = {
  timestamp: string
  sampledValue: SampledValue[]
}

export type MeterValuesRequest = {
  connectorId: number
  transactionId?: number
  meterValue: MeterValue[]
}

export type MeterValuesResponse = Record<string, never>
