import { z } from 'zod';

/**
 * Valid tool categories for TPMJS registry
 */
export const TPMJS_CATEGORIES = [
  'web-scraping',
  'data-processing',
  'file-operations',
  'communication',
  'database',
  'api-integration',
  'image-processing',
  'text-analysis',
  'automation',
  'ai-ml',
  'security',
  'monitoring',
] as const;

export type TpmjsCategory = (typeof TPMJS_CATEGORIES)[number];

/**
 * Tool parameter schema
 */
export const TpmjsParameterSchema = z.object({
  name: z.string().min(1),
  type: z.string().min(1),
  description: z.string().min(1),
  required: z.boolean().default(false),
  default: z.unknown().optional(),
});

export type TpmjsParameter = z.infer<typeof TpmjsParameterSchema>;

/**
 * Return value schema
 */
export const TpmjsReturnsSchema = z.object({
  type: z.string().min(1),
  description: z.string().min(1),
});

export type TpmjsReturns = z.infer<typeof TpmjsReturnsSchema>;

/**
 * Environment variable schema
 */
export const TpmjsEnvSchema = z.object({
  name: z.string().min(1),
  description: z.string().min(1),
  required: z.boolean().default(true),
  default: z.string().optional(),
});

export type TpmjsEnv = z.infer<typeof TpmjsEnvSchema>;

/**
 * AI Agent guidance schema
 */
export const TpmjsAiAgentSchema = z.object({
  useCase: z.string().min(10),
  limitations: z.string().optional(),
  examples: z.array(z.string()).optional(),
});

export type TpmjsAiAgent = z.infer<typeof TpmjsAiAgentSchema>;

/**
 * Individual tool definition within a multi-tool package
 */
export const TpmjsToolDefinitionSchema = z.object({
  exportName: z.string().min(1, 'Export name is required'),
  description: z.string().min(20, 'Description must be at least 20 characters').max(500),
  parameters: z.array(TpmjsParameterSchema).optional(),
  returns: TpmjsReturnsSchema.optional(),
  aiAgent: TpmjsAiAgentSchema.optional(),
});

export type TpmjsToolDefinition = z.infer<typeof TpmjsToolDefinitionSchema>;

/**
 * Multi-tool format - NEW SCHEMA
 * Package-level metadata with array of tools
 */
export const TpmjsMultiToolSchema = z.object({
  category: z.enum(TPMJS_CATEGORIES, {
    message: `Category must be one of: ${TPMJS_CATEGORIES.join(', ')}`,
  }),
  tools: z.array(TpmjsToolDefinitionSchema).min(1, 'At least one tool is required'),
  env: z.array(TpmjsEnvSchema).optional(),
  frameworks: z
    .array(z.enum(['vercel-ai', 'langchain', 'llamaindex', 'haystack', 'semantic-kernel']))
    .optional(),
});

export type TpmjsMultiTool = z.infer<typeof TpmjsMultiToolSchema>;

/**
 * Legacy minimal tier schema - DEPRECATED
 * Kept for backward compatibility with auto-migration
 */
export const TpmjsLegacyMinimalSchema = z.object({
  category: z.enum(TPMJS_CATEGORIES, {
    message: `Category must be one of: ${TPMJS_CATEGORIES.join(', ')}`,
  }),
  description: z.string().min(20, 'Description must be at least 20 characters').max(500),
});

export type TpmjsLegacyMinimal = z.infer<typeof TpmjsLegacyMinimalSchema>;

/**
 * Legacy rich tier schema - DEPRECATED
 * Kept for backward compatibility with auto-migration
 */
export const TpmjsLegacyRichSchema = TpmjsLegacyMinimalSchema.extend({
  parameters: z.array(TpmjsParameterSchema).optional(),
  returns: TpmjsReturnsSchema.optional(),
  env: z.array(TpmjsEnvSchema).optional(),
  frameworks: z
    .array(z.enum(['vercel-ai', 'langchain', 'llamaindex', 'haystack', 'semantic-kernel']))
    .optional(),
  aiAgent: TpmjsAiAgentSchema.optional(),
});

