"""
통합 테스트 파일 - 일반/인터페이스/보안 모드 모두 테스트 가능

이 파일은 gar의 세 가지 모드를 모두 테스트할 수 있도록 설계되었습니다:
1. 일반 모드: 코드 품질, 리팩토링 제안
2. 인터페이스 모드: 함수/클래스 인터페이스 변경
3. 보안 모드: 보안 취약점
"""

import os
import sqlite3
import subprocess
import requests
import hashlib
from typing import Optional, Dict, List
from flask import Flask, request, jsonify, Response
from urllib.request import urlopen

app = Flask(__name__)

# 보안 취약점: 암호화·시크릿 - 하드코딩된 시크릿
API_KEY = "sk-1234567890abcdefghijklmnopqrstuvwxyz"
SECRET_TOKEN = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0"
DATABASE_PASSWORD = "SuperSecret123!"
AWS_ACCESS_KEY = "AKIAIOSFODNN7EXAMPLE"
AWS_SECRET_KEY = "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
PRIVATE_KEY = "-----BEGIN RSA PRIVATE KEY-----\nMIIEpAIBAAKCAQEA..."
JWT_SECRET = "my-super-secret-jwt-key-12345"


# 일반 모드 이슈: 복잡한 함수, 중복 코드, 매직 넘버
def process_user_data(user_id: int, user_data: Dict[str, str]) -> Optional[Dict]:
    """사용자 데이터 처리 - 복잡한 로직, 매직 넘버 사용"""
    if user_id < 0 or user_id > 999999:  # 매직 넘버
        return None
    
    # 중복된 검증 로직
    if not user_data:
        return None
    if "name" not in user_data:
        return None
    if "email" not in user_data:
        return None
    
    # 복잡한 중첩 조건문
    if user_data.get("status") == "active":
        if user_data.get("verified") == True:
            if user_data.get("role") in ["admin", "user"]:
                if len(user_data.get("name", "")) > 5:
                    return {"id": user_id, "data": user_data}
    
    return None


# 인터페이스 모드: 함수 시그니처 변경 가능
class UserService:
    """사용자 서비스 클래스 - 인터페이스 변경 테스트용"""
    
    def __init__(self, db_path: str = "app.db"):
        self.db_path = db_path
    
    # 인터페이스 변경: 파라미터 추가/제거 가능
    def get_user(self, user_id: int, include_deleted: bool = False) -> Optional[Dict]:
        """사용자 조회"""
        conn = sqlite3.connect(self.db_path)
        cursor = conn.cursor()
        cursor.execute("SELECT * FROM users WHERE id = ?", (user_id,))
        row = cursor.fetchone()
        conn.close()
        return {"id": row[0], "name": row[1]} if row else None
    
    # 인터페이스 변경: 반환 타입 변경 가능
    def create_user(self, name: str, email: str) -> int:
        """사용자 생성 - 반환 타입이 int에서 Dict로 변경될 수 있음"""
        conn = sqlite3.connect(self.db_path)
        cursor = conn.cursor()
        cursor.execute("INSERT INTO users (name, email) VALUES (?, ?)", (name, email))
        user_id = cursor.lastrowid
        conn.commit()
        conn.close()
        return user_id


# 보안 취약점: 인증·인가 - 하드코딩된 비밀번호, API 키 노출
@app.post("/auth/login")
def auth_login():
    """인증 로그인 - 하드코딩된 비밀번호, API 키 노출"""
    username = request.form.get("username")
    password = request.form.get("password")
    if username == "admin" and password == "admin":  # 하드코딩된 비밀번호
        return jsonify({"token": f"{username}:{API_KEY}"})  # API 키 노출
    return jsonify({"error": "invalid credentials"}), 401


