// Tipos de identificadores
export type UUID = string
export type BpmnElementId = string

// ─── Entidades del modelo de dominio ─────────────────────────────────────────

export interface Process {
  id: UUID
  name: string
  clientName: string
  bpmnXml: string
  currency: string
  overheadPercentage: number
  annualFrequency: number         // 🆕 Sprint 1 — execuciones por año, default 1000
  analysisHorizonYears: number    // 🆕 Sprint 1 — horizonte de análisis en años, default 3
  automationInvestment: number    // 🆕 Sprint 1 — inversión total del proyecto, default 0
  createdAt: number
  updatedAt: number
  groupId: UUID | null            // 🆕 Sprint 3 — null = proceso sin grupo asignado ("Sin clasificar")
  tags: string[]                  // 🆕 Sprint 3 — tags libres para clasificación y búsqueda
}

export type ActivityType = 'task' | 'subprocess'

export interface Activity {
  id: UUID
  processId: UUID
  bpmnElementId: BpmnElementId
  name: string
  type: ActivityType
  directCostFixed: number
  executionTimeMinutes: number
  assignedResources: ActivityResourceAssignment[]
  automatable: boolean            // 🆕 Sprint 1 — si la actividad es candidata a automatización
  automatedCostFixed: number      // 🆕 Sprint 1 — costo recurrente por ejecución automatizada
  automatedTimeMinutes: number    // 🆕 Sprint 1 — tiempo de la actividad en escenario automatizado
  automatedAssignedResources: ActivityResourceAssignment[]   // 🆕 Sprint 3 — recursos del escenario automatizado (requerido desde Etapa 6)
}

export interface ActivityResourceAssignment {
  resourceId: UUID
  utilizationMinutes: number  // minutos que este recurso dedica por ejecución (independiente del tiempo de la actividad)
  units: number               // cantidad de unidades del recurso (ej: 2 impresoras). Default: 1.
}

export type GatewayType = 'exclusive' | 'parallel' | 'inclusive' | 'event-based'

export interface GatewayBranch {
  flowId: string
  targetElementId: BpmnElementId
  probability: number
}

export interface GatewayConfig {
  id: UUID
  processId: UUID
  bpmnElementId: BpmnElementId
  gatewayType: GatewayType
  branches: GatewayBranch[]
}

export type ResourceType = 'role' | 'person' | 'system' | 'equipment' | 'supply'

export interface Resource {
  id: UUID
  processId: UUID
  name: string
  type: ResourceType
  costPerHour: number
}

export interface Simulation {
  id: UUID
  processId: UUID
  executedAt: number
  result: SimulationResult           // escenario actual
  resultAutomated?: SimulationResult // 🆕 Sprint 1 — escenario automatizado (opcional por retrocompatibilidad)
}

// ─── Process Library ─────────────────────────────────────────────────────────

export interface ProcessGroup {
  id: UUID            // generado con crypto.randomUUID()
  name: string
  createdAt: number   // timestamp Unix ms
  updatedAt: number   // timestamp Unix ms
}

export interface AppSettings {
  id: 'singleton'     // siempre un único registro por instalación
  groupLabel: string  // etiqueta configurable para el nivel de agrupación. Default: 'Cliente'
}

// ─── Motor de simulación: Input/Output ───────────────────────────────────────

// Escenario de simulación: actual (campos directCostFixed/executionTimeMinutes)
// o automatizado (automatedCostFixed/automatedTimeMinutes para actividades marcadas).
export type Scenario = 'actual' | 'automated'

export interface SimulationInput {
  processXml: string
  activities: Map<BpmnElementId, Activity>
  gateways: Map<BpmnElementId, GatewayConfig>
  resources: Map<UUID, Resource>
  globalSettings: {
    currency: string
    overheadPercentage: number
  }
  scenario?: Scenario  // default 'actual' — opcional para retrocompatibilidad con tests existentes
}

export interface ActivitySimResult {
  activityId: UUID
  bpmnElementId: BpmnElementId
  activityName: string
  expectedDirectCost: number
  expectedIndirectCost: number
  expectedTotalCost: number
  percentOfTotal: number
  expectedExecutions: number
  executionProbability: number
  resourceCostBreakdown: Array<{ resourceId: UUID; resourceName: string; cost: number }>
  executionTimeMinutes: number
}

export interface ResourceSimResult {
  resourceId: UUID
  resourceName: string
  totalCost: number
  totalMinutesUsed: number
}

export interface SimulationResult {
  totalCost: number
  totalDirectCost: number
  totalIndirectCost: number
  totalTimeMinutes: number
  perActivity: ActivitySimResult[]
  perResource: ResourceSimResult[]
  warnings: string[]
}

// ─── Grafo en memoria (solo para el parser/motor) ────────────────────────────

export type BpmnNodeType =
  | 'startEvent'
  | 'endEvent'
  | 'task'
  | 'userTask'
  | 'serviceTask'
  | 'scriptTask'
  | 'manualTask'
  | 'businessRuleTask'
  | 'subprocess'
  | 'exclusiveGateway'
  | 'parallelGateway'
  | 'inclusiveGateway'
  | 'eventBasedGateway'
  | 'intermediateThrowEvent'
  | 'intermediateCatchEvent'
  | 'unknown'

export interface ProcessGraphNode {
  id: BpmnElementId
  name: string
  type: BpmnNodeType
  outgoing: string[]
  incoming: string[]
}

export interface ProcessGraphFlow {
  id: string
  sourceRef: BpmnElementId
  targetRef: BpmnElementId
  name?: string
}

export interface ProcessGraph {
  nodes: Map<BpmnElementId, ProcessGraphNode>
  flows: Map<string, ProcessGraphFlow>
  startEventIds: BpmnElementId[]
}

// ─── Helpers de clasificación ─────────────────────────────────────────────────

export function isTaskNode(type: BpmnNodeType): boolean {
  return ['task', 'userTask', 'serviceTask', 'scriptTask', 'manualTask', 'businessRuleTask', 'subprocess'].includes(type)
}

export function isGatewayNode(type: BpmnNodeType): boolean {
  return ['exclusiveGateway', 'parallelGateway', 'inclusiveGateway', 'eventBasedGateway'].includes(type)
}

export function bpmnTypeToActivityType(type: BpmnNodeType): ActivityType {
  return type === 'subprocess' ? 'subprocess' : 'task'
}

export function bpmnTypeToGatewayType(type: BpmnNodeType): GatewayType {
  switch (type) {
    case 'parallelGateway': return 'parallel'
    case 'inclusiveGateway': return 'inclusive'
    case 'eventBasedGateway': return 'event-based'
    default: return 'exclusive'
  }
}
