/**
 * Cross-Platform Code Translation Engine
 * Core competitive differentiator for AeThex Studio
 */

import { PlatformId, getPlatform } from './platforms';
import { toast } from 'sonner';
import { trackEvent, trackError } from './analytics';

export interface TranslationRequest {
  sourceCode: string;
  sourcePlatform: PlatformId;
  targetPlatform: PlatformId;
  context?: string;
}

export interface TranslationResult {
  success: boolean;
  translatedCode?: string;
  explanation?: string;
  warnings?: string[];
  error?: string;
}

/**
 * Platform-specific translation prompts
 */
const getTranslationPrompt = (
  sourceCode: string,
  sourcePlatform: PlatformId,
  targetPlatform: PlatformId,
  context?: string
): string => {
  const sourcePlat = getPlatform(sourcePlatform);
  const targetPlat = getPlatform(targetPlatform);

  return `You are an expert game developer specializing in cross-platform game development.

**Task**: Translate the following ${sourcePlat.language} code (${sourcePlat.displayName}) to ${targetPlat.language} (${targetPlat.displayName}).

**Source Platform**: ${sourcePlat.displayName}
- Language: ${sourcePlat.language}
- API Documentation: ${sourcePlat.apiDocs}

**Target Platform**: ${targetPlat.displayName}
- Language: ${targetPlat.language}
- API Documentation: ${targetPlat.apiDocs}

**Source Code**:
\`\`\`${sourcePlat.language.toLowerCase()}
${sourceCode}
\`\`\`

${context ? `**Additional Context**: ${context}\n` : ''}

**Instructions**:
1. Translate the code to ${targetPlat.language} while preserving the logic and functionality
2. Use ${targetPlat.displayName}-native APIs and best practices
3. Add comments explaining platform-specific differences
4. Ensure the code follows ${targetPlat.language} conventions and style
5. If certain features don't have direct equivalents, provide the closest alternative and explain

**Output Format**:
Return ONLY the translated code wrapped in triple backticks with the language identifier.
Then provide a brief explanation of key changes and any warnings.

Example:
\`\`\`${targetPlat.fileExtension.replace('.', '')}
// Translated code here
\`\`\`

**Explanation**: [Brief explanation of translation]

**Warnings**: [Any caveats or limitations, if applicable]`;
};

/**
 * Platform-specific translation rules
 */
const platformTranslationRules: Record<string, Record<string, string[]>> = {
  'roblox-to-uefn': [
    'game:GetService() → Use Verse imports',
    'Instance.new() → object{} syntax in Verse',
    'Connect() → Subscribe() in Verse',
    'wait() → Sleep() in Verse',
    'print() → Print() in Verse',
  ],
  'uefn-to-roblox': [
    'Verse imports → game:GetService()',
    'object{} → Instance.new()',
    'Subscribe() → Connect()',
    'Sleep() → wait()',
    'Print() → print()',
  ],
  'roblox-to-spatial': [
    'Lua → TypeScript syntax',
    'game:GetService() → Spatial SDK imports',
    'Instance.new() → new SpatialObject()',
    'Connect() → addEventListener()',
    'wait() → await setTimeout()',
  ],
  'spatial-to-roblox': [
    'TypeScript → Lua syntax',
    'Spatial SDK → game:GetService()',
    'new SpatialObject() → Instance.new()',
    'addEventListener() → Connect()',
    'await setTimeout() → wait()',
  ],
};

/**
 * Mock translation service (for development without API key)
 * Replace with actual Claude API call in production
 */
async function translateWithMockService(
  request: TranslationRequest
): Promise<TranslationResult> {
  const ruleKey = `${request.sourcePlatform}-to-${request.targetPlatform}`;
  const rules = platformTranslationRules[ruleKey] || [];

  return {
    success: true,
    translatedCode: `-- Translated from ${request.sourcePlatform} to ${request.targetPlatform}
-- Translation Rules Applied:
${rules.map(r => `-- ${r}`).join('\n')}

-- Original Code (needs actual translation):
${request.sourceCode}

-- TODO: Replace with actual ${request.targetPlatform} implementation`,
    explanation: `This is a mock translation. The actual translation engine will use Claude API to intelligently convert ${request.sourcePlatform} code to ${request.targetPlatform}.`,
    warnings: [
      'Mock translation active - integrate Claude API for production',
      `Translation rules: ${rules.join(', ')}`,
    ],
  };
}

/**
 * Translate code using Claude API
 * This is the production implementation
 */
