// ArkTS 类型系统测试 - 探索 create() 方法的类型安全方案

/**
 * 方案 1: 对象字面量类型(推荐)⭐⭐⭐⭐⭐
 * 优点:不需要额外接口,类型安全
 * 缺点:字段多时参数类型较长(但生成代码可接受)
 */
export class UserInfo1 extends Message {
  uid: bigint = 0n
  name: string = ''
  realm: string = ''

  static create(init?: {
    uid?: bigint
    name?: string
    realm?: string
  }): UserInfo1 {
    const msg = new UserInfo1()
    if (init) {
      if (init.uid !== undefined) msg.uid = init.uid
      if (init.name !== undefined) msg.name = init.name
      if (init.realm !== undefined) msg.realm = init.realm
    }
    return msg
  }
}

/**
 * 方案 2: Record<string, unknown>(次选)⭐⭐⭐
 * 优点:简洁
 * 缺点:失去类型安全
 */
export class UserInfo2 extends Message {
  uid: bigint = 0n
  name: string = ''

  static create(init?: Record<string, unknown>): UserInfo2 {
    const msg = new UserInfo2()
    if (init) {
      if ('uid' in init && init.uid !== undefined) {
        msg.uid = init.uid as bigint
      }
      if ('name' in init && init.name !== undefined) {
        msg.name = init.name as string
      }
    }
    return msg
  }
}

/**
 * 方案 3: any(不推荐)⭐
 * 优点:简单
 * 缺点:完全失去类型安全,ArkTS 可能也不支持 any
 */
export class UserInfo3 extends Message {
  uid: bigint = 0n
  name: string = ''

  static create(init?: any): UserInfo3 {
    const msg = new UserInfo3()
    if (init) {
      if (init.uid !== undefined) msg.uid = init.uid
      if (init.name !== undefined) msg.name = init.name
    }
    return msg
  }
}

/**
 * 方案 4: Object(不推荐)⭐
 * 优点:ArkTS 支持
 * 缺点:完全失去类型安全
 */
export class UserInfo4 extends Message {
  uid: bigint = 0n
  name: string = ''

  static create(init?: Object): UserInfo4 {
    const msg = new UserInfo4()
    if (init) {
      // 需要类型断言,很丑
      const obj = init as any
      if ('uid' in obj) msg.uid = obj.uid
      if ('name' in obj) msg.name = obj.name
    }
    return msg
  }
}

/**
 * 方案 5: 类型别名(与 *Init 接口本质相同)⭐⭐⭐⭐
 * 优点:类型安全,可以用 type 代替 interface
 * 缺点:还是需要定义额外的类型
 */
type UserInfo5Init = {
  uid?: bigint
  name?: string
  realm?: string
}

export class UserInfo5 extends Message {
  uid: bigint = 0n
  name: string = ''
  realm: string = ''

  static create(init?: UserInfo5Init): UserInfo5 {
    const msg = new UserInfo5()
    if (init) {
      if (init.uid !== undefined) msg.uid = init.uid
      if (init.name !== undefined) msg.name = init.name
      if (init.realm !== undefined) msg.realm = init.realm
    }
    return msg
  }
}

/**
 * 使用示例对比
 */
function testUsage() {
  // 方案 1: 对象字面量 - 类型安全 ✅
  const user1 = UserInfo1.create({
    uid: 123n,
    name: 'Alice'
    // realm 可选
  })

  // 编译错误:类型不匹配 ✅
  // const user1bad = UserInfo1.create({
  //   uid: 'wrong type'  // ❌ Error
  // })

  // 方案 2: Record - 失去类型安全 ⚠️
  const user2 = UserInfo2.create({
    uid: 123n,
    name: 'Alice',
    nonExistent: 'allowed'  // ⚠️ 不会报错
  })

  // 方案 5: 类型别名 - 类型安全 ✅
  const user5 = UserInfo5.create({
    uid: 123n,
    name: 'Alice'
  })
}

// =============================================================================
// 📊 方案对比分析
// =============================================================================

