"""Code generators for different languages and testing frameworks"""

import json
from typing import Dict, List, Any, Optional
from jinja2 import Template
from .models import TestCase, TestLanguage, TestFramework


class CodeGenerator:
    """Base class for code generators"""
    
    def __init__(self, language: TestLanguage, framework: TestFramework):
        self.language = language
        self.framework = framework
    
    def generate_test_code(self, test_cases: List[TestCase], session_info: Dict[str, Any]) -> str:
        """Generate test code for the given test cases"""
        
        # Check if we have GraphQL test cases
        is_graphql = self._is_graphql_test_suite(test_cases)
        
        # Get the appropriate template
        template = self._get_template(is_graphql)
        
        return template.render(
            test_cases=test_cases,
            session_info=session_info,
            language=self.language.value,
            framework=self.framework.value,
            is_graphql=is_graphql
        )
    
    def _is_graphql_test_suite(self, test_cases: List[TestCase]) -> bool:
        """Check if test cases are for GraphQL endpoints"""
        if not test_cases:
            return False
        
        # Check if any test case has GraphQL characteristics
        for test_case in test_cases:
            if (test_case.url and "/graphql" in test_case.url) or \
               (test_case.name and "GraphQL" in test_case.name):
                return True
                
        return False
    
    def _get_template(self, is_graphql: bool = False) -> Template:
        """Get the appropriate template for this language/framework combination"""
        if is_graphql:
            # Use GraphQL-specific templates when available
            if self.language == TestLanguage.PYTHON and self.framework == TestFramework.REQUESTS:
                return Template(PYTHON_REQUESTS_GRAPHQL_TEMPLATE)
            elif self.language == TestLanguage.PYTHON and self.framework == TestFramework.PYTEST:
                return Template(PYTHON_PYTEST_GRAPHQL_TEMPLATE)
            elif self.language == TestLanguage.TYPESCRIPT and self.framework == TestFramework.PLAYWRIGHT:
                return Template(TYPESCRIPT_PLAYWRIGHT_GRAPHQL_TEMPLATE)
            elif self.language == TestLanguage.JAVASCRIPT and self.framework == TestFramework.JEST:
                return Template(JAVASCRIPT_JEST_GRAPHQL_TEMPLATE)
        
        # Use regular templates for REST APIs or unsupported GraphQL combinations
        if self.language == TestLanguage.TYPESCRIPT and self.framework == TestFramework.PLAYWRIGHT:
            return Template(TYPESCRIPT_PLAYWRIGHT_TEMPLATE)
        elif self.language == TestLanguage.JAVASCRIPT and self.framework == TestFramework.JEST:
            return Template(JAVASCRIPT_JEST_TEMPLATE)
        elif self.language == TestLanguage.PYTHON and self.framework == TestFramework.PYTEST:
            return Template(PYTHON_PYTEST_TEMPLATE)
        elif self.language == TestLanguage.PYTHON and self.framework == TestFramework.REQUESTS:
            return Template(PYTHON_REQUESTS_TEMPLATE)
        elif self.language == TestLanguage.TYPESCRIPT and self.framework == TestFramework.SUPERTEST:
            return Template(TYPESCRIPT_SUPERTEST_TEMPLATE)
        elif self.language == TestLanguage.JAVASCRIPT and self.framework == TestFramework.CYPRESS:
            return Template(JAVASCRIPT_CYPRESS_TEMPLATE)
        else:
            raise ValueError(f"Unsupported language/framework combination: {self.language.value}/{self.framework.value}")