# 보안 취약점: 인증·인가 - IDOR, SQL 인젝션
@app.post("/user/update_role")
def update_role():
    """역할 업데이트 - IDOR 취약점, SQL 인젝션"""
    user_id = request.form.get("user_id")
    role = request.form.get("role")
    # IDOR 취약점: 권한 체크 없이 다른 사용자의 역할 변경 가능
    # 현재 사용자 확인 없이 user_id로 직접 업데이트
    conn = sqlite3.connect("app.db")
    cursor = conn.cursor()
    # SQL 인젝션 취약점: 사용자 입력을 직접 문자열 포맷으로 쿼리에 삽입
    cursor.execute(f"UPDATE users SET role = '{role}' WHERE id = '{user_id}'")
    conn.commit()
    conn.close()
    return jsonify({"user_id": user_id, "role": role, "api_key": API_KEY})


# 보안 취약점: 인증·인가 - IDOR (명확한 예시)
@app.post("/user/change_role")
def change_role():
    """사용자 역할 변경 - IDOR 취약점"""
    target_user_id = request.json.get("user_id")
    new_role = request.json.get("role")
    # IDOR 취약점: 권한 체크 없이 다른 사용자의 역할을 변경할 수 있음
    # 현재 사용자의 권한을 확인하지 않고 target_user_id로 직접 업데이트
    conn = sqlite3.connect("app.db")
    cursor = conn.cursor()
    cursor.execute(f"UPDATE users SET role = '{new_role}' WHERE id = {target_user_id}")
    conn.commit()
    conn.close()
    return jsonify({"success": True, "user_id": target_user_id, "role": new_role})


# 보안 취약점: 인증·인가 - 권한 체크 없음
@app.post("/admin/delete_user")
def delete_user():
    """사용자 삭제 - 권한 체크 없음"""
    user_id = request.form.get("user_id")
    # 권한 체크 없이 관리자 기능 실행
    conn = sqlite3.connect("app.db")
    cursor = conn.cursor()
    cursor.execute("DELETE FROM users WHERE id = ?", (user_id,))
    conn.commit()
    conn.close()
    return jsonify({"deleted": user_id})


# 보안 취약점: 입력값 검증·인젝션 - SQL 인젝션, 민감정보 노출
@app.get("/account/detail")
def account_detail():
    """계정 상세 조회 - SQL 인젝션, 민감정보 노출"""
    account_id = request.args.get("id")
    # SQL 인젝션 취약점: 사용자 입력을 직접 문자열 포맷으로 쿼리에 삽입
    conn = sqlite3.connect("app.db")
    cursor = conn.cursor()
    cursor.execute(f"SELECT * FROM accounts WHERE id = '{account_id}'")
    row = cursor.fetchone()
    conn.close()
    # 민감정보 노출: API 키와 시크릿 토큰을 함께 반환
    return jsonify({
        "account": row,
        "api_key": API_KEY,
        "secret": SECRET_TOKEN,
        "password": DATABASE_PASSWORD
    })


# 보안 취약점: 입력값 검증·인젝션 - SQL 인젝션 (명확한 예시)
@app.get("/user/search")
def user_search():
    """사용자 검색 - SQL 인젝션 취약점"""
    query = request.args.get("q")
    # SQL 인젝션 취약점: 사용자 입력을 직접 문자열 포맷으로 쿼리에 삽입
    # 예: q=admin' OR '1'='1 로 모든 사용자 조회 가능
    conn = sqlite3.connect("app.db")
    cursor = conn.cursor()
    cursor.execute(f"SELECT * FROM users WHERE name LIKE '%{query}%'")
    rows = cursor.fetchall()
    conn.close()
    return jsonify({"users": rows})


# 보안 취약점: 입력값 검증·인젝션 - 명령 주입
@app.post("/system/run")
def system_run():
    """시스템 명령 실행 - 명령 주입 취약점"""
    cmd = request.json.get("cmd")
    # 명령 주입 취약점: 사용자 입력을 shell=True로 실행, 검증 없음
    output = subprocess.check_output(cmd, shell=True, text=True)
    return jsonify({"output": output, "command": cmd})


