/**
 * Software Factory Core — Factory Contract
 *
 * PR-36 Part B：统一 Factory 接口定义。
 *
 * 所有 SF-01 ~ SF-15 必须遵守此合约。
 * 合约定义 6 个核心类型：Input / Output / Artifact / Metric / Report / Dependency。
 *
 * 设计原则：
 *   - Pure type definitions + factory functions, no side effects
 *   - Immutable creation pattern (factory functions return new objects)
 *   - All factories share these contracts — no factory-specific fields in core types
 *   - Metadata field for factory-specific extensions
 *   - Builds on PR-35 agent-runtime domain model
 *
 * @module software-factory-core/factory-contract
 * @since PR-36
 */

// ═══════════════════════════════════════════════════════
// Part B-1：FactoryInput
// ═══════════════════════════════════════════════════════

/**
 * Factory Input — 进入任意 Factory 的统一输入接口。
 *
 * 携带：
 *   - 调用方身份（factoryId 标识哪个 Factory 被调用）
 *   - 任务上下文（来自 PR-35 Runtime Task）
 *   - 产品上下文（产品模型引用）
 *   - 上游产物（上一阶段 Factory 的输出产物）
 *   - 运行时参数（Factory 特定参数）
 *   - 约束条件
 *
 * @typedef {object} FactoryInput
 * @property {string} factoryId       — 目标 Factory ID (SF-01 ~ SF-15)
 * @property {object|null} task       — PR-35 Task 对象
 * @property {object|null} product    — PR-36 ProductModel 对象
 * @property {object[]} upstreamArtifacts — 上游产物列表
 * @property {object} parameters      — Factory 特定参数
 * @property {object} constraints     — 约束条件（时间/资源/质量）
 * @property {object} metadata        — 扩展元数据
 */

let _inputSeq = 0;

/**
 * @param {object} p
 * @param {string} p.factoryId
 * @param {object|null} [p.task=null]
 * @param {object|null} [p.product=null]
 * @param {object[]} [p.upstreamArtifacts=[]]
 * @param {object} [p.parameters={}]
 * @param {object} [p.constraints={}]
 * @param {object} [p.metadata={}]
 * @returns {FactoryInput}
 */
export function createFactoryInput({
  factoryId,
  task = null,
  product = null,
  upstreamArtifacts = [],
  parameters = {},
  constraints = {},
  metadata = {},
}) {
  if (!factoryId) throw new TypeError("FactoryInput.factoryId is required");

  return {
    id: `fi-${++_inputSeq}`,
    factoryId,
    task,
    product,
    upstreamArtifacts: [...upstreamArtifacts],
    parameters: { ...parameters },
    constraints: {
      timeBudgetMs: constraints.timeBudgetMs ?? null,
      resourceLimits: constraints.resourceLimits ?? {},
      qualityThreshold: constraints.qualityThreshold ?? null,
      ...constraints,
    },
    metadata: { ...metadata },
    createdAt: new Date().toISOString(),
  };
}

// ═══════════════════════════════════════════════════════
// Part B-2：FactoryOutput
// ═══════════════════════════════════════════════════════

/**
 * Factory Output — 任意 Factory 的统一输出接口。
 *
 * 携带：
 *   - 执行结果（passed/failed/blocked）
 *   - 产出物列表（下游 Factory 的输入）
 *   - 度量指标
 *   - 风险清单
 *   - 决策记录
 *   - 建议的下一步动作
 *
 * @typedef {object} FactoryOutput
 * @property {string} factoryId       — 来源 Factory ID
 * @property {string} status          — "passed" | "failed" | "blocked" | "partial"
 * @property {object[]} artifacts     — 产出物列表
 * @property {object[]} metrics       — 度量指标
 * @property {object[]} risks         — 风险清单
 * @property {object[]} decisions     — 决策记录
 * @property {string[]} nextActions   — 建议的下步动作
 * @property {string|null} error      — 错误信息（若 failed）
 */

let _outputSeq = 0;

/**
 * @param {object} p
 * @param {string} p.factoryId
 * @param {"passed"|"failed"|"blocked"|"partial"} p.status
 * @param {object[]} [p.artifacts=[]]
 * @param {object[]} [p.metrics=[]]
 * @param {object[]} [p.risks=[]]
 * @param {object[]} [p.decisions=[]]
 * @param {string[]} [p.nextActions=[]]
 * @param {string|null} [p.error=null]
 * @param {object} [p.metadata={}]
 * @returns {FactoryOutput}
 */