# TypeScript + Playwright Template
TYPESCRIPT_PLAYWRIGHT_TEMPLATE = """
import { test, expect } from '@playwright/test';

/**
 * API Test Suite
 * Generated by API Tester MCP
 * Session ID: {{ session_info.id }}
 * Language: {{ language }}
 * Framework: {{ framework }}
 */

// Configuration
const BASE_URL = process.env.BASE_URL || '{{ session_info.base_url }}';
const AUTH_TOKEN = process.env.AUTH_TOKEN || '{{ session_info.auth_token }}';

{% for test_case in test_cases %}
test('{{ test_case.name }}', async ({ request }) => {
  const headers: Record<string, string> = {
    'Content-Type': 'application/json',
    'Accept': 'application/json'
  };
  
  {% if test_case.headers %}
  // Add additional headers, overriding defaults if necessary
  {% for key, value in test_case.headers.items() %}
  headers['{{ key }}'] = '{{ value }}';
  {% endfor %}
  {% endif %}

  {% if test_case.body %}
  const requestBody = {{ test_case.body | tojson }};
  {% endif %}

  const response = await request.{{ test_case.method.lower() }}('{{ test_case.url }}', {
    headers,
    {% if test_case.body %}
    data: requestBody,
    {% endif %}
    timeout: {{ test_case.timeout * 1000 }}
  });

  // Assertions
  {% for assertion in test_case.assertions %}
  {% if assertion.type == 'status_code' %}
  {% if assertion.operator == 'eq' %}
  expect(response.status()).toBe({{ assertion.value }});
  {% elif assertion.operator == 'in' %}
  expect([{{ assertion.value | join(', ') }}]).toContain(response.status());
  {% endif %}
  {% elif assertion.type == 'response_time' %}
  // Response time assertion would be handled by Playwright's timeout
  {% elif assertion.type == 'content_type' %}
  const contentType = response.headers()['content-type'] || '';
  {% if assertion.operator == 'contains' %}
  expect(contentType).toContain('{{ assertion.value }}');
  {% endif %}
  {% endif %}
  {% endfor %}

  // Additional validation
  const responseBody = await response.text();
  console.log(`Response status: ${response.status()}`);
  console.log(`Response body: ${responseBody.substring(0, 200)}...`);
});

{% endfor %}
"""

# JavaScript + Jest Template  
JAVASCRIPT_JEST_TEMPLATE = """
const axios = require('axios');

/**
 * API Test Suite
 * Generated by API Tester MCP
 * Session ID: {{ session_info.id }}
 * Language: {{ language }}
 * Framework: {{ framework }}
 */

// Configuration
const BASE_URL = process.env.BASE_URL || '{{ session_info.base_url }}';
const AUTH_TOKEN = process.env.AUTH_TOKEN || '{{ session_info.auth_token }}';

// Setup axios defaults
axios.defaults.timeout = 30000;
axios.defaults.validateStatus = () => true; // Don't throw on any status code

describe('API Test Suite', () => {
  {% for test_case in test_cases %}
  
  test('{{ test_case.name }}', async () => {
    const headers = {
      'Content-Type': 'application/json',
      'Accept': 'application/json'
    };
    
    {% if test_case.headers %}
    // Add additional headers, overriding defaults if necessary
    {% for key, value in test_case.headers.items() %}
    headers['{{ key }}'] = '{{ value }}';
    {% endfor %}
    {% endif %}
    
    const config = {
      method: '{{ test_case.method.lower() }}',
      url: '{{ test_case.url }}',
      headers,
      timeout: {{ test_case.timeout * 1000 }},
      {% if test_case.body %}
      data: {{ test_case.body | tojson }},
      {% endif %}
    };

    const startTime = Date.now();
    const response = await axios(config);
    const responseTime = Date.now() - startTime;

    // Assertions
    {% for assertion in test_case.assertions %}
    {% if assertion.type == 'status_code' %}
    {% if assertion.operator == 'eq' %}
    expect(response.status).toBe({{ assertion.value }});
    {% elif assertion.operator == 'in' %}
    expect([{{ assertion.value | join(', ') }}]).toContain(response.status);
    {% endif %}
    {% elif assertion.type == 'response_time' %}
    {% if assertion.operator == 'lt' %}
    expect(responseTime).toBeLessThan({{ assertion.value }});
    {% endif %}
    {% elif assertion.type == 'content_type' %}
    const contentType = response.headers['content-type'] || '';
    {% if assertion.operator == 'contains' %}
    expect(contentType).toContain('{{ assertion.value }}');
    {% endif %}
    {% endif %}
    {% endfor %}

    // Log response details
    console.log(`Response status: ${response.status}`);
    console.log(`Response time: ${responseTime}ms`);
    if (response.data) {
      console.log(`Response body: ${JSON.stringify(response.data).substring(0, 200)}...`);
    }
  });
  
  {% endfor %}
});
"""

