"""
사용자 활동 로그 서비스
모든 업무 활동을 추적하고 기록하는 서비스
"""

from sqlalchemy.orm import Session
from sqlalchemy import text
from typing import Optional, Dict, Any
from fastapi import Request
import json
from datetime import datetime

from ..utils.logger import get_logger

logger = get_logger(__name__)


class ActivityLogger:
    """사용자 활동 로그 관리 클래스"""
    
    def __init__(self, db: Session):
        self.db = db
    
    def log_activity(
        self,
        username: str,
        activity_type: str,
        activity_description: str,
        target_id: Optional[int] = None,
        target_type: Optional[str] = None,
        user_id: Optional[int] = None,
        ip_address: Optional[str] = None,
        user_agent: Optional[str] = None,
        metadata: Optional[Dict[str, Any]] = None
    ) -> int:
        """
        사용자 활동 로그 기록
        
        Args:
            username: 사용자명 (필수)
            activity_type: 활동 유형 (FILE_UPLOAD, PROJECT_CREATE 등)
            activity_description: 활동 설명
            target_id: 대상 ID (파일, 프로젝트 등)
            target_type: 대상 유형 (FILE, PROJECT 등)
            user_id: 사용자 ID
            ip_address: IP 주소
            user_agent: 브라우저 정보
            metadata: 추가 메타데이터
            
        Returns:
            int: 생성된 로그 ID
        """
        try:
            insert_query = text("""
                INSERT INTO user_activity_logs (
                    user_id, username, activity_type, activity_description,
                    target_id, target_type, ip_address, user_agent, metadata
                ) VALUES (
                    :user_id, :username, :activity_type, :activity_description,
                    :target_id, :target_type, :ip_address, :user_agent, :metadata
                ) RETURNING id
            """)
            
            result = self.db.execute(insert_query, {
                'user_id': user_id,
                'username': username,
                'activity_type': activity_type,
                'activity_description': activity_description,
                'target_id': target_id,
                'target_type': target_type,
                'ip_address': ip_address,
                'user_agent': user_agent,
                'metadata': json.dumps(metadata) if metadata else None
            })
            
            log_id = result.fetchone()[0]
            self.db.commit()
            
            logger.info(f"Activity logged: {username} - {activity_type} - {activity_description}")
            return log_id
            
        except Exception as e:
            logger.error(f"Failed to log activity: {str(e)}")
            self.db.rollback()
            raise
    
    def log_file_upload(
        self,
        username: str,
        file_id: int,
        filename: str,
        file_size: int,
        job_no: str,
        revision: str,
        user_id: Optional[int] = None,
        ip_address: Optional[str] = None,
        user_agent: Optional[str] = None
    ) -> int:
        """파일 업로드 활동 로그"""
        metadata = {
            'filename': filename,
            'file_size': file_size,
            'job_no': job_no,
            'revision': revision,
            'upload_time': datetime.now().isoformat()
        }
        
        return self.log_activity(
            username=username,
            activity_type='FILE_UPLOAD',
            activity_description=f'BOM 파일 업로드: {filename} (Job: {job_no}, Rev: {revision})',
            target_id=file_id,
            target_type='FILE',
            user_id=user_id,
            ip_address=ip_address,
            user_agent=user_agent,
            metadata=metadata
        )
    
    def log_project_create(
        self,
        username: str,
        project_id: int,
        project_name: str,
        job_no: str,
        user_id: Optional[int] = None,
        ip_address: Optional[str] = None,
        user_agent: Optional[str] = None
    ) -> int:
        """프로젝트 생성 활동 로그"""
        metadata = {
            'project_name': project_name,
            'job_no': job_no,
            'create_time': datetime.now().isoformat()
        }
        
        return self.log_activity(
            username=username,
            activity_type='PROJECT_CREATE',
            activity_description=f'프로젝트 생성: {project_name} ({job_no})',
            target_id=project_id,
            target_type='PROJECT',
            user_id=user_id,
            ip_address=ip_address,
            user_agent=user_agent,
            metadata=metadata
        )
    
    def log_material_classify(
        self,
        username: str,
        file_id: int,
        classified_count: int,
        job_no: str,
        revision: str,
        user_id: Optional[int] = None,
        ip_address: Optional[str] = None,
        user_agent: Optional[str] = None
    ) -> int:
        """자재 분류 활동 로그"""
        metadata = {
            'classified_count': classified_count,
            'job_no': job_no,
            'revision': revision,
            'classify_time': datetime.now().isoformat()
        }
        
        return self.log_activity(
            username=username,
            activity_type='MATERIAL_CLASSIFY',
            activity_description=f'자재 분류 완료: {classified_count}개 자재 (Job: {job_no}, Rev: {revision})',
            target_id=file_id,
            target_type='FILE',
            user_id=user_id,
            ip_address=ip_address,
            user_agent=user_agent,
            metadata=metadata
        )
    
    def log_purchase_confirm(
        self,
        username: str,
        job_no: str,
        revision: str,
        confirmed_count: int,
        total_amount: Optional[float] = None,
        user_id: Optional[int] = None,
        ip_address: Optional[str] = None,
        user_agent: Optional[str] = None
    ) -> int:
        """구매 확정 활동 로그"""
        metadata = {
            'job_no': job_no,
            'revision': revision,
            'confirmed_count': confirmed_count,
            'total_amount': total_amount,
            'confirm_time': datetime.now().isoformat()
        }
        
        return self.log_activity(
            username=username,
            activity_type='PURCHASE_CONFIRM',
            activity_description=f'구매 확정: {confirmed_count}개 품목 (Job: {job_no}, Rev: {revision})',
            target_id=None,  # 구매는 특정 ID가 없음
            target_type='PURCHASE',
            user_id=user_id,
            ip_address=ip_address,
            user_agent=user_agent,
            metadata=metadata
        )
    
    def get_user_activities(
        self,
        username: str,
        activity_type: Optional[str] = None,
        limit: int = 50,
        offset: int = 0
    ) -> list:
        """사용자 활동 이력 조회"""
        try:
            where_clause = "WHERE username = :username"
            params = {'username': username}
            
            if activity_type:
                where_clause += " AND activity_type = :activity_type"
                params['activity_type'] = activity_type
            
            query = text(f"""
                SELECT 
                    id, activity_type, activity_description,
                    target_id, target_type, metadata, created_at
                FROM user_activity_logs
                {where_clause}
                ORDER BY created_at DESC
                LIMIT :limit OFFSET :offset
            """)
            
            params.update({'limit': limit, 'offset': offset})
            result = self.db.execute(query, params)
            
            activities = []
            for row in result.fetchall():
                activity = {
                    'id': row[0],
                    'activity_type': row[1],
                    'activity_description': row[2],
                    'target_id': row[3],
                    'target_type': row[4],
                    'metadata': json.loads(row[5]) if row[5] else {},
                    'created_at': row[6].isoformat() if row[6] else None
                }
                activities.append(activity)
            
            return activities
            
        except Exception as e:
            logger.error(f"Failed to get user activities: {str(e)}")
            return []
    
    def get_recent_activities(
        self,
        days: int = 7,
        limit: int = 100
    ) -> list:
        """최근 활동 조회 (전체 사용자)"""
        try:
            query = text("""
                SELECT 
                    username, activity_type, activity_description,
                    target_id, target_type, created_at
                FROM user_activity_logs
                WHERE created_at >= CURRENT_TIMESTAMP - INTERVAL '%s days'
                ORDER BY created_at DESC
                LIMIT :limit
            """ % days)
            
            result = self.db.execute(query, {'limit': limit})
            
            activities = []
            for row in result.fetchall():
                activity = {
                    'username': row[0],
                    'activity_type': row[1],
                    'activity_description': row[2],
                    'target_id': row[3],
                    'target_type': row[4],
                    'created_at': row[5].isoformat() if row[5] else None
                }
                activities.append(activity)
            
            return activities
            
        except Exception as e:
            logger.error(f"Failed to get recent activities: {str(e)}")
            return []