export function createFactoryOutput({
  factoryId,
  status,
  artifacts = [],
  metrics = [],
  risks = [],
  decisions = [],
  nextActions = [],
  error = null,
  metadata = {},
}) {
  if (!factoryId) throw new TypeError("FactoryOutput.factoryId is required");
  if (!["passed", "failed", "blocked", "partial"].includes(status)) {
    throw new TypeError(`Invalid FactoryOutput.status: ${status}`);
  }

  return {
    id: `fo-${++_outputSeq}`,
    factoryId,
    status,
    artifacts: [...artifacts],
    metrics: [...metrics],
    risks: [...risks],
    decisions: [...decisions],
    nextActions: [...nextActions],
    error,
    metadata: { ...metadata },
    createdAt: new Date().toISOString(),
  };
}

// ═══════════════════════════════════════════════════════
// Part B-3：FactoryArtifact
// ═══════════════════════════════════════════════════════

/**
 * FactoryArtifact — Factory 产出的统一产物接口。
 *
 * 产物类型覆盖全生命周期：
 *   - requirement   需求文档
 *   - prototype     原型图
 *   - design        设计稿
 *   - architecture  架构图
 *   - code          代码
 *   - test          测试
 *   - release       发布包
 *   - report        报告
 *   - operations    运维报告
 *   - marketing     营销资料
 *
 * 与 PR-35 Artifact 的关系：
 *   FactoryArtifact 是 PR-35 Artifact 的高级包装，
 *   额外增加 factoryId / productId / dependencies / lineage。
 *
 * @typedef {object} FactoryArtifact
 */

export const FACTORY_ARTIFACT_KIND = Object.freeze({
  REQUIREMENT:   "requirement",
  PROTOTYPE:     "prototype",
  DESIGN:        "design",
  ARCHITECTURE:  "architecture",
  CODE:          "code",
  TEST:          "test",
  RELEASE:       "release",
  REPORT:        "report",
  OPERATIONS:    "operations",
  MARKETING:     "marketing",
  OTHER:         "other",
});

let _faSeq = 0;

/**
 * @param {object} p
 * @param {string} [p.id]
 * @param {string} p.kind          — FACTORY_ARTIFACT_KIND
 * @param {string} p.name
 * @param {string} p.factoryId     — 产出 Factory
 * @param {string|null} [p.productId=null]
 * @param {number} [p.version=1]
 * @param {string[]} [p.dependencies=[]]  — 依赖的其他 artifact IDs
 * @param {string|null} [p.parentId=null] — 血缘：父 artifact ID
 * @param {string|null} [p.path=null]     — 文件路径
 * @param {string|null} [p.content=null]  — 内容（文本）
 * @param {object} [p.metadata={}]
 * @returns {FactoryArtifact}
 */
export function createFactoryArtifact({
  id,
  kind,
  name,
  factoryId,
  productId = null,
  version = 1,
  dependencies = [],
  parentId = null,
  path = null,
  content = null,
  metadata = {},
}) {
  if (!kind || !FACTORY_ARTIFACT_KIND[kind.toUpperCase()]) {
    throw new TypeError(`Invalid FactoryArtifact kind: ${kind}`);
  }
  if (!name) throw new TypeError("FactoryArtifact.name is required");
  if (!factoryId) throw new TypeError("FactoryArtifact.factoryId is required");

  return {
    id: id || `fa-${++_faSeq}`,
    kind,
    name,
    factoryId,
    productId,
    version,
    dependencies: [...dependencies],
    parentId,
    path,
    content,
    metadata: { ...metadata },
    createdAt: new Date().toISOString(),
    checksum: null,  // set by artifact graph on registration
  };
}

// ═══════════════════════════════════════════════════════
// Part B-4：FactoryMetric
// ═══════════════════════════════════════════════════════

/**
 * FactoryMetric — Factory 的统一度量接口。
 *
 * 每个 Factory 可产出多个 Metric。
 * Metric 用于跨 Factory 比较和报告聚合。
 *
 * @typedef {object} FactoryMetric
 */

export const METRIC_KIND = Object.freeze({
  DURATION:    "duration",     // 耗时
  COUNT:       "count",        // 计数
  RATIO:       "ratio",        // 比率
  SCORE:       "score",        // 评分
  SIZE:        "size",         // 大小
  MONEY:       "money",        // 金额
  PERCENTAGE:  "percentage",   // 百分比
  OTHER:       "other",
});

let _fmSeq = 0;

/**
 * @param {object} p
 * @param {string} [p.id]
 * @param {string} p.factoryId
 * @param {string} p.name
 * @param {number} p.value
 * @param {string} p.kind          — METRIC_KIND
 * @param {string} [p.unit=""]
 * @param {number|null} [p.target=null]   — 目标值
 * @param {number|null} [p.threshold=null] — 阈值（超过告警）
 * @param {string} [p.trend="stable"]  — "up" | "down" | "stable"
 * @param {object} [p.tags={}]
 * @param {object} [p.metadata={}]
 * @returns {FactoryMetric}
 */