# Python + pytest Template
PYTHON_PYTEST_TEMPLATE = """
import pytest
import requests
import json
import time
from typing import Dict, Any

\"""
API Test Suite
Generated by API Tester MCP
Session ID: {{ session_info.id }}
Language: {{ language }}
Framework: {{ framework }}
\"""

# Configuration
BASE_URL = "{{ session_info.base_url }}"
AUTH_TOKEN = "{{ session_info.auth_token }}"

class TestAPIEndpoints:
    {% for test_case in test_cases %}
    
    def test_{{ test_case.id.replace('-', '_') }}(self):
        \"""{{ test_case.name }}\"""
        
        headers = {
            'Content-Type': 'application/json',
            'Accept': 'application/json'
        }
        
        {% if test_case.headers %}
        # Add additional headers, overriding defaults if necessary
        {% for key, value in test_case.headers.items() %}
        headers['{{ key }}'] = '{{ value }}'
        {% endfor %}
        {% endif %}
        
        {% if test_case.body %}
        request_body = {{ test_case.body | tojson }}
        {% endif %}
        
        start_time = time.time()
        response = requests.{{ test_case.method.lower() }}(
            url='{{ test_case.url }}',
            headers=headers,
            {% if test_case.body %}
            json=request_body,
            {% endif %}
            timeout={{ test_case.timeout }}
        )
        response_time = (time.time() - start_time) * 1000  # Convert to milliseconds
        
        # Assertions
        {% for assertion in test_case.assertions %}
        {% if assertion.type == 'status_code' %}
        {% if assertion.operator == 'eq' %}
        assert response.status_code == {{ assertion.value }}, f"Expected status {{ assertion.value }}, got {response.status_code}"
        {% elif assertion.operator == 'in' %}
        assert response.status_code in {{ assertion.value }}, f"Expected status in {{ assertion.value }}, got {response.status_code}"
        {% endif %}
        {% elif assertion.type == 'response_time' %}
        {% if assertion.operator == 'lt' %}
        assert response_time < {{ assertion.value }}, f"Response time {response_time}ms exceeded limit {{ assertion.value }}ms"
        {% endif %}
        {% elif assertion.type == 'content_type' %}
        content_type = response.headers.get('content-type', '')
        {% if assertion.operator == 'contains' %}
        assert '{{ assertion.value }}' in content_type, f"Content-type '{content_type}' does not contain '{{ assertion.value }}'"
        {% endif %}
        {% endif %}
        {% endfor %}
        
        # Log response details
        print(f"Response status: {response.status_code}")
        print(f"Response time: {response_time:.2f}ms")
        if response.text:
            print(f"Response body: {response.text[:200]}...")
    
    {% endfor %}
"""

# Python + requests Template (simpler, without pytest)
PYTHON_REQUESTS_TEMPLATE = """
import requests
import json
import time
from typing import Dict, Any

\"""
API Test Suite
Generated by API Tester MCP
Session ID: {{ session_info.id }}
Language: {{ language }}
Framework: {{ framework }}
\"""

# Configuration
BASE_URL = "{{ session_info.base_url }}"
AUTH_TOKEN = "{{ session_info.auth_token }}"

def run_all_tests():
    \"""Run all API tests\"""
    results = []
    
    {% for test_case in test_cases %}
    # Test: {{ test_case.name }}
    try:
        headers = {
            'Content-Type': 'application/json',
            'Accept': 'application/json'
        }
        
        {% if test_case.headers %}
        # Add additional headers, overriding defaults if necessary
        {% for key, value in test_case.headers.items() %}
        headers['{{ key }}'] = '{{ value }}'
        {% endfor %}
        {% endif %}
        
        {% if test_case.body %}
        request_body = {{ test_case.body | tojson }}
        {% endif %}
        
        start_time = time.time()
        response = requests.{{ test_case.method.lower() }}(
            url='{{ test_case.url }}',
            headers=headers,
            {% if test_case.body %}
            json=request_body,
            {% endif %}
            timeout={{ test_case.timeout }}
        )
        response_time = (time.time() - start_time) * 1000
        
        # Validate assertions
        test_passed = True
        assertion_results = []
        
        {% for assertion in test_case.assertions %}
        try:
            {% if assertion.type == 'status_code' %}
            {% if assertion.operator == 'eq' %}
            assert response.status_code == {{ assertion.value }}
            {% elif assertion.operator == 'in' %}
            assert response.status_code in {{ assertion.value }}
            {% endif %}
            assertion_results.append(("status_code", True, "Passed"))
            {% elif assertion.type == 'response_time' %}
            {% if assertion.operator == 'lt' %}
            assert response_time < {{ assertion.value }}
            {% endif %}
            assertion_results.append(("response_time", True, "Passed"))
            {% elif assertion.type == 'content_type' %}
            content_type = response.headers.get('content-type', '')
            {% if assertion.operator == 'contains' %}
            assert '{{ assertion.value }}' in content_type
            {% endif %}
            assertion_results.append(("content_type", True, "Passed"))
            {% endif %}
        except AssertionError as e:
            test_passed = False
            assertion_results.append(("assertion", False, str(e)))
        {% endfor %}
        
        results.append({
            'test_name': '{{ test_case.name }}',
            'test_id': '{{ test_case.id }}',
            'passed': test_passed,
            'response_status': response.status_code,
            'response_time': response_time,
            'assertion_results': assertion_results
        })
        
        print(f"✓ {{ test_case.name }} - {'PASSED' if test_passed else 'FAILED'}")
        print(f"  Status: {response.status_code}, Time: {response_time:.2f}ms")
        
    except Exception as e:
        results.append({
            'test_name': '{{ test_case.name }}',
            'test_id': '{{ test_case.id }}',
            'passed': False,
            'error': str(e)
        })
        print(f"✗ {{ test_case.name }} - ERROR: {e}")
    
    {% endfor %}
    
    # Print summary
    total_tests = len(results)
    passed_tests = sum(1 for r in results if r.get('passed', False))
    
    print(f"\\nTest Summary:")
    print(f"Total: {total_tests}")
    print(f"Passed: {passed_tests}")
    print(f"Failed: {total_tests - passed_tests}")
    print(f"Success Rate: {(passed_tests/total_tests*100):.1f}%")
    
    return results

if __name__ == "__main__":
    run_all_tests()
"""