/**
 * 方案对比表
 *
 * | 方案 | 类型安全 | 需要额外定义 | ArkTS兼容 | IntelliSense | 推荐度 |
 * |-----|---------|-------------|-----------|-------------|--------|
 * | 1. 对象字面量 | ✅ 完全 | ❌ 不需要 | ✅ 支持 | ✅ 完美 | ⭐⭐⭐⭐⭐ |
 * | 2. Record | ❌ 无 | ❌ 不需要 | ✅ 支持 | ❌ 无 | ⭐⭐ |
 * | 3. any | ❌ 无 | ❌ 不需要 | ⚠️ 不推荐 | ❌ 无 | ⭐ |
 * | 4. Object | ❌ 无 | ❌ 不需要 | ✅ 支持 | ❌ 无 | ⭐ |
 * | 5. 类型别名 | ✅ 完全 | ✅ 需要 | ✅ 支持 | ✅ 完美 | ⭐⭐⭐⭐ |
 */

// =============================================================================
// 🎯 最终推荐:方案 1 - 对象字面量类型
// =============================================================================

/**
 * 推荐理由:
 *
 * 1. ✅ 完全类型安全
 *    - 字段名称检查
 *    - 字段类型检查
 *    - 编译时错误提示
 *
 * 2. ✅ 不需要额外的类型定义
 *    - 不需要生成 *Init 接口
 *    - 不需要生成 type 别名
 *    - 代码更简洁
 *
 * 3. ✅ ArkTS 完全支持
 *    - 对象字面量类型是 TypeScript/ArkTS 的基础特性
 *    - 不使用任何高级类型特性
 *    - 不需要 Partial<T> 等工具类型
 *
 * 4. ✅ 优秀的开发体验
 *    - IDE 自动补全
 *    - 类型提示
 *    - 重构支持
 *
 * 5. ✅ 生成代码可接受
 *    - 虽然参数类型较长
 *    - 但是生成代码,不影响可读性
 *    - 用户调用时看到的是类型提示,不是源代码
 *
 * 唯一缺点:
 * - ⚠️ 字段多时参数类型会很长
 *   但这不是问题,因为:
 *   - 这是生成代码,不是手写代码
 *   - 用户看到的是 IDE 提示,不是源码
 *   - 类型信息完整,反而更好
 */

// =============================================================================
// 💻 生成器实现示例
// =============================================================================

/**
 * 在 arkpb-gen.js 中的实现:
 *
 * ```javascript
 * // 生成 create() 方法
 * function generateCreateMethod(className, fields) {
 *   // 1. 生成参数类型(对象字面量)
 *   const paramType = fields.length > 0
 *     ? `{\n    ${fields.map(f => `${f.name}?: ${fieldType(f)}`).join('\n    ')}\n  }`
 *     : '{}'
 *
 *   // 2. 生成方法签名
 *   lines.push(`  static create(init?: ${paramType}): ${className} {`)
 *   lines.push(`    const msg = new ${className}()`)
 *
 *   // 3. 生成字段赋值
 *   lines.push(`    if (init) {`)
 *   for (const f of fields) {
 *     lines.push(`      if (init.${f.name} !== undefined) msg.${f.name} = init.${f.name}`)
 *   }
 *   lines.push(`    }`)
 *   lines.push(`    return msg`)
 *   lines.push(`  }`)
 * }
 * ```
 */

// =============================================================================
// ✅ 结论
// =============================================================================

/**
 * 最终决定:使用方案 1 - 对象字面量类型
 *
 * 理由:
 * 1. 符合用户要求:不需要生成额外的 *Init 接口
 * 2. 类型安全:完全保留类型检查
 * 3. ArkTS 兼容:使用基础语法,无兼容性问题
 * 4. 开发体验好:完整的 IDE 支持
 * 5. 实现简单:修改生成器即可
 *
 * 下一步:
 * 1. 修改 arkpb-gen.js 中的 create() 方法生成逻辑
 * 2. 使用对象字面量类型替代 Partial<T>
 * 3. 重新生成代码
 * 4. 测试编译
 */

export const RECOMMENDATION = {
  solution: 'Object Literal Types',
  rating: 5,
  needsExtraInterface: false,
  typeSafe: true,
  arktsCompatible: true,
  reason: '完全类型安全,不需要额外接口,ArkTS完全支持'
}