"""
리비전 자재 처리 전용 서비스
구매 상태별 자재 처리 로직
"""

from sqlalchemy.orm import Session
from sqlalchemy import text
from typing import List, Dict, Any, Optional
from decimal import Decimal
from datetime import datetime

from ..models import Material, File
from ..utils.logger import get_logger
from .database_service import DatabaseService

logger = get_logger(__name__)


class RevisionMaterialService:
    """리비전 자재 처리 전용 서비스"""
    
    def __init__(self, db: Session):
        self.db = db
        self.db_service = DatabaseService(db)
    
    def process_material_by_purchase_status(
        self,
        prev_material: Dict,
        curr_material: Dict,
        category: str
    ) -> Dict[str, Any]:
        """
        구매 상태별 자재 처리
        
        Args:
            prev_material: 이전 리비전 자재
            curr_material: 현재 리비전 자재
            category: 자재 카테고리
            
        Returns:
            처리 결과
        """
        
        # 수량 변화 계산
        quantity_change = self._calculate_quantity_change(prev_material, curr_material, category)
        
        # 구매 완료 자재 처리
        if prev_material.get('purchase_confirmed', False):
            return self._process_purchased_material(prev_material, curr_material, quantity_change, category)
        else:
            # 구매 미완료 자재 처리
            return self._process_unpurchased_material(prev_material, curr_material, quantity_change, category)
    
    def process_new_material(self, material: Dict, category: str) -> Dict[str, Any]:
        """신규 자재 처리"""
        
        return {
            'material_id': material['id'],
            'category': category,
            'action': 'new_material',
            'status': 'needs_purchase',
            'quantity': material.get('quantity', 0),
            'description': material.get('original_description', ''),
            'processing_note': '신규 자재 - 구매 필요',
            'ui_display': {
                'show_in_revision_page': True,
                'highlight_color': 'green',
                'action_required': '구매 신청',
                'badge': 'NEW'
            }
        }
    
    def process_removed_material(self, material: Dict, category: str) -> Dict[str, Any]:
        """제거된 자재 처리"""
        
        if material.get('purchase_confirmed', False):
            # 구매 완료된 자재가 제거됨 → 재고로 분류
            return {
                'material_id': material['id'],
                'category': category,
                'action': 'move_to_inventory',
                'status': 'excess_inventory',
                'quantity': material.get('quantity', 0),
                'description': material.get('original_description', ''),
                'processing_note': '구매 완료 후 리비전에서 제거됨 - 재고 보관',
                'ui_display': {
                    'show_in_revision_page': True,
                    'highlight_color': 'orange',
                    'action_required': '재고 관리',
                    'badge': 'INVENTORY'
                }
            }
        else:
            # 구매 미완료 자재가 제거됨 → 완전 삭제
            return {
                'material_id': material['id'],
                'category': category,
                'action': 'delete',
                'status': 'deleted',
                'quantity': material.get('quantity', 0),
                'description': material.get('original_description', ''),
                'processing_note': '리비전에서 제거됨 - 구매 불필요',
                'ui_display': {
                    'show_in_revision_page': False,  # 삭제된 자재는 표시 안함
                    'highlight_color': 'red',
                    'action_required': '삭제 완료',
                    'badge': 'DELETED'
                }
            }
    
    def _process_purchased_material(
        self,
        prev_material: Dict,
        curr_material: Dict,
        quantity_change: Dict,
        category: str
    ) -> Dict[str, Any]:
        """구매 완료 자재 처리"""
        
        if quantity_change['change_type'] == 'no_change':
            # 변동 없음 → 구매 완료 상태 유지
            return {
                'material_id': curr_material['id'],
                'category': category,
                'action': 'maintain_status',
                'status': 'purchased_completed',
                'quantity': curr_material.get('quantity', 0),
                'description': curr_material.get('original_description', ''),
                'processing_note': '구매 완료 - 변동 없음',
                'ui_display': {
                    'show_in_revision_page': False,  # 변동 없는 구매완료 자재는 숨김
                    'highlight_color': 'gray',
                    'action_required': '관리 불필요',
                    'badge': 'COMPLETED'
                }
            }
        
        elif quantity_change['change_type'] == 'decreased':
            # 수량 감소 → 재고 자재로 분류
            excess_quantity = abs(quantity_change['quantity_change'])
            return {
                'material_id': curr_material['id'],
                'category': category,
                'action': 'partial_inventory',
                'status': 'excess_inventory',
                'quantity': curr_material.get('quantity', 0),
                'excess_quantity': excess_quantity,
                'purchased_quantity': prev_material.get('quantity', 0),
                'description': curr_material.get('original_description', ''),
                'processing_note': f'구매 완료 후 수량 감소 - 잉여 {excess_quantity}개 재고 보관',
                'ui_display': {
                    'show_in_revision_page': True,
                    'highlight_color': 'orange',
                    'action_required': '잉여 재고 관리',
                    'badge': 'EXCESS'
                }
            }
        
        else:  # increased
            # 수량 부족 → 추가 구매 필요
            additional_needed = quantity_change['quantity_change']
            return {
                'material_id': curr_material['id'],
                'category': category,
                'action': 'additional_purchase',
                'status': 'needs_additional_purchase',
                'quantity': curr_material.get('quantity', 0),
                'additional_needed': additional_needed,
                'already_purchased': prev_material.get('quantity', 0),
                'description': curr_material.get('original_description', ''),
                'processing_note': f'구매 완료 후 수량 부족 - 추가 {additional_needed}개 구매 필요',
                'ui_display': {
                    'show_in_revision_page': True,
                    'highlight_color': 'red',
                    'action_required': '추가 구매 신청',
                    'badge': 'ADDITIONAL'
                }
            }
    
    def _process_unpurchased_material(
        self,
        prev_material: Dict,
        curr_material: Dict,
        quantity_change: Dict,
        category: str
    ) -> Dict[str, Any]:
        """구매 미완료 자재 처리"""
        
        if quantity_change['change_type'] == 'no_change':
            # 수량 동일 → 구매 관리 계속
            return {
                'material_id': curr_material['id'],
                'category': category,
                'action': 'continue_purchase',
                'status': 'pending_purchase',
                'quantity': curr_material.get('quantity', 0),
                'description': curr_material.get('original_description', ''),
                'processing_note': '수량 변동 없음 - 구매 진행',
                'ui_display': {
                    'show_in_revision_page': True,
                    'highlight_color': 'blue',
                    'action_required': '구매 신청',
                    'badge': 'PENDING'
                }
            }
        
        else:
            # 수량 변경 → 수량 업데이트 후 구매 관리
            return {
                'material_id': curr_material['id'],
                'category': category,
                'action': 'update_quantity',
                'status': 'quantity_updated',
                'quantity': curr_material.get('quantity', 0),
                'previous_quantity': prev_material.get('quantity', 0),
                'quantity_change': quantity_change['quantity_change'],
                'description': curr_material.get('original_description', ''),
                'processing_note': f'수량 변경: {prev_material.get("quantity", 0)} → {curr_material.get("quantity", 0)}',
                'ui_display': {
                    'show_in_revision_page': True,
                    'highlight_color': 'yellow',
                    'action_required': '수량 확인 후 구매 신청',
                    'badge': 'UPDATED'
                }
            }
    
    def _calculate_quantity_change(
        self,
        prev_material: Dict,
        curr_material: Dict,
        category: str
    ) -> Dict[str, Any]:
        """수량 변화 계산"""
        
        # GASKET, BOLT는 규칙 적용 전 수량으로 비교
        if category in ['GASKET', 'BOLT']:
            prev_qty = float(prev_material.get('original_quantity', prev_material.get('quantity', 0)))
            curr_qty = float(curr_material.get('original_quantity', curr_material.get('quantity', 0)))
        else:
            prev_qty = float(prev_material.get('quantity', 0))
            curr_qty = float(curr_material.get('quantity', 0))
        
        quantity_change = curr_qty - prev_qty
        
        if abs(quantity_change) < 0.001:  # 부동소수점 오차 고려
            change_type = 'no_change'
        elif quantity_change > 0:
            change_type = 'increased'
        else:
            change_type = 'decreased'
        
        return {
            'previous_quantity': prev_qty,
            'current_quantity': curr_qty,
            'quantity_change': quantity_change,
            'change_type': change_type,
            'is_gasket_bolt': category in ['GASKET', 'BOLT']
        }
    
    def get_category_materials_for_revision(
        self,
        file_id: int,
        category: str,
        include_processing_info: bool = True
    ) -> List[Dict[str, Any]]:
        """
        리비전 페이지용 카테고리별 자재 조회
        
        Args:
            file_id: 파일 ID
            category: 카테고리
            include_processing_info: 처리 정보 포함 여부
            
        Returns:
            자재 목록 (처리 정보 포함)
        """
        
        query = """
            SELECT 
                m.id, m.original_description, m.classified_category,
                m.material_grade, m.schedule, m.size_spec, m.main_nom, m.red_nom,
                m.quantity, m.unit, m.length, m.drawing_name, m.line_no,
                m.purchase_confirmed, m.confirmed_quantity, m.purchase_status,
                m.material_hash, m.revision_status, m.brand, m.user_requirement,
                m.line_number, m.is_active, m.notes,
                -- 추가 정보
                COALESCE(m.purchase_confirmed_at, m.created_at) as status_date,
                COALESCE(m.purchase_confirmed_by, 'system') as status_by
            FROM materials m
            WHERE m.file_id = :file_id 
              AND m.classified_category = :category 
              AND m.classified_category != 'PIPE'
              AND m.is_active = true
            ORDER BY m.line_number
        """
        
        result = self.db_service.execute_query(query, {
            "file_id": file_id,
            "category": category
        })
        
        materials = []
        for row in result.fetchall():
            material_dict = dict(row._mapping)
            
            if include_processing_info:
                # 처리 정보 추가
                material_dict['processing_info'] = self._get_material_processing_info(material_dict)
            
            materials.append(material_dict)
        
        return materials
    
    def _get_material_processing_info(self, material: Dict) -> Dict[str, Any]:
        """자재 처리 정보 생성"""
        
        revision_status = material.get('revision_status', '')
        purchase_confirmed = material.get('purchase_confirmed', False)
        
        if revision_status == 'new_in_revision':
            return {
                'display_status': 'NEW',
                'color': 'green',
                'action': '신규 구매 필요',
                'priority': 'high'
            }
        elif revision_status == 'additional_purchase_needed':
            return {
                'display_status': 'ADDITIONAL',
                'color': 'red',
                'action': '추가 구매 필요',
                'priority': 'high'
            }
        elif revision_status == 'excess_inventory':
            return {
                'display_status': 'EXCESS',
                'color': 'orange',
                'action': '재고 관리',
                'priority': 'medium'
            }
        elif revision_status == 'quantity_updated':
            return {
                'display_status': 'UPDATED',
                'color': 'yellow',
                'action': '수량 확인',
                'priority': 'medium'
            }
        elif purchase_confirmed:
            return {
                'display_status': 'COMPLETED',
                'color': 'gray',
                'action': '완료',
                'priority': 'low'
            }
        else:
            return {
                'display_status': 'PENDING',
                'color': 'blue',
                'action': '구매 대기',
                'priority': 'medium'
            }
    
    def apply_material_processing_results(
        self,
        processing_results: List[Dict[str, Any]]
    ) -> Dict[str, Any]:
        """자재 처리 결과를 DB에 적용"""
        
        try:
            applied_count = 0
            error_count = 0
            
            for result in processing_results:
                try:
                    material_id = result['material_id']
                    action = result['action']
                    status = result['status']
                    
                    if action == 'delete':
                        # 자재 비활성화
                        update_query = """
                            UPDATE materials 
                            SET is_active = false,
                                revision_status = 'deleted',
                                notes = CONCAT(COALESCE(notes, ''), '\n', :note)
                            WHERE id = :material_id
                        """
                    else:
                        # 자재 상태 업데이트
                        update_query = """
                            UPDATE materials 
                            SET revision_status = :status,
                                notes = CONCAT(COALESCE(notes, ''), '\n', :note)
                            WHERE id = :material_id
                        """
                    
                    self.db_service.execute_query(update_query, {
                        "material_id": material_id,
                        "status": status,
                        "note": result.get('processing_note', '')
                    })
                    
                    applied_count += 1
                    
                except Exception as e:
                    logger.error(f"Failed to apply processing result for material {result.get('material_id')}: {e}")
                    error_count += 1
            
            self.db.commit()
            
            return {
                "success": True,
                "applied_count": applied_count,
                "error_count": error_count,
                "message": f"자재 처리 완료: {applied_count}개 적용, {error_count}개 오류"
            }
            
        except Exception as e:
            self.db.rollback()
            logger.error(f"Failed to apply material processing results: {e}")
            return {
                "success": False,
                "error": str(e),
                "message": "자재 처리 적용 중 오류 발생"
            }
