# app/models/audit.py

from flask_login import UserMixin
from datetime import datetime
from app.extensions import db, login_manager
from werkzeug.security import generate_password_hash, check_password_hash
import random
import string
import json


class AuditLog(db.Model):
    """مدل ثبت لاگ عملیات کاربران"""
    __tablename__ = 'audit_logs'
    __table_args__ = {'extend_existing': True}
    
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=True)
    
    # اطلاعات عملیات
    action = db.Column(db.String(100), nullable=False)  # create, update, delete, login, logout, view, approve, reject
    entity_type = db.Column(db.String(50), nullable=True)  # user, project, contract, payment, etc.
    entity_id = db.Column(db.Integer, nullable=True)
    
    # تغییرات
    old_value = db.Column(db.Text, nullable=True)
    new_value = db.Column(db.Text, nullable=True)
    details = db.Column(db.Text, nullable=True)
    
    # اطلاعات سیستم
    ip_address = db.Column(db.String(45), nullable=True)
    user_agent = db.Column(db.String(300), nullable=True)
    method = db.Column(db.String(10), nullable=True)  # GET, POST, PUT, DELETE
    url = db.Column(db.String(500), nullable=True)
    
    # زمان
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    
    # ========== روابط با نام یکتا ==========
    user = db.relationship(
        'User',
        foreign_keys=[user_id],
        backref='user_audit_logs_list'  # نام یکتا
    )
    
    # ========== متدها ==========
    
    @classmethod
    def log_action(cls, user_id, action, entity_type=None, entity_id=None, 
                   old_value=None, new_value=None, details=None, request=None):
        """ثبت یک عملیات در لاگ"""
        log = cls(
            user_id=user_id,
            action=action,
            entity_type=entity_type,
            entity_id=entity_id,
            old_value=json.dumps(old_value) if old_value else None,
            new_value=json.dumps(new_value) if new_value else None,
            details=details
        )
        
        if request:
            log.ip_address = request.remote_addr
            log.user_agent = request.headers.get('User-Agent')
            log.method = request.method
            log.url = request.url
        
        db.session.add(log)
        db.session.commit()
        return log
    
    @classmethod
    def log_create(cls, user_id, entity_type, entity_id, new_value, request=None):
        """ثبت عملیات ایجاد"""
        return cls.log_action(
            user_id=user_id,
            action='create',
            entity_type=entity_type,
            entity_id=entity_id,
            new_value=new_value,
            request=request
        )
    
    @classmethod
    def log_update(cls, user_id, entity_type, entity_id, old_value, new_value, request=None):
        """ثبت عملیات ویرایش"""
        return cls.log_action(
            user_id=user_id,
            action='update',
            entity_type=entity_type,
            entity_id=entity_id,
            old_value=old_value,
            new_value=new_value,
            request=request
        )
    
    @classmethod
    def log_delete(cls, user_id, entity_type, entity_id, old_value, request=None):
        """ثبت عملیات حذف"""
        return cls.log_action(
            user_id=user_id,
            action='delete',
            entity_type=entity_type,
            entity_id=entity_id,
            old_value=old_value,
            request=request
        )
    
    @classmethod
    def log_approve(cls, user_id, entity_type, entity_id, details, request=None):
        """ثبت عملیات تایید"""
        return cls.log_action(
            user_id=user_id,
            action='approve',
            entity_type=entity_type,
            entity_id=entity_id,
            details=details,
            request=request
        )
    
    @classmethod
    def log_reject(cls, user_id, entity_type, entity_id, details, request=None):
        """ثبت عملیات رد"""
        return cls.log_action(
            user_id=user_id,
            action='reject',
            entity_type=entity_type,
            entity_id=entity_id,
            details=details,
            request=request
        )
    
    @classmethod
    def log_login(cls, user_id, request=None):
        """ثبت ورود به سیستم"""
        return cls.log_action(
            user_id=user_id,
            action='login',
            details='ورود به سیستم',
            request=request
        )
    
    @classmethod
    def log_logout(cls, user_id, request=None):
        """ثبت خروج از سیستم"""
        return cls.log_action(
            user_id=user_id,
            action='logout',
            details='خروج از سیستم',
            request=request
        )
    
    def to_dict(self):
        """تبدیل به دیکشنری برای JSON"""
        return {
            'id': self.id,
            'user_id': self.user_id,
            'username': self.user.username if self.user else None,
            'fullname': self.user.fullname if self.user else None,
            'action': self.action,
            'entity_type': self.entity_type,
            'entity_id': self.entity_id,
            'details': self.details,
            'ip_address': self.ip_address,
            'method': self.method,
            'url': self.url,
            'created_at': self.created_at.strftime('%Y-%m-%d %H:%M:%S')
        }
    
    def __repr__(self):
        return f'<AuditLog {self.id} - {self.action} - {self.entity_type}>'