# TypeScript + Supertest Template
TYPESCRIPT_SUPERTEST_TEMPLATE = """
import request from 'supertest';

/**
 * API Test Suite
 * Generated by API Tester MCP
 * Session ID: {{ session_info.id }}
 * Language: {{ language }}
 * Framework: {{ framework }}
 */

const BASE_URL = process.env.BASE_URL || '{{ session_info.base_url }}';
const AUTH_TOKEN = process.env.AUTH_TOKEN || '{{ session_info.auth_token }}';

describe('API Test Suite', () => {
  {% for test_case in test_cases %}
  
  it('{{ test_case.name }}', async () => {
    let req = request(BASE_URL)
      .{{ test_case.method.lower() }}('{{ test_case.url.replace(session_info.base_url, '') }}')
      .set('Content-Type', 'application/json')
      .set('Accept', 'application/json')
      .timeout({{ test_case.timeout * 1000 }});
    
    {% if test_case.headers %}
    // Add additional headers (will override defaults if same key)
    {% for key, value in test_case.headers.items() %}
    req = req.set('{{ key }}', '{{ value }}');
    {% endfor %}
    {% endif %}
    
    {% if test_case.body %}
    req.send({{ test_case.body | tojson }});
    {% endif %}
    
    const response = await req;
    
    // Assertions
    {% for assertion in test_case.assertions %}
    {% if assertion.type == 'status_code' %}
    {% if assertion.operator == 'eq' %}
    expect(response.status).toBe({{ assertion.value }});
    {% elif assertion.operator == 'in' %}
    expect([{{ assertion.value | join(', ') }}]).toContain(response.status);
    {% endif %}
    {% elif assertion.type == 'content_type' %}
    {% if assertion.operator == 'contains' %}
    expect(response.headers['content-type']).toContain('{{ assertion.value }}');
    {% endif %}
    {% endif %}
    {% endfor %}
    
    console.log(`Response status: ${response.status}`);
    console.log(`Response body: ${JSON.stringify(response.body).substring(0, 200)}...`);
  });
  
  {% endfor %}
});
"""

# JavaScript + Cypress Template
JAVASCRIPT_CYPRESS_TEMPLATE = """
/**
 * API Test Suite
 * Generated by API Tester MCP
 * Session ID: {{ session_info.id }}
 * Language: {{ language }}
 * Framework: {{ framework }}
 */

const BASE_URL = Cypress.env('BASE_URL') || '{{ session_info.base_url }}';
const AUTH_TOKEN = Cypress.env('AUTH_TOKEN') || '{{ session_info.auth_token }}';

describe('API Test Suite', () => {
  {% for test_case in test_cases %}
  
  it('{{ test_case.name }}', () => {
    const headers = {
      'Content-Type': 'application/json',
      'Accept': 'application/json'
    };
    
    {% if test_case.headers %}
    // Add additional headers, overriding defaults if necessary
    {% for key, value in test_case.headers.items() %}
    headers['{{ key }}'] = '{{ value }}';
    {% endfor %}
    {% endif %}
    
    const options = {
      method: '{{ test_case.method }}',
      url: '{{ test_case.url }}',
      headers,
      timeout: {{ test_case.timeout * 1000 }},
      {% if test_case.body %}
      body: {{ test_case.body | tojson }},
      {% endif %}
      failOnStatusCode: false
    };
    
    cy.request(options).then((response) => {
      // Assertions
      {% for assertion in test_case.assertions %}
      {% if assertion.type == 'status_code' %}
      {% if assertion.operator == 'eq' %}
      expect(response.status).to.equal({{ assertion.value }});
      {% elif assertion.operator == 'in' %}
      expect([{{ assertion.value | join(', ') }}]).to.include(response.status);
      {% endif %}
      {% elif assertion.type == 'content_type' %}
      {% if assertion.operator == 'contains' %}
      expect(response.headers['content-type']).to.contain('{{ assertion.value }}');
      {% endif %}
      {% endif %}
      {% endfor %}
      
      // Log response details
      cy.log(`Response status: ${response.status}`);
      cy.log(`Response body: ${JSON.stringify(response.body).substring(0, 200)}...`);
    });
  });
  
  {% endfor %}
});
"""


