"""
PIPE 이슈 관리 API 라우터

스냅샷 기반 도면별/단관별 이슈 관리 기능
"""

import logging
from typing import Dict, List, Optional, Any
from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.orm import Session
from pydantic import BaseModel
from datetime import datetime

from ..database import get_db
from ..models import (
    PipeIssueSnapshot, PipeIssueSegment, 
    PipeDrawingIssue, PipeSegmentIssue
)

logger = logging.getLogger(__name__)

router = APIRouter(prefix="/pipe-issue", tags=["pipe-issue"])


# Pydantic 모델들
class CreateDrawingIssueRequest(BaseModel):
    snapshot_id: int
    area: str
    drawing_name: str
    issue_description: str
    severity: str = 'medium'  # low, medium, high, critical
    reported_by: Optional[str] = 'user'


class CreateSegmentIssueRequest(BaseModel):
    snapshot_id: int
    segment_id: int
    issue_description: str
    issue_type: Optional[str] = 'other'  # cutting, installation, material, routing, other
    length_change: Optional[float] = None
    new_length: Optional[float] = None
    material_change: Optional[str] = None
    severity: str = 'medium'
    reported_by: Optional[str] = 'user'


class UpdateIssueStatusRequest(BaseModel):
    status: str  # open, in_progress, resolved
    resolution_notes: Optional[str] = None
    resolved_by: Optional[str] = None


class DrawingIssueResponse(BaseModel):
    id: int
    snapshot_id: int
    area: str
    drawing_name: str
    issue_description: str
    severity: str
    status: str
    resolution_notes: Optional[str] = None
    resolved_by: Optional[str] = None
    resolved_at: Optional[str] = None
    reported_by: Optional[str] = None
    reported_at: str
    updated_at: str


class SegmentIssueResponse(BaseModel):
    id: int
    snapshot_id: int
    segment_id: int
    issue_description: str
    issue_type: Optional[str] = None
    length_change: Optional[float] = None
    new_length: Optional[float] = None
    material_change: Optional[str] = None
    severity: str
    status: str
    resolution_notes: Optional[str] = None
    resolved_by: Optional[str] = None
    resolved_at: Optional[str] = None
    reported_by: Optional[str] = None
    reported_at: str
    updated_at: str


@router.get("/snapshots/{job_no}")
async def get_job_snapshots(
    job_no: str,
    db: Session = Depends(get_db)
):
    """작업의 활성 스냅샷 조회"""
    try:
        snapshots = db.query(PipeIssueSnapshot).filter(
            PipeIssueSnapshot.job_no == job_no,
            PipeIssueSnapshot.is_active == True
        ).all()
        
        result = []
        for snapshot in snapshots:
            result.append({
                "snapshot_id": snapshot.id,
                "snapshot_name": snapshot.snapshot_name,
                "is_locked": snapshot.is_locked,
                "total_segments": snapshot.total_segments,
                "total_drawings": snapshot.total_drawings,
                "created_at": snapshot.created_at.isoformat() if snapshot.created_at else None,
                "locked_at": snapshot.locked_at.isoformat() if snapshot.locked_at else None
            })
        
        return {
            "job_no": job_no,
            "snapshots": result,
            "total_count": len(result)
        }
        
    except Exception as e:
        logger.error(f"Failed to get job snapshots: {e}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"스냅샷 조회 실패: {str(e)}"
        )


@router.get("/drawing-issues/{snapshot_id}")
async def get_drawing_issues(
    snapshot_id: int,
    area: Optional[str] = None,
    drawing_name: Optional[str] = None,
    status_filter: Optional[str] = None,
    db: Session = Depends(get_db)
):
    """도면 이슈 목록 조회"""
    try:
        query = db.query(PipeDrawingIssue).filter(
            PipeDrawingIssue.snapshot_id == snapshot_id
        )
        
        if area:
            query = query.filter(PipeDrawingIssue.area == area)
        
        if drawing_name:
            query = query.filter(PipeDrawingIssue.drawing_name == drawing_name)
        
        if status_filter:
            query = query.filter(PipeDrawingIssue.status == status_filter)
        
        issues = query.order_by(PipeDrawingIssue.reported_at.desc()).all()
        
        result = []
        for issue in issues:
            result.append(DrawingIssueResponse(
                id=issue.id,
                snapshot_id=issue.snapshot_id,
                area=issue.area,
                drawing_name=issue.drawing_name,
                issue_description=issue.issue_description,
                severity=issue.severity,
                status=issue.status,
                resolution_notes=issue.resolution_notes,
                resolved_by=issue.resolved_by,
                resolved_at=issue.resolved_at.isoformat() if issue.resolved_at else None,
                reported_by=issue.reported_by,
                reported_at=issue.reported_at.isoformat() if issue.reported_at else '',
                updated_at=issue.updated_at.isoformat() if issue.updated_at else ''
            ))
        
        return {
            "snapshot_id": snapshot_id,
            "issues": result,
            "total_count": len(result)
        }
        
    except Exception as e:
        logger.error(f"Failed to get drawing issues: {e}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"도면 이슈 조회 실패: {str(e)}"
        )


