import 'reflect-metadata';

import { InvalidDecoratorMetadataError } from '../../errors/decorator.errors';
import { frontMcpPluginMetadataSchema, type PluginMetadata } from '../metadata';
import { FrontMcpPluginTokens } from '../tokens';

/**
 * Decorator that marks a class as a McpPlugin and provides metadata
 */
function FrontMcpPlugin(providedMetadata: PluginMetadata): ClassDecorator {
  return (target: Function) => {
    const { error, data: metadata } = frontMcpPluginMetadataSchema.safeParse(providedMetadata);
    if (error) {
      const formatted = error.format();
      if (formatted.providers) {
        throw new InvalidDecoratorMetadataError('Plugin', 'providers', JSON.stringify(formatted.providers, null, 2));
      }
      if (formatted.adapters) {
        throw new InvalidDecoratorMetadataError('Plugin', 'adapters', JSON.stringify(formatted.adapters, null, 2));
      }
      if (formatted.tools) {
        throw new InvalidDecoratorMetadataError('Plugin', 'tools', JSON.stringify(formatted.tools, null, 2));
      }
      if (formatted.resources) {
        throw new InvalidDecoratorMetadataError('Plugin', 'resources', JSON.stringify(formatted.resources, null, 2));
      }
      if (formatted.prompts) {
        throw new InvalidDecoratorMetadataError('Plugin', 'prompts', JSON.stringify(formatted.prompts, null, 2));
      }
      throw error;
    }

    Reflect.defineMetadata(FrontMcpPluginTokens.type, true, target);
    for (const property in metadata) {
      Reflect.defineMetadata(FrontMcpPluginTokens[property] ?? property, metadata[property], target);
    }
  };
}

export { FrontMcpPlugin, FrontMcpPlugin as Plugin };
