"""
NovaLang Repository Generator - Auto-generated CRUD operations
Generates repository implementations for database entities
"""

from typing import Dict, List, Any, Optional
import mysql.connector
import sqlite3

class BaseRepository:
    """Base repository with CRUD operations"""
    
    def __init__(self, entity_class: str, table_name: str, db_connection: Any):
        self.entity_class = entity_class
        self.table_name = table_name
        self.db_connection = db_connection
        self.is_mysql = isinstance(db_connection, mysql.connector.connection.MySQLConnection)
    
    def find_all(self) -> List[Dict[str, Any]]:
        """Get all records"""
        cursor = self.db_connection.cursor(dictionary=True if self.is_mysql else None)
        cursor.execute(f"SELECT * FROM {self.table_name}")
        
        if self.is_mysql:
            results = cursor.fetchall()
        else:
            # SQLite - convert to dict
            columns = [desc[0] for desc in cursor.description]
            results = [dict(zip(columns, row)) for row in cursor.fetchall()]
        
        cursor.close()
        return results
    
    def find_by_id(self, id_value: Any) -> Optional[Dict[str, Any]]:
        """Find by primary key"""
        cursor = self.db_connection.cursor(dictionary=True if self.is_mysql else None)
        cursor.execute(f"SELECT * FROM {self.table_name} WHERE id = %s", (id_value,))
        
        if self.is_mysql:
            result = cursor.fetchone()
        else:
            # SQLite
            columns = [desc[0] for desc in cursor.description]
            row = cursor.fetchone()
            result = dict(zip(columns, row)) if row else None
        
        cursor.close()
        return result
    
    def save(self, entity: Dict[str, Any]) -> Dict[str, Any]:
        """Insert or update record"""
        cursor = self.db_connection.cursor()
        
        # Check if entity has ID (update) or not (insert)
        if 'id' in entity and entity['id']:
            # Update
            set_clause = ', '.join([f"{k} = %s" for k in entity.keys() if k != 'id'])
            values = [v for k, v in entity.items() if k != 'id']
            values.append(entity['id'])
            
            sql = f"UPDATE {self.table_name} SET {set_clause} WHERE id = %s"
            cursor.execute(sql, values)
        else:
            # Insert
            columns = [k for k in entity.keys() if k != 'id' or entity[k]]
            placeholders = ', '.join(['%s'] * len(columns))
            values = [entity[k] for k in columns]
            
            sql = f"INSERT INTO {self.table_name} ({', '.join(columns)}) VALUES ({placeholders})"
            cursor.execute(sql, values)
            
            # Get last inserted ID
            if self.is_mysql:
                entity['id'] = cursor.lastrowid
            else:
                entity['id'] = cursor.lastrowid
        
        self.db_connection.commit()
        cursor.close()
        return entity
    
    def delete_by_id(self, id_value: Any) -> bool:
        """Delete by primary key"""
        cursor = self.db_connection.cursor()
        cursor.execute(f"DELETE FROM {self.table_name} WHERE id = %s", (id_value,))
        self.db_connection.commit()
        affected = cursor.rowcount
        cursor.close()
        return affected > 0
    
    def count(self) -> int:
        """Count all records"""
        cursor = self.db_connection.cursor()
        cursor.execute(f"SELECT COUNT(*) FROM {self.table_name}")
        count = cursor.fetchone()[0]
        cursor.close()
        return count
    
    def exists_by_id(self, id_value: Any) -> bool:
        """Check if record exists"""
        cursor = self.db_connection.cursor()
        cursor.execute(f"SELECT 1 FROM {self.table_name} WHERE id = %s LIMIT 1", (id_value,))
        exists = cursor.fetchone() is not None
        cursor.close()
        return exists
    
    def execute_query(self, query: str, params: tuple = ()) -> List[Dict[str, Any]]:
        """Execute custom query"""
        cursor = self.db_connection.cursor(dictionary=True if self.is_mysql else None)
        cursor.execute(query, params)
        
        if self.is_mysql:
            results = cursor.fetchall()
        else:
            columns = [desc[0] for desc in cursor.description]
            results = [dict(zip(columns, row)) for row in cursor.fetchall()]
        
        cursor.close()
        return results

class RepositoryFactory:
    """Factory to create repository instances"""
    
    @staticmethod
    def create_repository(entity_class: str, table_name: str, 
                         db_connection: Any) -> BaseRepository:
        """Create a repository instance for an entity"""
        return BaseRepository(entity_class, table_name, db_connection)
