from typing import Optional, List

from llm_redact.config import get_settings
from llm_redact.db.database import get_db_manager, configure_database
from llm_redact.db.models import RedactionResult, RedactionRule, RuleRecord
from llm_redact.client.mask import mask_text
from llm_redact.db.manager import (
    get_rule, list_rules, insert_rule, update_rule, archive_rule
)
from llm_redact.client.rule import generate_rules_from_llm


class LLMRedactClient:
    """Main client for LLM redaction operations"""
    
    def __init__(
        self,
        llm_host_url: Optional[str] = None,
        database_url: Optional[str] = None
    ):
        settings = get_settings()
        self.llm_host_url = llm_host_url or settings.llm_host_url
        self.db_manager = get_db_manager()
        
        if database_url:
            configure_database(database_url)
            self.db_manager = get_db_manager()
    
    def mask(
        self,
        text: str,
        rule_group_id: Optional[str] = None,
        rules: Optional[List[RedactionRule]] = None,
        model: Optional[str] = None
    ) -> RedactionResult:
        """
        Redact sensitive information from text.
        
        Args:
            text: The text to redact
            rule_group_id: Optional rule group ID to use for redaction
            rules: Optional list of RedactionRule objects  
            model: Optional LLM model to use
            
        Note:
            If both rule_group_id and rules are provided, 
            rules takes precedence.
            
        Returns:
            RedactionResult with redacted text and metadata
        """
        return mask_text(
            text=text,
            rule_group_id=rule_group_id,
            rules=rules,
            model=model,
            llm_host_url=self.llm_host_url
        )
    
    def get_history(self, limit: int = 100):
        """Get redaction history from database"""
        return self.db_manager.get_history(limit)
    
    # Rule management methods
    def get_rule(self, rule_id: str) -> Optional[RuleRecord]:
        """Get a specific rule by ID"""
        return get_rule(rule_id)
    
    def list_rules(
        self, 
        active_only: bool = True, 
        include_archived: bool = False,
        limit: int = 100
    ) -> List[RuleRecord]:
        """List redaction rules with filtering options"""
        return list_rules(active_only, include_archived, limit)
    
    def create_rule(
        self, name: str, description: str, data_type: str
    ) -> RuleRecord:
        """Create a new redaction rule"""
        return insert_rule(name, description, data_type)
    
    def update_rule(
        self,
        rule_id: str,
        name: Optional[str] = None,
        description: Optional[str] = None,
        is_active: Optional[bool] = None
    ) -> Optional[RuleRecord]:
        """Update an existing rule"""
        return update_rule(rule_id, name, description, is_active)
    
    def archive_rule(self, rule_id: str) -> Optional[RuleRecord]:
        """Archive a rule (disable and mark as archived)"""
        return archive_rule(rule_id)
    
    def generate_rules(
        self,
        user_input: str,
        model: Optional[str] = None
    ) -> List[RedactionRule]:
        """
        Generate redaction rules based on user input using LLM.
        
        Args:
            user_input: Description of what data to redact
            model: Optional specific model to use
            
        Returns:
            List of RedactionRule objects
            
        Example:
            rules = client.generate_rules(
                "help me filter medical sensitive data"
            )
        """
        return generate_rules_from_llm(
            user_input=user_input,
            llm_host_url=self.llm_host_url,
            model=model
        )
    
    # Legacy compatibility methods
    def get_rules(self):
        """Get all active redaction rules (legacy compatibility)"""
        return self.list_rules(active_only=True, include_archived=False) 