"""
구매 추적 및 관리 API
엑셀 내보내기 이력 및 구매 상태 관리
"""
from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy import text
from sqlalchemy.orm import Session
from typing import Optional, List, Dict, Any
from datetime import datetime, date
import json

from ..database import get_db
from ..auth.middleware import get_current_user
from ..utils.logger import get_logger

logger = get_logger(__name__)

router = APIRouter(prefix="/purchase", tags=["Purchase Tracking"])


@router.post("/export-history")
async def create_export_history(
    file_id: int,
    job_no: Optional[str] = None,
    export_type: str = "full",
    category: Optional[str] = None,
    material_ids: List[int] = [],
    filters_applied: Optional[Dict] = None,
    current_user: dict = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """
    엑셀 내보내기 이력 생성 및 자재 추적
    """
    try:
        # 내보내기 이력 생성
        insert_history = text("""
            INSERT INTO excel_export_history (
                file_id, job_no, exported_by, export_type, 
                category, material_count, filters_applied
            ) VALUES (
                :file_id, :job_no, :exported_by, :export_type,
                :category, :material_count, :filters_applied
            ) RETURNING export_id
        """)
        
        result = db.execute(insert_history, {
            "file_id": file_id,
            "job_no": job_no,
            "exported_by": current_user.get("user_id"),
            "export_type": export_type,
            "category": category,
            "material_count": len(material_ids),
            "filters_applied": json.dumps(filters_applied) if filters_applied else None
        })
        
        export_id = result.fetchone().export_id
        
        # 내보낸 자재들 기록
        if material_ids:
            for material_id in material_ids:
                insert_material = text("""
                    INSERT INTO exported_materials (
                        export_id, material_id, purchase_status
                    ) VALUES (
                        :export_id, :material_id, 'pending'
                    )
                """)
                db.execute(insert_material, {
                    "export_id": export_id,
                    "material_id": material_id
                })
        
        db.commit()
        
        logger.info(f"Export history created: {export_id} with {len(material_ids)} materials")
        
        return {
            "success": True,
            "export_id": export_id,
            "message": f"{len(material_ids)}개 자재의 내보내기 이력이 저장되었습니다"
        }
        
    except Exception as e:
        db.rollback()
        logger.error(f"Failed to create export history: {str(e)}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"내보내기 이력 생성 실패: {str(e)}"
        )


@router.get("/export-history")
async def get_export_history(
    file_id: Optional[int] = None,
    job_no: Optional[str] = None,
    limit: int = 50,
    current_user: dict = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """
    엑셀 내보내기 이력 조회
    """
    try:
        query = text("""
            SELECT 
                eeh.export_id,
                eeh.file_id,
                eeh.job_no,
                eeh.export_date,
                eeh.export_type,
                eeh.category,
                eeh.material_count,
                u.name as exported_by_name,
                f.original_filename,
                COUNT(DISTINCT em.material_id) as actual_material_count,
                COUNT(DISTINCT CASE WHEN em.purchase_status = 'pending' THEN em.material_id END) as pending_count,
                COUNT(DISTINCT CASE WHEN em.purchase_status = 'requested' THEN em.material_id END) as requested_count,
                COUNT(DISTINCT CASE WHEN em.purchase_status = 'ordered' THEN em.material_id END) as ordered_count,
                COUNT(DISTINCT CASE WHEN em.purchase_status = 'received' THEN em.material_id END) as received_count
            FROM excel_export_history eeh
            LEFT JOIN users u ON eeh.exported_by = u.user_id
            LEFT JOIN files f ON eeh.file_id = f.id
            LEFT JOIN exported_materials em ON eeh.export_id = em.export_id
            WHERE 1=1
                AND (:file_id IS NULL OR eeh.file_id = :file_id)
                AND (:job_no IS NULL OR eeh.job_no = :job_no)
            GROUP BY 
                eeh.export_id, eeh.file_id, eeh.job_no, eeh.export_date,
                eeh.export_type, eeh.category, eeh.material_count,
                u.name, f.original_filename
            ORDER BY eeh.export_date DESC
            LIMIT :limit
        """)
        
        results = db.execute(query, {
            "file_id": file_id,
            "job_no": job_no,
            "limit": limit
        }).fetchall()
        
        history = []
        for row in results:
            history.append({
                "export_id": row.export_id,
                "file_id": row.file_id,
                "job_no": row.job_no,
                "export_date": row.export_date.isoformat() if row.export_date else None,
                "export_type": row.export_type,
                "category": row.category,
                "material_count": row.material_count,
                "exported_by": row.exported_by_name,
                "file_name": row.original_filename,
                "status_summary": {
                    "total": row.actual_material_count,
                    "pending": row.pending_count,
                    "requested": row.requested_count,
                    "ordered": row.ordered_count,
                    "received": row.received_count
                }
            })
        
        return {
            "success": True,
            "history": history,
            "count": len(history)
        }
        
    except Exception as e:
        logger.error(f"Failed to get export history: {str(e)}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"내보내기 이력 조회 실패: {str(e)}"
        )


@router.get("/materials/status")
async def get_materials_by_status(
    status: Optional[str] = None,
    export_id: Optional[int] = None,
    file_id: Optional[int] = None,
    current_user: dict = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """
    구매 상태별 자재 목록 조회
    """
    try:
        query = text("""
            SELECT 
                em.id as exported_material_id,
                em.material_id,
                m.original_description,
                m.classified_category,
                m.quantity,
                m.unit,
                em.purchase_status,
                em.purchase_request_no,
                em.purchase_order_no,
                em.vendor_name,
                em.expected_date,
                em.quantity_ordered,
                em.quantity_received,
                em.unit_price,
                em.total_price,
                em.notes,
                em.updated_at,
                eeh.export_date,
                f.original_filename as file_name,
                j.job_no,
                j.job_name
            FROM exported_materials em
            JOIN materials m ON em.material_id = m.id
            JOIN excel_export_history eeh ON em.export_id = eeh.export_id
            LEFT JOIN files f ON eeh.file_id = f.id
            LEFT JOIN jobs j ON eeh.job_no = j.job_no
            WHERE 1=1
                AND (:status IS NULL OR em.purchase_status = :status)
                AND (:export_id IS NULL OR em.export_id = :export_id)
                AND (:file_id IS NULL OR eeh.file_id = :file_id)
            ORDER BY em.updated_at DESC
        """)
        
        results = db.execute(query, {
            "status": status,
            "export_id": export_id,
            "file_id": file_id
        }).fetchall()
        
        materials = []
        for row in results:
            materials.append({
                "exported_material_id": row.exported_material_id,
                "material_id": row.material_id,
                "description": row.original_description,
                "category": row.classified_category,
                "quantity": row.quantity,
                "unit": row.unit,
                "purchase_status": row.purchase_status,
                "purchase_request_no": row.purchase_request_no,
                "purchase_order_no": row.purchase_order_no,
                "vendor_name": row.vendor_name,
                "expected_date": row.expected_date.isoformat() if row.expected_date else None,
                "quantity_ordered": row.quantity_ordered,
                "quantity_received": row.quantity_received,
                "unit_price": float(row.unit_price) if row.unit_price else None,
                "total_price": float(row.total_price) if row.total_price else None,
                "notes": row.notes,
                "updated_at": row.updated_at.isoformat() if row.updated_at else None,
                "export_date": row.export_date.isoformat() if row.export_date else None,
                "file_name": row.file_name,
                "job_no": row.job_no,
                "job_name": row.job_name
            })
        
        return {
            "success": True,
            "materials": materials,
            "count": len(materials)
        }
        
    except Exception as e:
        logger.error(f"Failed to get materials by status: {str(e)}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"구매 상태별 자재 조회 실패: {str(e)}"
        )


@router.patch("/materials/{exported_material_id}/status")
async def update_purchase_status(
    exported_material_id: int,
    new_status: str,
    purchase_request_no: Optional[str] = None,
    purchase_order_no: Optional[str] = None,
    vendor_name: Optional[str] = None,
    expected_date: Optional[date] = None,
    quantity_ordered: Optional[int] = None,
    quantity_received: Optional[int] = None,
    unit_price: Optional[float] = None,
    notes: Optional[str] = None,
    current_user: dict = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """
    자재 구매 상태 업데이트
    """
    try:
        # 현재 상태 조회
        get_current = text("""
            SELECT purchase_status, material_id 
            FROM exported_materials 
            WHERE id = :id
        """)
        current = db.execute(get_current, {"id": exported_material_id}).fetchone()
        
        if not current:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="해당 자재를 찾을 수 없습니다"
            )
        
        # 상태 업데이트
        update_query = text("""
            UPDATE exported_materials
            SET 
                purchase_status = :new_status,
                purchase_request_no = COALESCE(:pr_no, purchase_request_no),
                purchase_order_no = COALESCE(:po_no, purchase_order_no),
                vendor_name = COALESCE(:vendor, vendor_name),
                expected_date = COALESCE(:expected_date, expected_date),
                quantity_ordered = COALESCE(:qty_ordered, quantity_ordered),
                quantity_received = COALESCE(:qty_received, quantity_received),
                unit_price = COALESCE(:unit_price, unit_price),
                total_price = CASE 
                    WHEN :unit_price IS NOT NULL AND :qty_ordered IS NOT NULL 
                    THEN :unit_price * :qty_ordered
                    WHEN :unit_price IS NOT NULL AND quantity_ordered IS NOT NULL
                    THEN :unit_price * quantity_ordered
                    ELSE total_price
                END,
                notes = COALESCE(:notes, notes),
                updated_by = :updated_by,
                requested_date = CASE WHEN :new_status = 'requested' THEN CURRENT_TIMESTAMP ELSE requested_date END,
                ordered_date = CASE WHEN :new_status = 'ordered' THEN CURRENT_TIMESTAMP ELSE ordered_date END,
                received_date = CASE WHEN :new_status = 'received' THEN CURRENT_TIMESTAMP ELSE received_date END
            WHERE id = :id
        """)
        
        db.execute(update_query, {
            "id": exported_material_id,
            "new_status": new_status,
            "pr_no": purchase_request_no,
            "po_no": purchase_order_no,
            "vendor": vendor_name,
            "expected_date": expected_date,
            "qty_ordered": quantity_ordered,
            "qty_received": quantity_received,
            "unit_price": unit_price,
            "notes": notes,
            "updated_by": current_user.get("user_id")
        })
        
        # 이력 기록
        insert_history = text("""
            INSERT INTO purchase_status_history (
                exported_material_id, material_id, 
                previous_status, new_status, 
                changed_by, reason
            ) VALUES (
                :em_id, :material_id,
                :prev_status, :new_status,
                :changed_by, :reason
            )
        """)
        
        db.execute(insert_history, {
            "em_id": exported_material_id,
            "material_id": current.material_id,
            "prev_status": current.purchase_status,
            "new_status": new_status,
            "changed_by": current_user.get("user_id"),
            "reason": notes
        })
        
        db.commit()
        
        logger.info(f"Purchase status updated: {exported_material_id} from {current.purchase_status} to {new_status}")
        
        return {
            "success": True,
            "message": f"구매 상태가 {new_status}로 변경되었습니다"
        }
        
    except HTTPException:
        raise
    except Exception as e:
        db.rollback()
        logger.error(f"Failed to update purchase status: {str(e)}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"구매 상태 업데이트 실패: {str(e)}"
        )


@router.get("/status-summary")
async def get_status_summary(
    file_id: Optional[int] = None,
    job_no: Optional[str] = None,
    current_user: dict = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """
    구매 상태 요약 통계
    """
    try:
        query = text("""
            SELECT 
                em.purchase_status,
                COUNT(DISTINCT em.material_id) as material_count,
                SUM(em.quantity_exported) as total_quantity,
                SUM(em.total_price) as total_amount,
                COUNT(DISTINCT em.export_id) as export_count
            FROM exported_materials em
            JOIN excel_export_history eeh ON em.export_id = eeh.export_id
            WHERE 1=1
                AND (:file_id IS NULL OR eeh.file_id = :file_id)
                AND (:job_no IS NULL OR eeh.job_no = :job_no)
            GROUP BY em.purchase_status
        """)
        
        results = db.execute(query, {
            "file_id": file_id,
            "job_no": job_no
        }).fetchall()
        
        summary = {}
        total_materials = 0
        total_amount = 0
        
        for row in results:
            summary[row.purchase_status] = {
                "material_count": row.material_count,
                "total_quantity": row.total_quantity,
                "total_amount": float(row.total_amount) if row.total_amount else 0,
                "export_count": row.export_count
            }
            total_materials += row.material_count
            if row.total_amount:
                total_amount += float(row.total_amount)
        
        # 기본 상태들 추가 (없는 경우 0으로)
        for status in ['pending', 'requested', 'ordered', 'received', 'cancelled']:
            if status not in summary:
                summary[status] = {
                    "material_count": 0,
                    "total_quantity": 0,
                    "total_amount": 0,
                    "export_count": 0
                }
        
        return {
            "success": True,
            "summary": summary,
            "total_materials": total_materials,
            "total_amount": total_amount
        }
        
    except Exception as e:
        logger.error(f"Failed to get status summary: {str(e)}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"구매 상태 요약 조회 실패: {str(e)}"
        )