# GraphQL-specific templates
PYTHON_REQUESTS_GRAPHQL_TEMPLATE = """
import requests
import json
import time
from typing import Dict, Any, Optional

\"""
GraphQL API Test Suite
Generated by API Tester MCP
Session ID: {{ session_info.id }}
Language: {{ language }}
Framework: {{ framework }}
\"""

# Configuration
{% if session_info.graphql_endpoint %}
GRAPHQL_ENDPOINT = "{{ session_info.graphql_endpoint }}"
{% else %}
GRAPHQL_ENDPOINT = "{{ session_info.base_url }}/graphql"
{% endif %}

{% if session_info.auth_token %}
AUTH_TOKEN = "{{ session_info.auth_token }}"
{% else %}
AUTH_TOKEN = None
{% endif %}

def execute_graphql_query(query: str, variables: Optional[Dict[str, Any]] = None, headers: Optional[Dict[str, str]] = None) -> Dict[str, Any]:
    \"""Execute a GraphQL query\"""
    request_headers = {
        'Content-Type': 'application/json',
        'Accept': 'application/json'
    }
    
    if AUTH_TOKEN:
        request_headers['Authorization'] = f'Bearer {AUTH_TOKEN}'
    
    if headers:
        request_headers.update(headers)
    
    payload = {"query": query}
    if variables:
        payload["variables"] = variables
    
    response = requests.post(
        url=GRAPHQL_ENDPOINT,
        json=payload,
        headers=request_headers,
        timeout=30
    )
    
    return response.json()

def run_all_tests():
    \"""Run all GraphQL API tests\"""
    results = []
    
    {% for test_case in test_cases %}
    # Test: {{ test_case.name }}
    try:
        start_time = time.time()
        
        # Extract GraphQL query from test case body
        {% if test_case.body %}
        test_body = {{ test_case.body | tojson }}
        query = test_body.get("query", "")
        variables = test_body.get("variables", {})
        {% else %}
        # Generate query based on test case info
        query = \"""
        # Auto-generated query for {{ test_case.name }}
        # Add your GraphQL query here
        \"""
        variables = {}
        {% endif %}
        
        # Execute GraphQL query
        response_data = execute_graphql_query(query, variables)
        response_time = (time.time() - start_time) * 1000
        
        # Validate response
        success = True
        error_msg = None
        
        if "errors" in response_data and response_data["errors"]:
            success = False
            error_msg = f"GraphQL errors: {response_data['errors']}"
        elif "data" not in response_data:
            success = False
            error_msg = "No data field in response"
        
        {% if test_case.assertions %}
        # Custom assertions
        {% for assertion in test_case.assertions %}
        try:
            # {{ assertion.description }}
            if "{{ assertion.type }}" == "field_exists":
                field_path = "{{ assertion.field }}"
                data = response_data.get("data", {})
                if field_path not in str(data):
                    success = False
                    error_msg = f"Field '{field_path}' not found in response"
            elif "{{ assertion.type }}" == "no_errors":
                if response_data.get("errors"):
                    success = False
                    error_msg = "Expected no errors but got: " + str(response_data["errors"])
        except Exception as e:
            success = False
            error_msg = f"Assertion failed: {str(e)}"
        {% endfor %}
        {% endif %}
        
        result = {
            "test": "{{ test_case.name }}",
            "success": success,
            "response_time_ms": round(response_time, 2),
            "response_data": response_data,
            "error": error_msg
        }
        results.append(result)
        print(f"✓ {{ test_case.name }}: {'PASS' if success else 'FAIL'} ({round(response_time, 2)}ms)")
        if error_msg:
            print(f"  Error: {error_msg}")
        
    except Exception as e:
        result = {
            "test": "{{ test_case.name }}",
            "success": False,
            "response_time_ms": 0,
            "error": str(e)
        }
        results.append(result)
        print(f"✗ {{ test_case.name }}: ERROR - {str(e)}")
    
    {% endfor %}
    
    # Summary
    total_tests = len(results)
    passed_tests = sum(1 for r in results if r["success"])
    print(f"\\n=== Test Summary ===")
    print(f"Total: {total_tests}, Passed: {passed_tests}, Failed: {total_tests - passed_tests}")
    
    return results

if __name__ == "__main__":
    run_all_tests()
"""

