import {get} from '@/shared/services/http';
// 注意：后端 /api/v1/models 的 category 查询参数实际不可用（传参返回空列表），
// 因此客户端采用"全量拉取 + 按 category_name 字段分组"的策略。
// 后端分类 slug 格式为 img2img / txt2img 等，前端通过 CATEGORY_SLUG_MAP 映射。
// ---------- 路由常量 ----------

const ModelsUrlObj = {
    modelList: '/api/v1/models',
    getModelInfo: '/api/v1/models/{model_id}',
    estimateCost: '/api/v1/models/{model_id}/estimate'
} as const;

// ---------- 类型 ----------

/** 模型类别常量数组（单一数据源，类型由此推导） */
export const MODEL_CATEGORIES = [
    'image_to_image',
    'text_to_image',
    'image_to_video',
    'text_to_audio',
] as const;

export type ModelCategoryStringEnum = typeof MODEL_CATEGORIES[number];

/**
 * 模型参数 Schema 项
 *
 * 后端 /api/v1/models 返回的 param_schema 为对象数组，
 * 每项描述一个模型入参的元信息（标识、字段映射、规格约束、UI 配置）。
 */
export interface ParamSchemaItem {
    id: string;
    /** 映射到提交参数中的字段名 */
    map_to: string;
    /** 规格约束（类型、范围、默认值等） */
    spec: Record<string, unknown>;
    /** UI 控件配置 */
    ui: Record<string, unknown>;
}

/** 模型类别中文映射 */
export const MODEL_CATEGORY_LABELS: Record<ModelCategoryStringEnum, string> = {
    image_to_image: '图生图',
    text_to_image: '文生图',
    image_to_video: '图生视频',
    text_to_audio: '文生音频',
};

/**
 * 前端 ModelCategory → 后端分类 slug 映射
 *
 * 后端分类 API 使用简写 slug（如 img2img），而非前端的长标识符。
 * 查询模型列表时需将前端类别转为后端 slug 作为 category 参数。
 */
export const CATEGORY_SLUG_MAP: Record<ModelCategoryStringEnum, string> = {
    image_to_image: 'img2img',
    text_to_image: 'txt2img',
    image_to_video: 'img2video',
    text_to_audio: 'txt2audio',
};

/** 后端 slug → 前端 ModelCategory 反向映射（由 CATEGORY_SLUG_MAP 自动推导） */
const SLUG_TO_CATEGORY: Record<string, ModelCategoryStringEnum> = Object.fromEntries(
    Object.entries(CATEGORY_SLUG_MAP).map(([cat, slug]) => [slug, cat as ModelCategoryStringEnum]),
) as Record<string, ModelCategoryStringEnum>;

/**
 * 根据任意 category_name 值解析出最佳中文标签
 *
 * 解析优先级：
 *   1. 匹配 MODEL_CATEGORY_LABELS（前端 ModelCategory 字面量）
 *   2. 匹配 SLUG_TO_CATEGORY 反向映射（后端 slug → 中英文标签）
 *   3. 兜底返回原始字符串
 */
export function resolveCategoryLabel(categoryName: string): string {
    // 优先按 ModelCategory 字面量查找
    if (categoryName in MODEL_CATEGORY_LABELS) {
        return MODEL_CATEGORY_LABELS[categoryName as ModelCategoryStringEnum];
    }
    // 按后端 slug 反向查找
    const cat = SLUG_TO_CATEGORY[categoryName];
    if (cat) {
        return MODEL_CATEGORY_LABELS[cat];
    }
    // 兜底返回原始值
    return categoryName;
}

/**
 * 将前端 ModelCategory 转为后端 API 用的分类 slug
 */
export function toCategorySlug(category: ModelCategoryStringEnum): string {
    return CATEGORY_SLUG_MAP[category];
}

/**
 * 查询可用模型的请求参数
 */
export interface ModelsListReqeustParams {
    provider_name?: string;
    category?: ModelCategoryStringEnum;
    page: number;
    page_size: number;
}

/**
 * 查询可用模型的响应体
 */
export interface ModelsListResponseBody {
    id: string;
    name: string;
    provider_name: string;
    model_type: ModelCategoryStringEnum;
    category_name: ModelCategoryStringEnum | null;
    status: string;
    priority: number;
    response_mode: string;
    pricing_config: Record<string, unknown> | null;
    param_schema: ParamSchemaItem[];
    quota_config: Record<string, unknown> | null;
    ui_config: Record<string, unknown>;
    meta_config: Record<string, unknown>;
    constraints_config: Record<string, unknown>;
    expires_at: string;
    created_at: string;
    updated_at: string;
}

/**
 * 模型信息请求参数
 */
export interface ModelInfoRequestParams {
    model_id: string;
}

/** 模型详情响应体（与列表项结构一致） */
export type ModelInfoResponseBody = ModelsListResponseBody;

// ---------- API ----------


export class ModelAPI {
    /**
     * 获取可用模型列表
     * GET /api/v1/models
     */
    static fetchModels(params: ModelsListReqeustParams, signal?: AbortSignal): Promise<ModelsListResponseBody[]> {
        return get<ModelsListResponseBody[]>(ModelsUrlObj.modelList, params as unknown as Record<string, unknown>, { signal });
    }

    /**
     * 获取单个模型详情
     * GET /api/v1/models/:id
     */
    static fetchModelInfo(modelId: string): Promise<ModelInfoResponseBody> {
        const url = ModelsUrlObj.getModelInfo.replace('{model_id}', modelId);
        return get<ModelInfoResponseBody>(url);
    }
}