class SystemLog(db.Model):
    """مدل ثبت لاگ سیستم (عمومی‌تر)"""
    __tablename__ = 'system_logs'
    __table_args__ = {'extend_existing': True}
    
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=True)
    
    # اطلاعات لاگ
    level = db.Column(db.String(20), default='info')  # info, warning, error, debug
    action = db.Column(db.String(100), nullable=False)
    description = db.Column(db.Text, nullable=True)
    
    # اطلاعات فنی
    module = db.Column(db.String(100), nullable=True)
    function = db.Column(db.String(100), nullable=True)
    line = db.Column(db.Integer, nullable=True)
    
    # اطلاعات سیستم
    ip_address = db.Column(db.String(45), nullable=True)
    user_agent = db.Column(db.String(300), nullable=True)
    traceback = db.Column(db.Text, nullable=True)  # برای خطاها
    
    # زمان
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    
    # ========== روابط با نام یکتا ==========
    user = db.relationship(
        'User',
        foreign_keys=[user_id],
        backref='user_system_logs_list'  # نام یکتا
    )
    
    # ========== متدها ==========
    
    @classmethod
    def info(cls, user_id, action, description=None, module=None, function=None, request=None):
        """ثبت لاگ اطلاعاتی"""
        log = cls(
            user_id=user_id,
            level='info',
            action=action,
            description=description,
            module=module,
            function=function
        )
        if request:
            log.ip_address = request.remote_addr
            log.user_agent = request.headers.get('User-Agent')
        db.session.add(log)
        db.session.commit()
        return log
    
    @classmethod
    def warning(cls, user_id, action, description=None, module=None, function=None, request=None):
        """ثبت لاگ هشدار"""
        log = cls(
            user_id=user_id,
            level='warning',
            action=action,
            description=description,
            module=module,
            function=function
        )
        if request:
            log.ip_address = request.remote_addr
            log.user_agent = request.headers.get('User-Agent')
        db.session.add(log)
        db.session.commit()
        return log
    
    @classmethod
    def error(cls, user_id, action, description=None, traceback=None, module=None, function=None, request=None):
        """ثبت لاگ خطا"""
        log = cls(
            user_id=user_id,
            level='error',
            action=action,
            description=description,
            traceback=traceback,
            module=module,
            function=function
        )
        if request:
            log.ip_address = request.remote_addr
            log.user_agent = request.headers.get('User-Agent')
        db.session.add(log)
        db.session.commit()
        return log
    
    @classmethod
    def debug(cls, user_id, action, description=None, module=None, function=None, request=None):
        """ثبت لاگ دیباگ"""
        log = cls(
            user_id=user_id,
            level='debug',
            action=action,
            description=description,
            module=module,
            function=function
        )
        if request:
            log.ip_address = request.remote_addr
            log.user_agent = request.headers.get('User-Agent')
        db.session.add(log)
        db.session.commit()
        return log
    
    def to_dict(self):
        """تبدیل به دیکشنری برای JSON"""
        return {
            'id': self.id,
            'user_id': self.user_id,
            'username': self.user.username if self.user else None,
            'level': self.level,
            'action': self.action,
            'description': self.description,
            'module': self.module,
            'function': self.function,
            'ip_address': self.ip_address,
            'created_at': self.created_at.strftime('%Y-%m-%d %H:%M:%S')
        }
    
    def __repr__(self):
        return f'<SystemLog {self.id} - {self.level} - {self.action}>'