PYTHON_PYTEST_GRAPHQL_TEMPLATE = """
import pytest
import requests
import json
from typing import Dict, Any, Optional

\"""
GraphQL API Test Suite
Generated by API Tester MCP
Session ID: {{ session_info.id }}
Language: {{ language }}
Framework: {{ framework }}
\"""

# Configuration
{% if session_info.graphql_endpoint %}
GRAPHQL_ENDPOINT = "{{ session_info.graphql_endpoint }}"
{% else %}
GRAPHQL_ENDPOINT = "{{ session_info.base_url }}/graphql"
{% endif %}

{% if session_info.auth_token %}
AUTH_TOKEN = "{{ session_info.auth_token }}"
{% else %}
AUTH_TOKEN = None
{% endif %}

@pytest.fixture
def graphql_client():
    \"""GraphQL client fixture\"""
    class GraphQLClient:
        def __init__(self, endpoint: str, auth_token: Optional[str] = None):
            self.endpoint = endpoint
            self.auth_token = auth_token
        
        def execute(self, query: str, variables: Optional[Dict[str, Any]] = None, headers: Optional[Dict[str, str]] = None) -> Dict[str, Any]:
            request_headers = {
                'Content-Type': 'application/json',
                'Accept': 'application/json'
            }
            
            if self.auth_token:
                request_headers['Authorization'] = f'Bearer {self.auth_token}'
            
            if headers:
                request_headers.update(headers)
            
            payload = {"query": query}
            if variables:
                payload["variables"] = variables
            
            response = requests.post(
                url=self.endpoint,
                json=payload,
                headers=request_headers,
                timeout=30
            )
            
            response.raise_for_status()
            return response.json()
    
    return GraphQLClient(GRAPHQL_ENDPOINT, AUTH_TOKEN)

{% for test_case in test_cases %}
def test_{{ test_case.id | replace('-', '_') }}(graphql_client):
    \"""{{ test_case.name }}\"""
    
    {% if test_case.body %}
    test_body = {{ test_case.body | tojson }}
    query = test_body.get("query", "")
    variables = test_body.get("variables", {})
    {% else %}
    # Auto-generated query for {{ test_case.name }}
    query = \"""
    # Add your GraphQL query here for {{ test_case.name }}
    \"""
    variables = {}
    {% endif %}
    
    # Execute GraphQL query
    response_data = graphql_client.execute(query, variables)
    
    # Basic validations
    assert "data" in response_data, "Response should contain 'data' field"
    
    if response_data.get("errors"):
        pytest.fail(f"GraphQL errors: {response_data['errors']}")
    
    {% if test_case.assertions %}
    # Custom assertions
    {% for assertion in test_case.assertions %}
    # {{ assertion.description }}
    {% if assertion.type == "field_exists" %}
    data = response_data.get("data", {})
    assert "{{ assertion.field }}" in str(data), "Field '{{ assertion.field }}' should exist in response data"
    {% elif assertion.type == "no_errors" %}
    assert not response_data.get("errors"), f"Expected no errors but got: {response_data.get('errors')}"
    {% elif assertion.type == "status_code" %}
    # Status code assertions are handled by requests.raise_for_status() above
    pass
    {% endif %}
    {% endfor %}
    {% endif %}

{% endfor %}
"""