# 보안 취약점: 입력값 검증·인젝션 - 명령 주입 (os.system)
@app.post("/system/exec")
def system_exec():
    """시스템 명령 실행 - os.system 사용"""
    command = request.json.get("command")
    # 명령 주입 취약점: os.system으로 사용자 입력 직접 실행
    # 예: command=rm -rf / 또는 command=; cat /etc/passwd
    os.system(command)
    return jsonify({"status": "executed"})


# 보안 취약점: 입력값 검증·인젝션 - 명령 주입 (subprocess.Popen)
@app.post("/system/process")
def process_command():
    """명령 처리 - 명령 주입 취약점"""
    cmd = request.json.get("cmd")
    # 명령 주입 취약점: subprocess.Popen으로 사용자 입력 직접 실행
    process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    stdout, stderr = process.communicate()
    return jsonify({"output": stdout.decode(), "error": stderr.decode()})


# 보안 취약점: 입력값 검증·인젝션 - 경로 탐색
@app.get("/file/read")
def file_read():
    """파일 읽기 - 경로 탐색 취약점"""
    path = request.args.get("path")
    # 경로 탐색 취약점: 사용자 입력을 검증 없이 파일 경로로 사용
    # ../../../etc/passwd 같은 경로 탐색 공격 가능
    with open(path, "r") as f:
        content = f.read()
    return jsonify({"path": path, "content": content})


# 보안 취약점: 입력값 검증·인젝션 - 경로 탐색 (문자열 연결)
@app.get("/file/download")
def file_download():
    """파일 다운로드 - 경로 탐색 취약점"""
    filename = request.args.get("file")
    # 경로 탐색 취약점: 사용자 입력을 직접 경로에 사용
    # 예: file=../../../etc/passwd 로 시스템 파일 접근 가능
    filepath = f"/uploads/{filename}"
    with open(filepath, "rb") as f:
        content = f.read()
    return Response(content, mimetype="application/octet-stream")


# 보안 취약점: 입력값 검증·인젝션 - 경로 탐색 (os.path.join 미사용)
@app.get("/file/read_content")
def read_file_content():
    """파일 내용 읽기 - 경로 탐색 취약점"""
    filepath = request.args.get("path")
    # 경로 탐색 취약점: 사용자 입력을 검증 없이 파일 경로로 사용
    # 예: path=../../.env 로 환경 변수 파일 접근 가능
    with open(filepath, "r", encoding="utf-8") as f:
        content = f.read()
    return jsonify({"path": filepath, "content": content})


# 보안 취약점: 입력값 검증·인젝션 - XSS
@app.get("/render")
def render():
    """HTML 렌더링 - XSS 취약점"""
    html = request.args.get("html")
    # XSS 취약점: 사용자 입력을 검증 없이 HTML로 렌더링
    return Response(html, mimetype="text/html")


# 보안 취약점: 입력값 검증·인젝션 - XSS (템플릿 렌더링)
@app.get("/comment")
def show_comment():
    """댓글 표시 - XSS 취약점"""
    comment = request.args.get("comment")
    # XSS 취약점: 사용자 입력을 검증 없이 HTML로 렌더링
    # 예: comment=<script>alert('XSS')</script> 로 스크립트 실행 가능
    html_content = f"<div>{comment}</div>"
    return Response(html_content, mimetype="text/html")


# 보안 취약점: 입력값 검증·인젝션 - 오픈 리다이렉트
@app.get("/redirect")
def redirect():
    """리다이렉트 - 오픈 리다이렉트 취약점"""
    target = request.args.get("to")
    # 오픈 리다이렉트 취약점: 외부 URL로 리다이렉트 가능
    return "", 302, {"Location": target}