async function translateWithClaudeAPI(
  request: TranslationRequest
): Promise<TranslationResult> {
  try {
    // Check if API key is configured
    const apiKey = import.meta.env.VITE_CLAUDE_API_KEY || process.env.NEXT_PUBLIC_CLAUDE_API_KEY;

    if (!apiKey) {
      console.warn('Claude API key not configured, using mock translation');
      return await translateWithMockService(request);
    }

    const prompt = getTranslationPrompt(
      request.sourceCode,
      request.sourcePlatform,
      request.targetPlatform,
      request.context
    );

    // Call Claude API
    const response = await fetch('https://api.anthropic.com/v1/messages', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'x-api-key': apiKey,
        'anthropic-version': '2023-06-01',
      },
      body: JSON.stringify({
        model: 'claude-3-5-sonnet-20241022',
        max_tokens: 4096,
        messages: [
          {
            role: 'user',
            content: prompt,
          },
        ],
      }),
    });

    if (!response.ok) {
      const errorData = await response.json().catch(() => ({}));
      throw new Error(
        `API request failed: ${response.statusText} (${response.status})${
          errorData.error?.message ? ` - ${errorData.error.message}` : ''
        }`
      );
    }

    const data = await response.json();
    const content = data.content?.[0]?.text;

    if (!content) {
      throw new Error('No content in API response');
    }

    // Parse the response to extract code, explanation, and warnings
    const result = parseClaudeResponse(content, request.targetPlatform);
    return result;
  } catch (error) {
    trackError(error as Error, {
      context: 'translation_api',
      sourcePlatform: request.sourcePlatform,
      targetPlatform: request.targetPlatform,
    });

    // Fallback to mock if API fails
    console.warn('Claude API failed, falling back to mock:', error);
    return await translateWithMockService(request);
  }
}

/**
 * Parse Claude API response to extract code, explanation, and warnings
 */
function parseClaudeResponse(
  content: string,
  targetPlatform: PlatformId
): TranslationResult {
  try {
    // Extract code block (supports multiple formats)
    const codeMatch = content.match(/```(?:verse|lua|typescript|ts|javascript|js)?\n([\s\S]*?)```/);

    if (!codeMatch) {
      // If no code block found, treat entire response as code
      return {
        success: true,
        translatedCode: content.trim(),
        explanation: 'Translation completed',
      };
    }

    const translatedCode = codeMatch[1].trim();

    // Extract explanation (multiple formats)
    const explanationMatch =
      content.match(/\*\*Explanation\*\*:\s*(.*?)(?:\n\*\*|$)/s) ||
      content.match(/Explanation:\s*(.*?)(?:\n\*\*|$)/s) ||
      content.match(/## Explanation\s*(.*?)(?:\n##|$)/s);

    // Extract warnings (multiple formats)
    const warningsMatch =
      content.match(/\*\*Warnings\*\*:\s*([\s\S]*?)(?:\n\*\*|$)/) ||
      content.match(/Warnings:\s*([\s\S]*?)(?:\n\*\*|$)/) ||
      content.match(/## Warnings\s*([\s\S]*?)(?:\n##|$)/);

    const warnings = warningsMatch
      ? warningsMatch[1]
          .split('\n')
          .map(w => w.trim().replace(/^[-•*]\s*/, ''))
          .filter(w => w.length > 0)
      : undefined;

    return {
      success: true,
      translatedCode,
      explanation: explanationMatch ? explanationMatch[1].trim() : undefined,
      warnings: warnings && warnings.length > 0 ? warnings : undefined,
    };
  } catch (error) {
    console.error('Error parsing Claude response:', error);
    return {
      success: true,
      translatedCode: content.trim(),
      explanation: 'Translation completed (parsing error)',
      warnings: ['Response parsing encountered issues, code may need review'],
    };
  }
}

/**
 * Main translation function
 */
export async function translateCode(
  request: TranslationRequest
): Promise<TranslationResult> {
  try {
    // Validate platforms
    if (request.sourcePlatform === request.targetPlatform) {
      return {
        success: false,
        error: 'Source and target platforms must be different',
      };
    }

    if (!request.sourceCode || request.sourceCode.trim() === '') {
      return {
        success: false,
        error: 'Source code cannot be empty',
      };
    }

    // Log translation attempt
    trackEvent('translation_started', {
      sourcePlatform: request.sourcePlatform,
      targetPlatform: request.targetPlatform,
      codeLength: request.sourceCode.length,
    });

    // Perform translation
    const result = await translateWithClaudeAPI(request);

    // Log result
    if (result.success) {
      trackEvent('translation_success', {
        sourcePlatform: request.sourcePlatform,
        targetPlatform: request.targetPlatform,
      });
      toast.success(
        `Translated ${request.sourcePlatform} → ${request.targetPlatform}`
      );
    } else {
      trackEvent('translation_failed', {
        sourcePlatform: request.sourcePlatform,
        targetPlatform: request.targetPlatform,
        error: result.error,
      });
      toast.error(`Translation failed: ${result.error}`);
    }

    return result;
  } catch (error) {
    trackError(error as Error, { context: 'translate_code' });
    return {
      success: false,
      error: `Unexpected error: ${(error as Error).message}`,
    };
  }
}

/**
 * Get supported translation pairs
 */
export function getSupportedTranslations(): Array<{
  source: PlatformId;
  target: PlatformId;
}> {
  return [
    { source: 'roblox', target: 'uefn' },
    { source: 'uefn', target: 'roblox' },
    { source: 'roblox', target: 'spatial' },
    { source: 'spatial', target: 'roblox' },
    { source: 'uefn', target: 'spatial' },
    { source: 'spatial', target: 'uefn' },
  ];
}

/**
 * Check if translation is supported
 */
export function isTranslationSupported(
  source: PlatformId,
  target: PlatformId
): boolean {
  return getSupportedTranslations().some(
    (pair) => pair.source === source && pair.target === target
  );
}