TYPESCRIPT_PLAYWRIGHT_GRAPHQL_TEMPLATE = """
import { test, expect } from '@playwright/test';

/**
 * GraphQL API Test Suite
 * Generated by API Tester MCP
 * Session ID: {{ session_info.id }}
 * Language: {{ language }}
 * Framework: {{ framework }}
 */

const GRAPHQL_ENDPOINT = '{% if session_info.graphql_endpoint %}{{ session_info.graphql_endpoint }}{% else %}{{ session_info.base_url }}/graphql{% endif %}';
const AUTH_TOKEN = {% if session_info.auth_token %}'{{ session_info.auth_token }}'{% else %}null{% endif %};

interface GraphQLResponse {
  data?: any;
  errors?: Array<{ message: string; locations?: any[]; path?: string[] }>;
}

async function executeGraphQLQuery(
  query: string, 
  variables?: Record<string, any>,
  customHeaders?: Record<string, string>
): Promise<GraphQLResponse> {
  const headers: Record<string, string> = {
    'Content-Type': 'application/json',
    'Accept': 'application/json',
  };
  
  if (AUTH_TOKEN) {
    headers['Authorization'] = `Bearer ${AUTH_TOKEN}`;
  }
  
  if (customHeaders) {
    Object.assign(headers, customHeaders);
  }
  
  const payload = { query };
  if (variables) {
    (payload as any).variables = variables;
  }
  
  const response = await fetch(GRAPHQL_ENDPOINT, {
    method: 'POST',
    headers,
    body: JSON.stringify(payload),
  });
  
  if (!response.ok) {
    throw new Error(`HTTP error! status: ${response.status}`);
  }
  
  return await response.json();
}

{% for test_case in test_cases %}
test('{{ test_case.name }}', async () => {
  {% if test_case.body %}
  const testBody = {{ test_case.body | tojson }};
  const query = testBody.query || '';
  const variables = testBody.variables || {};
  {% else %}
  // Auto-generated query for {{ test_case.name }}
  const query = `
    # Add your GraphQL query here for {{ test_case.name }}
  `;
  const variables = {};
  {% endif %}
  
  // Execute GraphQL query
  const response = await executeGraphQLQuery(query, variables);
  
  // Basic validations
  expect(response).toHaveProperty('data');
  
  if (response.errors && response.errors.length > 0) {
    throw new Error(`GraphQL errors: ${JSON.stringify(response.errors)}`);
  }
  
  {% if test_case.assertions %}
  // Custom assertions
  {% for assertion in test_case.assertions %}
  // {{ assertion.description }}
  {% if assertion.type == "field_exists" %}
  expect(JSON.stringify(response.data)).toContain('{{ assertion.field }}');
  {% elif assertion.type == "no_errors" %}
  expect(response.errors).toBeFalsy();
  {% endif %}
  {% endfor %}
  {% endif %}
});

{% endfor %}
"""

JAVASCRIPT_JEST_GRAPHQL_TEMPLATE = """
const fetch = require('node-fetch');

/**
 * GraphQL API Test Suite  
 * Generated by API Tester MCP
 * Session ID: {{ session_info.id }}
 * Language: {{ language }}
 * Framework: {{ framework }}
 */

const GRAPHQL_ENDPOINT = '{% if session_info.graphql_endpoint %}{{ session_info.graphql_endpoint }}{% else %}{{ session_info.base_url }}/graphql{% endif %}';
const AUTH_TOKEN = {% if session_info.auth_token %}'{{ session_info.auth_token }}'{% else %}null{% endif %};

async function executeGraphQLQuery(query, variables = null, customHeaders = {}) {
  const headers = {
    'Content-Type': 'application/json',
    'Accept': 'application/json',
    ...customHeaders
  };
  
  if (AUTH_TOKEN) {
    headers['Authorization'] = `Bearer ${AUTH_TOKEN}`;
  }
  
  const payload = { query };
  if (variables) {
    payload.variables = variables;
  }
  
  const response = await fetch(GRAPHQL_ENDPOINT, {
    method: 'POST',
    headers,
    body: JSON.stringify(payload),
  });
  
  if (!response.ok) {
    throw new Error(`HTTP error! status: ${response.status}`);
  }
  
  return await response.json();
}

describe('GraphQL API Tests', () => {
  {% for test_case in test_cases %}
  test('{{ test_case.name }}', async () => {
    {% if test_case.body %}
    const testBody = {{ test_case.body | tojson }};
    const query = testBody.query || '';
    const variables = testBody.variables || {};
    {% else %}
    // Auto-generated query for {{ test_case.name }}
    const query = `
      # Add your GraphQL query here for {{ test_case.name }}
    `;
    const variables = {};
    {% endif %}
    
    // Execute GraphQL query
    const response = await executeGraphQLQuery(query, variables);
    
    // Basic validations
    expect(response).toHaveProperty('data');
    
    if (response.errors && response.errors.length > 0) {
      throw new Error(`GraphQL errors: ${JSON.stringify(response.errors)}`);
    }
    
    {% if test_case.assertions %}
    // Custom assertions
    {% for assertion in test_case.assertions %}
    // {{ assertion.description }}
    {% if assertion.type == "field_exists" %}
    expect(JSON.stringify(response.data)).toContain('{{ assertion.field }}');
    {% elif assertion.type == "no_errors" %}
    expect(response.errors).toBeFalsy();
    {% endif %}
    {% endfor %}
    {% endif %}
  });
  
  {% endfor %}
});
"""


