"""
Password entry data models with backward compatibility.
"""
import time as time_module
from typing import Optional, List, Dict, Any


class PasswordEntry:
    """
    Password entry model that supports both legacy and new format.
    
    Legacy format (v1):
        - entries: list of keywords
        - passwd: encrypted password
        - time: timestamp
    
    New format (v2):
        - All legacy fields plus:
        - version: data version (2)
        - title: display name
        - url: website URL
        - username: username/email
        - description: notes
        - created_time: creation timestamp
        - modified_time: last modified timestamp
        - category: category/folder
        - tags: list of tags
    """
    
    def __init__(
        self,
        entries: List[str],
        passwd: str,
        time: str = None,
        version: int = 2,
        title: Optional[str] = None,
        url: Optional[str] = None,
        username: Optional[str] = None,
        description: Optional[str] = None,
        created_time: Optional[str] = None,
        modified_time: Optional[str] = None,
        category: Optional[str] = None,
        tags: Optional[List[str]] = None,
        deleted: Optional[bool] = None
    ):
        self.entries = entries
        self.passwd = passwd
        self.time = time if time is not None else str(time_module.time())
        self.version = version
        
        # Optional fields
        self.title = title
        self.url = url
        self.username = username
        self.description = description
        self.created_time = created_time if created_time is not None else self.time
        self.modified_time = modified_time if modified_time is not None else self.time
        self.category = category
        self.tags = tags if tags is not None else []
        self.deleted = deleted
    
    @classmethod
    def from_legacy(cls, legacy_data: Dict[str, Any]) -> 'PasswordEntry':
        """
        Create PasswordEntry from legacy format (v1).
        
        Args:
            legacy_data: Dict with 'entries', 'passwd', 'time' keys
            
        Returns:
            PasswordEntry instance
        """
        return cls(
            entries=legacy_data['entries'],
            passwd=legacy_data['passwd'],
            time=legacy_data.get('time'),
            version=1,
            deleted=legacy_data.get('deleted')
        )
    
    @classmethod
    def from_dict(cls, data: Dict[str, Any]) -> 'PasswordEntry':
        """
        Create PasswordEntry from dictionary (auto-detect version).
        
        Args:
            data: Dictionary containing entry data
            
        Returns:
            PasswordEntry instance
        """
        version = data.get('version', 1)
        
        if version == 1 or 'version' not in data:
            # Legacy format
            return cls.from_legacy(data)
        
        # New format (v2)
        return cls(
            entries=data['entries'],
            passwd=data['passwd'],
            time=data.get('time'),
            version=version,
            title=data.get('title'),
            url=data.get('url'),
            username=data.get('username'),
            description=data.get('description'),
            created_time=data.get('created_time'),
            modified_time=data.get('modified_time'),
            category=data.get('category'),
            tags=data.get('tags', []),
            deleted=data.get('deleted')
        )
    
    def to_dict(self) -> Dict[str, Any]:
        """
        Serialize to dictionary. Only includes non-empty optional fields.
        
        Returns:
            Dictionary representation
        """
        result = {
            'entries': self.entries,
            'passwd': self.passwd,
            'time': self.time,
            'version': 2  # Always save as v2
        }
        
        # Only save fields that are explicitly set
        optional_fields = {
            'title': self.title,
            'url': self.url,
            'username': self.username,
            'description': self.description,
            'created_time': self.created_time,
            'modified_time': self.modified_time,
            'category': self.category,
            'tags': self.tags,
            'deleted': self.deleted
        }
        
        for key, value in optional_fields.items():
            if value is not None:
                # Skip empty lists and empty strings
                if isinstance(value, (list, str)) and not value:
                    continue
                result[key] = value
        
        return result
    
    def update_fields(self, **kwargs):
        """
        Update entry fields and set modified_time.
        
        Args:
            **kwargs: Fields to update (title, url, username, etc.)
        """
        for key, value in kwargs.items():
            if hasattr(self, key) and value is not None:
                setattr(self, key, value)
        
        self.modified_time = str(time_module.time())
    
    def infer_metadata(self) -> tuple:
        """
        Infer title and URL from entries keywords.
        
        Returns:
            Tuple of (title, url)
        """
        # Known service mappings
        KNOWN_SERVICES = {
            'github': 'https://github.com',
            'google': 'https://google.com',
            'gmail': 'https://gmail.com',
            'amazon': 'https://amazon.com',
            'facebook': 'https://facebook.com',
            'twitter': 'https://twitter.com',
            'linkedin': 'https://linkedin.com',
            'instagram': 'https://instagram.com',
            'reddit': 'https://reddit.com',
            'netflix': 'https://netflix.com',
            'spotify': 'https://spotify.com',
            'dropbox': 'https://dropbox.com',
        }
        
        keywords = self.entries
        
        # Infer title: capitalize first keyword
        title = self.title or (keywords[0].capitalize() if keywords else "Untitled")
        
        # Infer URL
        url = self.url
        if not url:
            for kw in keywords:
                kw_lower = kw.lower()
                # Check known services first
                if kw_lower in KNOWN_SERVICES:
                    url = KNOWN_SERVICES[kw_lower]
                    break
                # Check if it looks like a domain
                elif '.' in kw and not kw.startswith('.'):
                    url = f"https://{kw}"
                    break
        
        return title or "", url or ""
    
    def __repr__(self):
        return f"PasswordEntry(entries={self.entries}, title={self.title}, url={self.url})"