export function createFactoryMetric({
  id,
  factoryId,
  name,
  value,
  kind = "other",
  unit = "",
  target = null,
  threshold = null,
  trend = "stable",
  tags = {},
  metadata = {},
}) {
  if (!factoryId) throw new TypeError("FactoryMetric.factoryId is required");
  if (!name) throw new TypeError("FactoryMetric.name is required");
  if (typeof value !== "number") throw new TypeError("FactoryMetric.value must be a number");

  return {
    id: id || `fm-${++_fmSeq}`,
    factoryId,
    name,
    value,
    kind,
    unit,
    target,
    threshold,
    trend,
    tags: { ...tags },
    metadata: { ...metadata },
    timestamp: new Date().toISOString(),
  };
}

// ═══════════════════════════════════════════════════════
// Part B-5：FactoryReport
// ═══════════════════════════════════════════════════════

/**
 * FactoryReport — Factory 的统一报告接口。
 *
 * 用于：
 *   - 单 Factory 执行报告
 *   - 跨 Factory 聚合报告
 *   - 项目/产品/发布/业务报告
 *
 * @typedef {object} FactoryReport
 */

export const REPORT_TYPE = Object.freeze({
  FACTORY:  "factory",   // 单 Factory 报告
  PROJECT:  "project",   // 项目报告
  PRODUCT:  "product",   // 产品报告
  RELEASE:  "release",   // 发布报告
  BUSINESS: "business",  // 业务报告
});

let _frSeq = 0;

/**
 * @param {object} p
 * @param {string} [p.id]
 * @param {"factory"|"project"|"product"|"release"|"business"} p.type
 * @param {string} p.title
 * @param {string|null} [p.factoryId=null]
 * @param {string|null} [p.productId=null]
 * @param {string} [p.period=""]          — 报告周期
 * @param {object[]} [p.metrics=[]]
 * @param {object[]} [p.artifacts=[]]
 * @param {object[]} [p.risks=[]]
 * @param {object[]} [p.decisions=[]]
 * @param {string} [p.summary=""]
 * @param {string[]} [p.recommendations=[]]
 * @param {object} [p.metadata={}]
 * @returns {FactoryReport}
 */
export function createFactoryReport({
  id,
  type,
  title,
  factoryId = null,
  productId = null,
  period = "",
  metrics = [],
  artifacts = [],
  risks = [],
  decisions = [],
  summary = "",
  recommendations = [],
  metadata = {},
}) {
  if (!REPORT_TYPE[type.toUpperCase()]) throw new TypeError(`Invalid report type: ${type}`);
  if (!title) throw new TypeError("FactoryReport.title is required");

  return {
    id: id || `fr-${++_frSeq}`,
    type,
    title,
    factoryId,
    productId,
    period,
    metrics: [...metrics],
    artifacts: [...artifacts],
    risks: [...risks],
    decisions: [...decisions],
    summary,
    recommendations: [...recommendations],
    metadata: { ...metadata },
    createdAt: new Date().toISOString(),
  };
}

// ═══════════════════════════════════════════════════════
// Part B-6：FactoryDependency
// ═══════════════════════════════════════════════════════

/**
 * FactoryDependency — Factory 之间的依赖关系定义。
 *
 * 用于 Workflow Engine 编排。
 *
 * 依赖类型：
 *   - hard   强制依赖，上游失败则下游阻断
 *   - soft   软依赖，上游结果影响但不阻断
 *   - data   数据依赖，上游产物作为下游输入
 *   - trigger 触发依赖，上游完成触发下游启动
 *
 * @typedef {object} FactoryDependency
 */

export const DEPENDENCY_KIND = Object.freeze({
  HARD:    "hard",
  SOFT:    "soft",
  DATA:    "data",
  TRIGGER: "trigger",
});

let _fdSeq = 0;

/**
 * @param {object} p
 * @param {string} [p.id]
 * @param {string} p.from         — 上游 Factory ID
 * @param {string} p.to           — 下游 Factory ID
 * @param {"hard"|"soft"|"data"|"trigger"} [p.kind="hard"]
 * @param {boolean} [p.required=true]
 * @param {string} [p.description=""]
 * @param {string[]} [p.artifactKinds=[]] — 传递的 artifact 类型
 * @param {object} [p.metadata={}]
 * @returns {FactoryDependency}
 */
export function createFactoryDependency({
  id,
  from,
  to,
  kind = "hard",
  required = true,
  description = "",
  artifactKinds = [],
  metadata = {},
}) {
  if (!from) throw new TypeError("FactoryDependency.from is required");
  if (!to) throw new TypeError("FactoryDependency.to is required");
  if (!DEPENDENCY_KIND[kind.toUpperCase()]) throw new TypeError(`Invalid dependency kind: ${kind}`);

  return {
    id: id || `fd-${++_fdSeq}`,
    from,
    to,
    kind,
    required,
    description,
    artifactKinds: [...artifactKinds],
    metadata: { ...metadata },
    createdAt: new Date().toISOString(),
  };
}
