#!/usr/bin/env python3
"""
Generate high-quality code review training data locally.
"""

import json
import os
from pathlib import Path

OUTPUT_FILE = Path(__file__).parent.parent / "data" / "processed" / "dev_finetuning_generated.json"

def generate_patterns():
    patterns = []
    
    # Python: SQL Injection
    patterns.append({
        "bad": "def get_user(user_id):\n    conn = psycopg2.connect(DB_URL)\n    cursor = conn.cursor()\n    cursor.execute(f\"SELECT * FROM users WHERE id = {user_id}\")\n    return cursor.fetchone()",
        "review": "**Issues Found: 3**\n\n1. **SQL Injection:** String formatting in SQL queries allows attackers to inject arbitrary commands.\n2. **Resource Leak:** Connection and cursor are never closed.\n3. **No Error Handling:** Database failures will crash the application.\n\n**Improved Code:**\n```python\nimport psycopg2\nfrom contextlib import contextmanager\n\n@contextmanager\ndef get_db_connection():\n    conn = psycopg2.connect(DB_URL)\n    try:\n        yield conn\n        conn.commit()\n    except Exception:\n        conn.rollback()\n        raise\n    finally:\n        conn.close()\n\ndef get_user(user_id: int) -> dict:\n    if not isinstance(user_id, int):\n        raise ValueError(\"user_id must be an integer\")\n        \n    with get_db_connection() as conn:\n        with conn.cursor() as cursor:\n            cursor.execute(\"SELECT * FROM users WHERE id = %s\", (user_id,))\n            return cursor.fetchone()\n```",
        "tags": ["python", "sql_injection", "security"]
    })
    
    # Python: Mutable Default
    patterns.append({
        "bad": "def add_item(item, items=[]):\n    items.append(item)\n    return items",
        "review": "**Bug:** Mutable default argument `[]` is shared across all calls. Modifying it in one call affects all subsequent calls.\n\n**Fix:**\n```python\ndef add_item(item, items=None):\n    if items is None:\n        items = []\n    items.append(item)\n    return items\n```",
        "tags": ["python", "mutable_default", "classic_bug"]
    })
    
    # Python: String Concatenation
    patterns.append({
        "bad": "def build_string(items):\n    result = \"\"\n    for item in items:\n        result += str(item)\n    return result",
        "review": "**Performance Issue:** String concatenation in a loop is O(n²). Use `str.join()` instead.\n\n**Fix:**\n```python\ndef build_string(items):\n    return ''.join(str(item) for item in items)\n```",
        "tags": ["python", "performance", "strings"]
    })
    
    # JavaScript: Fetch Error Handling
    patterns.append({
        "bad": "function getUser(id) {\n  fetch('/api/users/' + id)\n    .then(res => res.json())\n    .then(data => console.log(data));\n}",
        "review": "**Issues:**\n1. Promise chain is harder to read than async/await.\n2. No error handling for network failures or invalid responses.\n3. String concatenation is error-prone; use template literals.\n\n**Fix:**\n```javascript\nasync function getUser(id) {\n  try {\n    const response = await fetch(`/api/users/${id}`);\n    if (!response.ok) throw new Error(`HTTP ${response.status}`);\n    const data = await response.json();\n    console.log(data);\n  } catch (error) {\n    console.error('Failed to fetch user:', error);\n  }\n}\n```",
        "tags": ["javascript", "async", "error_handling"]
    })
    
    # JavaScript: Array Mapping
    patterns.append({
        "bad": "const arr = [1, 2, 3, 4, 5];\nconst doubled = [];\nfor (let i = 0; i < arr.length; i++) {\n  doubled.push(arr[i] * 2);\n}",
        "review": "**Readability:** Use `Array.map()` for transformations.\n\n**Fix:**\n```javascript\nconst doubled = arr.map(n => n * 2);\n```",
        "tags": ["javascript", "readability", "arrays"]
    })
    
    # Rust: Borrowing
    patterns.append({
        "bad": "fn main() {\n    let v = vec![1, 2, 3];\n    let x = &v[0];\n    v.push(4);\n    println!(\"{}\", x);\n}",
        "review": "**Bug:** Mutable borrow (`v.push()`) while an immutable borrow (`x`) is active. This will fail to compile.\n\n**Fix:**\n```rust\nfn main() {\n    let mut v = vec![1, 2, 3];\n    let x = v[0]; // Copy, not borrow\n    v.push(4);\n    println!(\"{}\", x);\n}\n```",
        "tags": ["rust", "borrowing", "compile_error"]
    })
    
    # Go: Goroutines
    patterns.append({
        "bad": "package main\nimport \"fmt\"\nfunc main() {\n  ch := make(chan int)\n  go func() {\n    ch <- 42\n  }()\n  fmt.Println(<-ch)\n}",
        "review": "**Issue:** No way to know when the goroutine finishes or if it panicked. Use `sync.WaitGroup` or a done channel.\n\n**Fix:**\n```go\npackage main\nimport (\n\t\"fmt\"\n\t\"sync\"\n)\nfunc main() {\n\tvar wg sync.WaitGroup\n\tch := make(chan int, 1)\n\t\n\twg.Add(1)\n\tgo func() {\n\t\tdefer wg.Done()\n\t\tch <- 42\n\t}()\n\t\n\tfmt.Println(<-ch)\n\twg.Wait()\n}\n```",
        "tags": ["go", "concurrency", "goroutines"]
    })
    
    # Security: Env Files
    patterns.append({
        "bad": "# .env file\nDB_PASSWORD=super_secret_password_123\nAPI_KEY=sk-1234567890abcdef",
        "review": "**Security Issue:** Never commit `.env` files to version control. Use `.env.example` with dummy values and add `.env` to `.gitignore`.\n\n**Fix:**\n```bash\n# .gitignore\n.env\n\n# .env.example\nDB_PASSWORD=your_password_here\nAPI_KEY=your_api_key_here\n```",
        "tags": ["security", "git", "best_practice"]
    })
    
    return patterns


def compile_generated_dataset():
    print("=" * 60)
    print("Dev-AI Generated Dataset")
    print("=" * 60)
    
    all_data = generate_patterns()
    
    # Format for training
    training_data = []
    for item in all_data:
        training_data.append({
            "messages": [
                {"role": "user", "content": f"Review this code for issues:\n\n```{item['tags'][0]}\n{item['bad']}\n```"},
                {"role": "assistant", "content": item['review']}
            ],
            "source": "generated_review",
            "tags": item['tags']
        })
    
    # Save
    os.makedirs(OUTPUT_FILE.parent, exist_ok=True)
    with open(OUTPUT_FILE, "w") as f:
        json.dump(training_data, f, indent=2)
    
    print(f"Total entries: {len(training_data)}")
    print(f"Saved to: {OUTPUT_FILE}")
    print("=" * 60)
    
    return training_data


if __name__ == "__main__":
    compile_generated_dataset()