def get_client_info(request: Request) -> tuple:
    """
    요청에서 클라이언트 정보 추출
    
    Args:
        request: FastAPI Request 객체
        
    Returns:
        tuple: (ip_address, user_agent)
    """
    # IP 주소 추출 (프록시 고려)
    ip_address = (
        request.headers.get('x-forwarded-for', '').split(',')[0].strip() or
        request.headers.get('x-real-ip', '') or
        request.client.host if request.client else 'unknown'
    )
    
    # User-Agent 추출
    user_agent = request.headers.get('user-agent', 'unknown')
    
    return ip_address, user_agent


def log_activity_from_request(
    db: Session,
    request: Request,
    username: str,
    activity_type: str,
    activity_description: str,
    target_id: Optional[int] = None,
    target_type: Optional[str] = None,
    user_id: Optional[int] = None,
    metadata: Optional[Dict[str, Any]] = None
) -> int:
    """
    요청 정보를 포함한 활동 로그 기록 (편의 함수)
    
    Args:
        db: 데이터베이스 세션
        request: FastAPI Request 객체
        username: 사용자명
        activity_type: 활동 유형
        activity_description: 활동 설명
        target_id: 대상 ID
        target_type: 대상 유형
        user_id: 사용자 ID
        metadata: 추가 메타데이터
        
    Returns:
        int: 생성된 로그 ID
    """
    ip_address, user_agent = get_client_info(request)
    
    activity_logger = ActivityLogger(db)
    return activity_logger.log_activity(
        username=username,
        activity_type=activity_type,
        activity_description=activity_description,
        target_id=target_id,
        target_type=target_type,
        user_id=user_id,
        ip_address=ip_address,
        user_agent=user_agent,
        metadata=metadata
    )
