/**
 * 拉取 OpenAPI 文档并修复 SpringDoc 生成的 oneOf schema 问题
 * 解决 orval 报错: "oneOf must match exactly one schema in oneOf"
 */
import { writeFileSync } from 'fs';
import { join, dirname } from 'path';
import { fileURLToPath } from 'url';

const __dirname = dirname(fileURLToPath(import.meta.url));
const TARGET = 'http://localhost:8480/v3/api-docs';
const OUTPUT = join(__dirname, '../openapi.json');

async function fetchAndFix() {
  const res = await fetch(TARGET);
  if (!res.ok) throw new Error(`Failed to fetch: ${res.status} ${res.statusText}. 请确保后端已启动 (mvn spring-boot:run)`);
  let spec = await res.json();

  const paths = spec.paths || {};
  for (const path of Object.keys(paths)) {
    let newKey = path.replace(/\/v1\/v1\//g, '/v1/');
    if (newKey === path) newKey = path.replace(/^\/api\/(?!v1\/)/, '/api/v1/');
    if (newKey !== path) {
      paths[newKey] = paths[path];
      delete paths[path];
    }
  }

  fixOneOfInPaths(paths);
  inlineResultObjectArrayRef(paths);
  // 移除非法 schema 名 ResultObject[]（含 [] 不符合 OpenAPI 规范）
  if (spec.components?.schemas) {
    delete spec.components.schemas['ResultObject[]'];
  }
  // 修复成长记录 images 字段：统一为 array of string（避免 SpringDoc 误生成为 string）
  fixGrowthRecordImagesSchema(spec.components?.schemas);

  writeFileSync(OUTPUT, JSON.stringify(spec, null, 2));
  console.log('OpenAPI spec written to:', OUTPUT);
}

function fixOneOfInPaths(paths) {
  for (const pathObj of Object.values(paths)) {
    for (const op of Object.values(pathObj)) {
      const res200 = op?.responses?.['200'];
      if (!res200?.content) continue;
      for (const media of Object.values(res200.content)) {
        if (media?.schema) fixSchema(media.schema);
      }
    }
  }
}

function fixSchema(schema) {
  if (!schema || typeof schema !== 'object') return;
  if (schema.oneOf && Array.isArray(schema.oneOf)) {
    schema.type = 'array';
    schema.items = { type: 'object', additionalProperties: true };
    delete schema.oneOf;
  }
  if (schema.properties) {
    for (const p of Object.values(schema.properties)) fixSchema(p);
  }
  if (schema.items) fixSchema(schema.items);
}

/** 将 GrowthRecordCreateRequest/GrowthRecordUpdateRequest 的 images 统一为 array of string */
function fixGrowthRecordImagesSchema(schemas) {
  if (!schemas) return;
  const arrayOfString = {
    type: 'array',
    items: { type: 'string', description: '图片 URL' },
    description: '图片 URL 列表',
  };
  for (const name of ['GrowthRecordCreateRequest', 'GrowthRecordUpdateRequest']) {
    const s = schemas[name];
    if (s?.properties?.images?.type === 'string') {
      schemas[name].properties.images = arrayOfString;
    }
  }
}

function inlineResultObjectArrayRef(paths) {
  const inlineSchema = {
    type: 'object',
    properties: {
      code: { type: 'integer', format: 'int32' },
      message: { type: 'string' },
      data: { type: 'array', items: { type: 'object', additionalProperties: true } },
    },
  };
  for (const pathObj of Object.values(paths)) {
    for (const op of Object.values(pathObj)) {
      const res200 = op?.responses?.['200'];
      if (!res200?.content) continue;
      for (const media of Object.values(res200.content)) {
        if (media?.schema?.['$ref']?.endsWith('ResultObject[]')) {
          media.schema = { ...inlineSchema };
        }
      }
    }
  }
}

fetchAndFix().catch((e) => {
  console.error(e);
  process.exit(1);
});