def get_supported_combinations() -> List[Dict[str, str]]:
    """Get list of supported language/framework combinations"""
    return [
        {"language": "typescript", "framework": "playwright", "description": "TypeScript with Playwright for robust E2E testing (supports GraphQL)"},
        {"language": "typescript", "framework": "supertest", "description": "TypeScript with Supertest for Express.js API testing"},
        {"language": "javascript", "framework": "jest", "description": "JavaScript with Jest for unit and API testing (supports GraphQL)"},
        {"language": "javascript", "framework": "cypress", "description": "JavaScript with Cypress for E2E API testing"},
        {"language": "python", "framework": "pytest", "description": "Python with pytest for comprehensive testing (supports GraphQL)"},
        {"language": "python", "framework": "requests", "description": "Python with requests library for simple API testing (supports GraphQL)"},
    ]


def generate_package_files(language: TestLanguage, framework: TestFramework) -> Dict[str, str]:
    """Generate package configuration files for the selected language/framework"""
    files = {}
    
    if language == TestLanguage.TYPESCRIPT:
        if framework == TestFramework.PLAYWRIGHT:
            files["package.json"] = """{
  "name": "api-tests",
  "version": "1.0.0",
  "description": "Generated API tests using Playwright",
  "scripts": {
    "test": "npx playwright test",
    "test:headed": "npx playwright test --headed",
    "test:debug": "npx playwright test --debug"
  },
  "devDependencies": {
    "@playwright/test": "^1.40.0",
    "typescript": "^5.0.0"
  }
}"""
            files["playwright.config.ts"] = """import { defineConfig } from '@playwright/test';

export default defineConfig({
  testDir: './tests',
  timeout: 30000,
  retries: 1,
  use: {
    baseURL: process.env.BASE_URL,
    extraHTTPHeaders: {
      'Authorization': `Bearer ${process.env.AUTH_TOKEN || ''}`
    }
  }
});"""
            
        elif framework == TestFramework.SUPERTEST:
            files["package.json"] = """{
  "name": "api-tests",
  "version": "1.0.0",
  "description": "Generated API tests using Supertest",
  "scripts": {
    "test": "jest",
    "test:watch": "jest --watch"
  },
  "devDependencies": {
    "@types/jest": "^29.0.0",
    "@types/supertest": "^2.0.0",
    "jest": "^29.0.0",
    "supertest": "^6.3.0",
    "ts-jest": "^29.0.0",
    "typescript": "^5.0.0"
  }
}"""
            files["jest.config.js"] = """module.exports = {
  preset: 'ts-jest',
  testEnvironment: 'node',
  testMatch: ['**/*.test.ts']
};"""
    
    elif language == TestLanguage.JAVASCRIPT:
        if framework == TestFramework.JEST:
            files["package.json"] = """{
  "name": "api-tests",
  "version": "1.0.0",
  "description": "Generated API tests using Jest",
  "scripts": {
    "test": "jest",
    "test:watch": "jest --watch"
  },
  "devDependencies": {
    "axios": "^1.6.0",
    "jest": "^29.0.0"
  }
}"""
        elif framework == TestFramework.CYPRESS:
            files["package.json"] = """{
  "name": "api-tests",
  "version": "1.0.0",
  "description": "Generated API tests using Cypress",
  "scripts": {
    "test": "cypress run",
    "test:open": "cypress open"
  },
  "devDependencies": {
    "cypress": "^13.0.0"
  }
}"""
            files["cypress.config.js"] = """module.exports = {
  e2e: {
    setupNodeEvents(on, config) {},
    specPattern: 'cypress/e2e/**/*.cy.js'
  }
};"""
    
    elif language == TestLanguage.PYTHON:
        if framework == TestFramework.PYTEST:
            files["requirements.txt"] = """pytest>=7.0.0
requests>=2.28.0
pytest-html>=3.0.0"""
            files["pytest.ini"] = """[tool:pytest]
testpaths = tests
addopts = --html=report.html --self-contained-html -v"""
        elif framework == TestFramework.REQUESTS:
            files["requirements.txt"] = """requests>=2.28.0"""
    
    return files