import { Type, Static } from '@sinclair/typebox';
import { type AnyAgentTool } from '../common.js';
import { registerSchema } from '../catalog.js';
import type {
  ImageGenerationProvider,
  ImageProviderCredentials,
} from '../../image_providers/types.js';
import { ImageGenerationError } from '../../image_providers/types.js';
import type { ImageStorageService } from '../../service/image_storage.js';
import { clampDimension, persistImages, formatImageToolResult } from './image_common.js';

const Params = Type.Object({
  prompt: Type.String({ description: '对参考图的修改描述' }),
  referenceImage: Type.String({ description: '参考图片 URL（从用户上传附件获取）' }),
  strength: Type.Optional(Type.Number({
    description: '参考图影响强度 0-1，越大越接近原图', minimum: 0, maximum: 1,
  })),
  aspectRatio: Type.Optional(Type.String({
    description: '宽高比（推荐用此参数，工具会根据模型自动选择合适尺寸）。可选: 1:1, 16:9, 4:3, 3:2, 2:3, 3:4, 9:16, 21:9',
  })),
  width: Type.Optional(Type.Integer({ description: '精确宽度（像素），仅在需要特殊尺寸时使用，否则优先用 aspectRatio' })),
  height: Type.Optional(Type.Integer({ description: '精确高度（像素），仅在需要特殊尺寸时使用，否则优先用 aspectRatio' })),
  n: Type.Optional(Type.Integer({ description: '生成数量，默认 1，最大 9', minimum: 1, maximum: 9 })),
  watermark: Type.Optional(Type.Boolean({ description: '是否添加水印' })),
  seed: Type.Optional(Type.Integer({ description: '随机种子' })),
  extra: Type.Optional(Type.Record(Type.String(), Type.Unknown(), {
    description: 'Provider 特有参数',
  })),
});

export function createImageToImageTool(
  creds: ImageProviderCredentials,
  provider: ImageGenerationProvider,
  storage: ImageStorageService,
): AnyAgentTool {
  const defaults = creds.extra?.imageDefaults ?? {};
  const constraints = creds.extra?.imageConstraints ?? {};

  return {
    name: 'image_to_image',
    label: '图生图',
    description: creds.promptHint
      ? `基于参考图片生成新图片。\n${creds.promptHint}`
      : '基于参考图片生成新图片，支持风格迁移、内容编辑等。传入参考图URL和修改描述。',
    parameters: Params,
    async execute(_id: string, params: Static<typeof Params>) {
      const merged = {
        prompt: params.prompt,
        referenceImage: params.referenceImage,
        strength: params.strength,
        n: Math.min(params.n ?? defaults.n ?? 1, constraints.maxN ?? 9),
        aspectRatio: params.aspectRatio ?? defaults.aspectRatio,
        width: clampDimension(params.width ?? defaults.width, constraints.maxWidth ?? 2048),
        height: clampDimension(params.height ?? defaults.height, constraints.maxHeight ?? 2048),
        watermark: params.watermark ?? defaults.watermark ?? false,
        seed: params.seed,
        responseFormat: (defaults.responseFormat ?? 'url') as 'url' | 'base64',
        extra: params.extra,
      };

      try {
        let result = await provider.imageToImage(merged, creds);
        result = await persistImages(result, storage);
        return formatImageToolResult(result);
      } catch (err) {
        if (err instanceof ImageGenerationError) {
          const prefix = err.retryable ? '[可重试] ' : '';
          return { type: 'text' as const, text: `${prefix}图片生成失败: ${err.message}` };
        }
        return { type: 'text' as const, text: `图片生成失败: ${err instanceof Error ? err.message : String(err)}` };
      }
    },
  };
}

registerSchema({
  name: 'image_to_image',
  toolset: 'aigc',
  description: '基于参考图片生成新图片，支持风格迁移、内容编辑等。传入参考图URL和修改描述。',
  capability: 'image_aigc',
  visibility: 'tool',
  isCore: false,
  canDisable: true,
  supportsPromptHint: true,
  requiresModel: true,
});