# 보안 취약점: 외부 통신 - SSRF
@app.get("/fetch")
def fetch():
    """외부 URL 페치 - SSRF 취약점"""
    url = request.args.get("url")
    # SSRF 취약점: verify=False로 TLS 검증 비활성화, 외부 URL 직접 호출
    # 내부 네트워크(127.0.0.1, 10.0.0.1 등) 접근 가능
    resp = requests.get(url, verify=False, timeout=3)
    return jsonify({"status": resp.status_code, "body": resp.text, "url": url})


# 보안 취약점: 외부 통신 - SSRF (urllib)
@app.get("/proxy")
def proxy():
    """프록시 요청 - SSRF 취약점"""
    target_url = request.args.get("url")
    # SSRF 취약점: urllib로 내부 네트워크 접근 가능
    response = urlopen(target_url)
    return jsonify({"content": response.read().decode("utf-8")})


# 보안 취약점: 외부 통신 - HTTP 사용
@app.get("/api/call")
def api_call():
    """API 호출 - HTTP 사용"""
    api_url = request.args.get("url")
    # 외부 통신 취약점: HTTP 사용 (HTTPS 아님)
    resp = requests.get(api_url, timeout=5)
    return jsonify({"data": resp.json()})


# 보안 취약점: 외부 통신 - HTTP 사용 (명확한 예시)
@app.post("/payment/process")
def process_payment():
    """결제 처리 - HTTP 사용 취약점"""
    payment_data = request.json
    # 외부 통신 취약점: HTTP 사용 (HTTPS 아님)
    # 결제 정보를 HTTP로 전송하면 중간자 공격으로 정보 유출 가능
    api_url = "http://payment-gateway.com/api/charge"
    resp = requests.post(api_url, json=payment_data, timeout=10)
    return jsonify({"status": resp.status_code, "response": resp.json()})


# 보안 취약점: 민감정보 노출 - 로깅
@app.post("/log")
def log_message():
    """로그 메시지 - 민감정보 노출"""
    message = request.json.get("message")
    # 민감정보 노출: 로그에 API 키와 시크릿 토큰 포함
    print(f"Log: {message}, API_KEY={API_KEY}, SECRET={SECRET_TOKEN}, PASSWORD={DATABASE_PASSWORD}")
    return jsonify({"logged": True})


# 보안 취약점: 민감정보 노출 - 에러 메시지
@app.post("/error")
def error_handler():
    """에러 핸들러 - 민감정보 노출"""
    try:
        user_id = request.json.get("user_id")
        conn = sqlite3.connect("app.db")
        cursor = conn.cursor()
        cursor.execute("SELECT * FROM users WHERE id = ?", (user_id,))
        row = cursor.fetchone()
        conn.close()
        if not row:
            # 민감정보 노출: 에러 메시지에 데이터베이스 정보 포함
            raise ValueError(f"User not found. DB: app.db, Query: SELECT * FROM users WHERE id = {user_id}")
    except Exception as e:
        # 민감정보 노출: 전체 예외 정보를 응답에 포함
        return jsonify({"error": str(e), "traceback": repr(e)}), 500
    return jsonify({"user": row})


# 보안 취약점: 민감정보 노출 - 응답에 시크릿 포함
@app.get("/config")
def get_config():
    """설정 조회 - 민감정보 노출"""
    # 민감정보 노출: 응답에 시크릿 정보 포함
    return jsonify({
        "api_key": API_KEY,
        "secret": SECRET_TOKEN,
        "aws_key": AWS_ACCESS_KEY,
        "aws_secret": AWS_SECRET_KEY,
        "db_password": DATABASE_PASSWORD
    })


# 보안 취약점: 민감정보 노출 - 디버그 정보
@app.get("/debug/info")
def debug_info():
    """디버그 정보 - 민감정보 노출"""
    # 민감정보 노출: 디버그 모드에서 민감한 정보를 응답에 포함
    return jsonify({
        "debug": True,
        "api_key": API_KEY,
        "secret_token": SECRET_TOKEN,
        "database_password": DATABASE_PASSWORD,
        "jwt_secret": JWT_SECRET,
        "private_key": PRIVATE_KEY
    })