@router.post("/drawing-issues", response_model=DrawingIssueResponse)
async def create_drawing_issue(
    request: CreateDrawingIssueRequest,
    db: Session = Depends(get_db)
):
    """도면 이슈 생성"""
    try:
        # 스냅샷 존재 확인
        snapshot = db.query(PipeIssueSnapshot).filter(
            PipeIssueSnapshot.id == request.snapshot_id
        ).first()
        
        if not snapshot:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="스냅샷을 찾을 수 없습니다."
            )
        
        # 이슈 생성
        issue = PipeDrawingIssue(
            snapshot_id=request.snapshot_id,
            area=request.area,
            drawing_name=request.drawing_name,
            issue_description=request.issue_description,
            severity=request.severity,
            reported_by=request.reported_by
        )
        
        db.add(issue)
        db.commit()
        db.refresh(issue)
        
        return DrawingIssueResponse(
            id=issue.id,
            snapshot_id=issue.snapshot_id,
            area=issue.area,
            drawing_name=issue.drawing_name,
            issue_description=issue.issue_description,
            severity=issue.severity,
            status=issue.status,
            resolution_notes=issue.resolution_notes,
            resolved_by=issue.resolved_by,
            resolved_at=issue.resolved_at.isoformat() if issue.resolved_at else None,
            reported_by=issue.reported_by,
            reported_at=issue.reported_at.isoformat() if issue.reported_at else '',
            updated_at=issue.updated_at.isoformat() if issue.updated_at else ''
        )
        
    except HTTPException:
        raise
    except Exception as e:
        db.rollback()
        logger.error(f"Failed to create drawing issue: {e}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"도면 이슈 생성 실패: {str(e)}"
        )


@router.get("/segment-issues/{snapshot_id}")
async def get_segment_issues(
    snapshot_id: int,
    segment_id: Optional[int] = None,
    status_filter: Optional[str] = None,
    db: Session = Depends(get_db)
):
    """단관 이슈 목록 조회"""
    try:
        query = db.query(PipeSegmentIssue).filter(
            PipeSegmentIssue.snapshot_id == snapshot_id
        )
        
        if segment_id:
            query = query.filter(PipeSegmentIssue.segment_id == segment_id)
        
        if status_filter:
            query = query.filter(PipeSegmentIssue.status == status_filter)
        
        issues = query.order_by(PipeSegmentIssue.reported_at.desc()).all()
        
        result = []
        for issue in issues:
            result.append(SegmentIssueResponse(
                id=issue.id,
                snapshot_id=issue.snapshot_id,
                segment_id=issue.segment_id,
                issue_description=issue.issue_description,
                issue_type=issue.issue_type,
                length_change=float(issue.length_change) if issue.length_change else None,
                new_length=float(issue.new_length) if issue.new_length else None,
                material_change=issue.material_change,
                severity=issue.severity,
                status=issue.status,
                resolution_notes=issue.resolution_notes,
                resolved_by=issue.resolved_by,
                resolved_at=issue.resolved_at.isoformat() if issue.resolved_at else None,
                reported_by=issue.reported_by,
                reported_at=issue.reported_at.isoformat() if issue.reported_at else '',
                updated_at=issue.updated_at.isoformat() if issue.updated_at else ''
            ))
        
        return {
            "snapshot_id": snapshot_id,
            "issues": result,
            "total_count": len(result)
        }
        
    except Exception as e:
        logger.error(f"Failed to get segment issues: {e}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"단관 이슈 조회 실패: {str(e)}"
        )


@router.post("/segment-issues", response_model=SegmentIssueResponse)
async def create_segment_issue(
    request: CreateSegmentIssueRequest,
    db: Session = Depends(get_db)
):
    """단관 이슈 생성"""
    try:
        # 단관 존재 확인
        segment = db.query(PipeIssueSegment).filter(
            PipeIssueSegment.id == request.segment_id
        ).first()
        
        if not segment:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="단관을 찾을 수 없습니다."
            )
        
        # 이슈 생성
        issue = PipeSegmentIssue(
            snapshot_id=request.snapshot_id,
            segment_id=request.segment_id,
            issue_description=request.issue_description,
            issue_type=request.issue_type,
            length_change=request.length_change,
            new_length=request.new_length,
            material_change=request.material_change,
            severity=request.severity,
            reported_by=request.reported_by
        )
        
        db.add(issue)
        db.commit()
        db.refresh(issue)
        
        return SegmentIssueResponse(
            id=issue.id,
            snapshot_id=issue.snapshot_id,
            segment_id=issue.segment_id,
            issue_description=issue.issue_description,
            issue_type=issue.issue_type,
            length_change=float(issue.length_change) if issue.length_change else None,
            new_length=float(issue.new_length) if issue.new_length else None,
            material_change=issue.material_change,
            severity=issue.severity,
            status=issue.status,
            resolution_notes=issue.resolution_notes,
            resolved_by=issue.resolved_by,
            resolved_at=issue.resolved_at.isoformat() if issue.resolved_at else None,
            reported_by=issue.reported_by,
            reported_at=issue.reported_at.isoformat() if issue.reported_at else '',
            updated_at=issue.updated_at.isoformat() if issue.updated_at else ''
        )
        
    except HTTPException:
        raise
    except Exception as e:
        db.rollback()
        logger.error(f"Failed to create segment issue: {e}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"단관 이슈 생성 실패: {str(e)}"
        )