export type TpmjsLegacyRich = z.infer<typeof TpmjsLegacyRichSchema>;

/**
 * Union type for legacy formats
 */
export type TpmjsLegacy = TpmjsLegacyMinimal | TpmjsLegacyRich;

/**
 * Union type for all formats (new multi-tool + legacy)
 */
export type TpmjsField = TpmjsMultiTool | TpmjsLegacy;

// Backward compatibility aliases
export type TpmjsMinimal = TpmjsLegacyMinimal;
export type TpmjsRich = TpmjsLegacyRich;
export const TpmjsMinimalSchema = TpmjsLegacyMinimalSchema;
export const TpmjsRichSchema = TpmjsLegacyRichSchema;

/**
 * Extended validation result type for multi-tool support
 */
export interface ValidationResult {
  valid: boolean;
  tier: 'minimal' | 'rich' | null;
  data?: TpmjsField;
  errors?: z.ZodError;
  // New fields for multi-tool support
  packageData?: {
    category: TpmjsCategory;
    env?: TpmjsEnv[];
    frameworks?: string[];
  };
  tools?: TpmjsToolDefinition[];
  wasLegacyFormat?: boolean;
}

/**
 * Validates a tpmjs field and determines its tier
 * Supports both new multi-tool format and legacy single-tool format with auto-migration
 */
export function validateTpmjsField(tpmjs: unknown): ValidationResult {
  // Try new multi-tool format first
  const multiResult = TpmjsMultiToolSchema.safeParse(tpmjs);
  if (multiResult.success) {
    const data = multiResult.data;

    // Determine tier based on tool richness
    const hasRichFields =
      data.tools.some((tool) => tool.parameters || tool.returns || tool.aiAgent) ||
      data.env ||
      data.frameworks;

    return {
      valid: true,
      tier: hasRichFields ? 'rich' : 'minimal',
      data: data,
      packageData: {
        category: data.category,
        env: data.env,
        frameworks: data.frameworks,
      },
      tools: data.tools,
      wasLegacyFormat: false,
    };
  }

  // Try legacy rich tier format with auto-migration
  const richResult = TpmjsLegacyRichSchema.safeParse(tpmjs);
  if (richResult.success) {
    const legacyData = richResult.data;

    // Auto-migrate to multi-tool format
    const tool: TpmjsToolDefinition = {
      exportName: 'default',
      description: legacyData.description,
      parameters: legacyData.parameters,
      returns: legacyData.returns,
      aiAgent: legacyData.aiAgent,
    };

    const hasRichFields =
      legacyData.parameters ||
      legacyData.returns ||
      legacyData.env ||
      legacyData.frameworks ||
      legacyData.aiAgent;

    return {
      valid: true,
      tier: hasRichFields ? 'rich' : 'minimal',
      data: legacyData,
      packageData: {
        category: legacyData.category,
        env: legacyData.env,
        frameworks: legacyData.frameworks,
      },
      tools: [tool],
      wasLegacyFormat: true,
    };
  }

  // Try legacy minimal tier format with auto-migration
  const minimalResult = TpmjsLegacyMinimalSchema.safeParse(tpmjs);
  if (minimalResult.success) {
    // Auto-migrate to multi-tool format
    const tool: TpmjsToolDefinition = {
      exportName: 'default',
      description: minimalResult.data.description,
    };

    return {
      valid: true,
      tier: 'minimal',
      data: minimalResult.data,
      packageData: {
        category: minimalResult.data.category,
      },
      tools: [tool],
      wasLegacyFormat: true,
    };
  }

  // Invalid - return error from multi-tool schema (most informative)
  return {
    valid: false,
    tier: null,
    errors: multiResult.error,
  };
}

/**
 * Type guard for minimal tier
 */
export function isTpmjsMinimal(tpmjs: unknown): tpmjs is TpmjsMinimal {
  return TpmjsMinimalSchema.safeParse(tpmjs).success;
}

/**
 * Type guard for rich tier
 */
export function isTpmjsRich(tpmjs: unknown): tpmjs is TpmjsRich {
  return TpmjsRichSchema.safeParse(tpmjs).success;
}