# 보안 취약점: 암호화·시크릿 - 약한 해시 (MD5)
@app.post("/hash_password")
def hash_password():
    """비밀번호 해시 - 약한 해시 알고리즘"""
    password = request.json.get("password")
    # 암호화 취약점: MD5는 취약한 해시 알고리즘
    hashed = hashlib.md5(password.encode()).hexdigest()
    return jsonify({"hash": hashed})


# 보안 취약점: 암호화·시크릿 - 약한 해시 (SHA1)
@app.post("/hash_token")
def hash_token():
    """토큰 해시 - SHA1 사용"""
    token = request.json.get("token")
    # 암호화 취약점: SHA1은 취약한 해시 알고리즘
    hashed = hashlib.sha1(token.encode()).hexdigest()
    return jsonify({"hash": hashed})


# 보안 취약점: 암호화·시크릿 - 하드코딩된 키
@app.post("/encrypt")
def encrypt_data():
    """데이터 암호화 - 하드코딩된 키"""
    data = request.json.get("data")
    # 암호화 취약점: 하드코딩된 암호화 키 사용
    encryption_key = "my-secret-encryption-key-12345"
    # 실제 암호화 로직은 생략
    return jsonify({"encrypted": data, "key": encryption_key})


# 보안 취약점: 암호화·시크릿 - 하드코딩된 암호화 키 (명확한 예시)
@app.post("/user/encrypt_data")
def encrypt_user_data():
    """사용자 데이터 암호화 - 하드코딩된 키"""
    user_data = request.json.get("data")
    # 암호화 취약점: 하드코딩된 암호화 키 사용
    # 키가 코드에 하드코딩되어 있어 누구나 복호화 가능
    hardcoded_key = "super-secret-encryption-key-2024"
    # 실제 암호화 로직은 생략
    return jsonify({"encrypted": user_data, "encryption_key": hardcoded_key})


# 일반 모드 이슈: 긴 함수, 복잡한 로직
def complex_calculation(data: List[int]) -> Dict[str, float]:
    """복잡한 계산 함수 - 리팩토링 제안 대상"""
    result = {}
    total = 0
    count = 0
    max_val = None
    min_val = None
    
    for item in data:
        if item is not None:
            total += item
            count += 1
            if max_val is None or item > max_val:
                max_val = item
            if min_val is None or item < min_val:
                min_val = item
    
    if count > 0:
        result["average"] = total / count
        result["max"] = max_val
        result["min"] = min_val
        result["sum"] = total
        result["count"] = count
    else:
        result["average"] = 0
        result["max"] = 0
        result["min"] = 0
        result["sum"] = 0
        result["count"] = 0
    
    return result


# 인터페이스 모드: 함수 시그니처 변경 가능
def format_user_info(user_id: int, include_email: bool = True) -> str:
    """사용자 정보 포맷팅 - 인터페이스 변경 테스트용"""
    service = UserService()
    user = service.get_user(user_id)
    if not user:
        return "User not found"
    
    if include_email:
        return f"User: {user['name']} (ID: {user_id})"
    return f"User: {user['name']}"


# 일반 모드 이슈: 중복 코드
def validate_email(email: str) -> bool:
    """이메일 검증 - 중복 로직"""
    if not email:
        return False
    if "@" not in email:
        return False
    if "." not in email:
        return False
    return True


def validate_phone(phone: str) -> bool:
    """전화번호 검증 - 중복 로직 (validate_email과 유사)"""
    if not phone:
        return False
    if "-" not in phone:
        return False
    if len(phone) < 10:
        return False
    return True


if __name__ == "__main__":
    app.run(debug=True, port=int(os.getenv("PORT", "8000")))