@router.put("/drawing-issues/{issue_id}/status")
async def update_drawing_issue_status(
    issue_id: int,
    request: UpdateIssueStatusRequest,
    db: Session = Depends(get_db)
):
    """도면 이슈 상태 업데이트"""
    try:
        issue = db.query(PipeDrawingIssue).filter(
            PipeDrawingIssue.id == issue_id
        ).first()
        
        if not issue:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="이슈를 찾을 수 없습니다."
            )
        
        # 상태 업데이트
        issue.status = request.status
        if request.resolution_notes:
            issue.resolution_notes = request.resolution_notes
        if request.resolved_by:
            issue.resolved_by = request.resolved_by
        
        if request.status == 'resolved':
            issue.resolved_at = datetime.utcnow()
        
        db.commit()
        
        return {"message": "이슈 상태가 업데이트되었습니다.", "issue_id": issue_id}
        
    except HTTPException:
        raise
    except Exception as e:
        db.rollback()
        logger.error(f"Failed to update drawing issue status: {e}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"이슈 상태 업데이트 실패: {str(e)}"
        )


@router.put("/segment-issues/{issue_id}/status")
async def update_segment_issue_status(
    issue_id: int,
    request: UpdateIssueStatusRequest,
    db: Session = Depends(get_db)
):
    """단관 이슈 상태 업데이트"""
    try:
        issue = db.query(PipeSegmentIssue).filter(
            PipeSegmentIssue.id == issue_id
        ).first()
        
        if not issue:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="이슈를 찾을 수 없습니다."
            )
        
        # 상태 업데이트
        issue.status = request.status
        if request.resolution_notes:
            issue.resolution_notes = request.resolution_notes
        if request.resolved_by:
            issue.resolved_by = request.resolved_by
        
        if request.status == 'resolved':
            issue.resolved_at = datetime.utcnow()
        
        db.commit()
        
        return {"message": "이슈 상태가 업데이트되었습니다.", "issue_id": issue_id}
        
    except HTTPException:
        raise
    except Exception as e:
        db.rollback()
        logger.error(f"Failed to update segment issue status: {e}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"이슈 상태 업데이트 실패: {str(e)}"
        )


@router.get("/report/{snapshot_id}")
async def generate_issue_report(
    snapshot_id: int,
    db: Session = Depends(get_db)
):
    """이슈 리포트 생성"""
    try:
        # 스냅샷 정보
        snapshot = db.query(PipeIssueSnapshot).filter(
            PipeIssueSnapshot.id == snapshot_id
        ).first()
        
        if not snapshot:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="스냅샷을 찾을 수 없습니다."
            )
        
        # 도면 이슈 통계
        drawing_issues = db.query(PipeDrawingIssue).filter(
            PipeDrawingIssue.snapshot_id == snapshot_id
        ).all()
        
        # 단관 이슈 통계
        segment_issues = db.query(PipeSegmentIssue).filter(
            PipeSegmentIssue.snapshot_id == snapshot_id
        ).all()
        
        # 통계 계산
        drawing_stats = {
            "total": len(drawing_issues),
            "by_status": {},
            "by_severity": {},
            "by_area": {}
        }
        
        for issue in drawing_issues:
            # 상태별
            status = issue.status
            drawing_stats["by_status"][status] = drawing_stats["by_status"].get(status, 0) + 1
            
            # 심각도별
            severity = issue.severity
            drawing_stats["by_severity"][severity] = drawing_stats["by_severity"].get(severity, 0) + 1
            
            # 구역별
            area = issue.area
            drawing_stats["by_area"][area] = drawing_stats["by_area"].get(area, 0) + 1
        
        segment_stats = {
            "total": len(segment_issues),
            "by_status": {},
            "by_severity": {},
            "by_type": {}
        }
        
        for issue in segment_issues:
            # 상태별
            status = issue.status
            segment_stats["by_status"][status] = segment_stats["by_status"].get(status, 0) + 1
            
            # 심각도별
            severity = issue.severity
            segment_stats["by_severity"][severity] = segment_stats["by_severity"].get(severity, 0) + 1
            
            # 유형별
            issue_type = issue.issue_type or 'other'
            segment_stats["by_type"][issue_type] = segment_stats["by_type"].get(issue_type, 0) + 1
        
        return {
            "snapshot_id": snapshot_id,
            "snapshot_name": snapshot.snapshot_name,
            "job_no": snapshot.job_no,
            "report_generated_at": datetime.utcnow().isoformat(),
            "drawing_issues": drawing_stats,
            "segment_issues": segment_stats,
            "total_issues": len(drawing_issues) + len(segment_issues)
        }
        
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"Failed to generate issue report: {e}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"이슈 리포트 생성 실패: {str(e)}"
        )
