from dotenv import load_dotenv
load_dotenv()  # This loads variables from .env into os.environ
import os
import json
import logging
from typing import Dict, List, Optional, Any
from fastapi import FastAPI, HTTPException, Depends, Header, Request, BackgroundTasks
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import StreamingResponse
from pydantic import BaseModel, Field
from minaions_rfp_service import MinaionsRFPService
from bid_processing_apis import router as bid_processing_router
from location_finder_api import router as location_finder_router
import asyncio
import time

ANTHROPIC_API_KEY = os.getenv("ANTHROPIC_API_KEY")
ANTHROPIC_MODEL = os.getenv("ANTHROPIC_MODEL", "claude-3-5-haiku-latest")

OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
OPENAI_MODEL = os.getenv("OPENAI_MODEL", "Qwen/Qwen3-Next-80B-A3B-Instruct")
OPENAI_URL = os.getenv("OPENAI_URL", "https://api.deepinfra.com/v1/openai")

from openai import OpenAI

# Create an OpenAI client with your token and endpoint
openai = OpenAI(
    api_key=OPENAI_API_KEY,
    base_url=OPENAI_URL,
)

llm_model = os.getenv("GENAI_ENGINE", "claude")

# Configure logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)

# Initialize FastAPI app
app = FastAPI(
    title="Tender Automation AI Engine",
    description="AI Engine for Getting RFP Documents, RFP Analysis, and Bid Document Generation using Claude",
    version="2.0.0"
)

# Configure CORS
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],  # Adjust in production
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# Include bid processing routes
app.include_router(bid_processing_router)

# Include location finder routes
app.include_router(location_finder_router)

# Initialize Minaions RFP Service
service = MinaionsRFPService()

# API key authentication
async def verify_api_key(x_api_key: str = Header(None)):
    if not x_api_key or x_api_key != os.environ.get("AI_SERVICE_API_KEY"):
        raise HTTPException(status_code=401, detail="Invalid API key")
    return x_api_key

# =================================================================
# REQUEST/RESPONSE MODELS
# =================================================================

# Get RFP Documents Models
class GetRfpDocumentsRequest(BaseModel):
    tender_id: str = Field(..., description="Tender ID to get additional documents for")
    tenant_id: str = Field(..., description="Tenant ID")

# Analysis Estimation Models
class EstimateAnalysisCostRequest(BaseModel):
    tender_id: str = Field(..., description="Tender ID")
    tenant_id: str = Field(..., description="Tenant ID")
    company_id: str = Field(..., description="Company ID")

# RFP Analysis Models
class AnalyzeRfpRequest(BaseModel):
    analysis_id: str = Field(..., description="Analysis record ID")
    tenant_id: str = Field(..., description="Tenant ID")
    company_id: str = Field(..., description="Company ID")

# RFP Analysis Models
class AnalyzeCompanyDocsRequest(BaseModel):
    tenant_id: str = Field(..., description="Tenant ID")
    company_id: str = Field(..., description="Company ID")
    folder_list: List[Dict[str, Any]] = Field(..., description="List of companies documents with their details")

# Bid Generation Estimation Models
class EstimateBidGenerationCostRequest(BaseModel):
    analysis_id: str = Field(..., description="Analysis record ID")
    tenant_id: str = Field(..., description="Tenant ID")
    required_docs: List[Dict[str, Any]] = Field(..., description="List of required documents with their details")

# Bid Document Generation Models
class GenerateBidDocumentsRequest(BaseModel):
    bid_generation_id: str = Field(..., description="Bid generation record ID")
    tenant_id: str = Field(..., description="Tenant ID")
    required_docs: List[Dict[str, Any]] = Field(..., description="List of required documents with their details")
    company_id: str = Field(..., description="Company ID")

# NEW: Regenerate Bid Document Models
class RegenerateBidDocumentRequest(BaseModel):
    bid_generation_id: str = Field(..., description="Bid generation record ID")
    tenant_id: str = Field(..., description="Tenant ID")
    document_id: str = Field(..., description="Document ID of the original document to regenerate")
    user_prompt: str = Field(..., description="User's instructions for regeneration")
    company_id: str = Field(..., description="Company ID")

# Chat Models
class SetupRfpChatRequest(BaseModel):
    analysis_id: str = Field(..., description="Analysis record ID")
    tenant_id: str = Field(..., description="Tenant ID")

class ChatWithRfpRequest(BaseModel):
    analysis_id: str = Field(..., description="Analysis record ID")
    tenant_id: str = Field(..., description="Tenant ID")
    tender_id: str = Field(..., description="Tender ID")
    query: str = Field(..., description="User's question")
    client_id: Optional[str] = Field(None, description="Client session ID")

# Legacy Models (for backward compatibility)
class ChatCompletionRequest(BaseModel):
    prompt: str
    model: Optional[str] = ANTHROPIC_MODEL
    max_tokens: Optional[int] = 4000
    temperature: Optional[float] = 0.7

class AnalyzeDocumentRequest(BaseModel):
    file_url: str
    document_type: Optional[str] = "tender"

# PDF Merger and Compression Models
class MergeBidDocumentsRequest(BaseModel):
    bid_generation_id: str = Field(..., description="Bid generation record ID")
    tenant_id: str = Field(..., description="Tenant ID")
    generated_document_ids: List[str]
    document_categories: Optional[List[str]] = Field(None, description="List of document categories to include")
    add_page_numbers: bool = Field(True, description="Whether to add page numbers to merged PDF")

class CompressDocumentRequest(BaseModel):
    bid_generation_id: str = Field(..., description="Bid generation record ID")
    document_id: str = Field(..., description="Document ID to compress")
    tenant_id: str = Field(..., description="Tenant ID")
    target_size_percent: int = Field(50, description="Target size as percentage of original (25, 50, or 75)")
    preserve_quality: bool = Field(True, description="Whether to prioritize quality over exact size target")

class BatchCompressDocumentsRequest(BaseModel):
    bid_generation_id: str = Field(..., description="Bid generation record ID")
    tenant_id: str = Field(..., description="Tenant ID")
    target_size_percent: int = Field(50, description="Target size as percentage of original (25, 50, or 75)")
    preserve_quality: bool = Field(True, description="Whether to prioritize quality over exact size target")
    document_categories: Optional[List[str]] = Field(None, description="List of document categories to compress")

class MergeTenderDocumentsRequest(BaseModel):
    tender_id: str = Field(..., description="Tender ID")
    tenant_id: str = Field(..., description="Tenant ID")
    add_page_numbers: bool = Field(True, description="Whether to add page numbers to merged PDF")
    include_linked_docs: bool = Field(True, description="Whether to include linked documents")

# =================================================================
# HEALTH CHECK ROUTES
# =================================================================

@app.get("/")
async def root():
    return {"message": "Tender Automation AI Engine v2.0 is running"}

@app.get("/health")
async def health_check():
    return {"status": "healthy", "version": "2.0.0"}

# =================================================================
# GET RFP DOCUMENTS ROUTES
# =================================================================

@app.post("/get_rfp_documents")
async def get_rfp_documents(
    request: GetRfpDocumentsRequest,
    background_tasks: BackgroundTasks,
    api_key: str = Depends(verify_api_key)
):
    """Extract links from existing RFP documents and download additional documents"""
    try:
        # Start RFP document extraction in the background
        background_tasks.add_task(
            service.get_rfp_documents,
            request.tender_id,
            request.tenant_id
        )
        
        return {
            "status": "processing",
            "message": f"Getting additional RFP documents for tender: {request.tender_id}",
            "tender_id": request.tender_id,
            "tenant_id": request.tenant_id
        }
    except Exception as e:
        logger.error(f"Error getting RFP documents: {e}")
        raise HTTPException(status_code=500, detail=str(e))

# =================================================================
# ANALYSIS ESTIMATION ROUTES
# =================================================================

@app.post("/estimate_analysis_cost")
async def estimate_analysis_cost(
    request: EstimateAnalysisCostRequest,
    background_tasks: BackgroundTasks,
    api_key: str = Depends(verify_api_key)
):
    """Estimate the cost for RFP analysis based on document complexity"""
    try:
        # Create placeholder analysis record immediately (synchronous)
        analysis_id = service.create_analysis_placeholder(request.tender_id, request.tenant_id, request.company_id)

        # Start processing in background - DOES NOT BLOCK
        background_tasks.add_task(
            service.process_analysis_cost_estimation_background,
            request.tender_id,
            request.tenant_id,
            request.company_id,
            analysis_id
        )

        # Return immediately with analysis_id
        return {
            "status": "processing",
            "message": "Analysis cost estimation started",
            "analysis_id": analysis_id
        }
    except Exception as e:
        logger.error(f"Error estimating analysis cost: {e}")
        raise HTTPException(status_code=500, detail=str(e))

# =================================================================
# RFP ANALYSIS ROUTES
# =================================================================

@app.post("/analyze_rfp")
async def analyze_rfp(
    request: AnalyzeRfpRequest,
    background_tasks: BackgroundTasks,
    api_key: str = Depends(verify_api_key)
):
    """Analyze RFP documents to extract key information and check eligibility"""
    try:
        # Start RFP analysis in the background
        background_tasks.add_task(
            service.analyze_rfp,
            request.analysis_id,
            request.tenant_id,
            request.company_id
        )

        # result = service.analyze_rfp(request.analysis_id, request.tenant_id)

        # return result
        
        return {
            "status": "processing",
            "message": "RFP analysis started",
            "analysis_id": request.analysis_id
        }
    except Exception as e:
        logger.error(f"Error starting RFP analysis: {e}")
        raise HTTPException(status_code=500, detail=str(e))


# =================================================================
# COMPANY DOCUMENT ANALYSIS ROUTES
# =================================================================

@app.post("/analyze_company_docs")
async def analyze_company_docs(
    request: AnalyzeCompanyDocsRequest,
    background_tasks: BackgroundTasks,
    api_key: str = Depends(verify_api_key)
):
    """Analyze Company documents to extract key information"""
    try:
        # Start RFP analysis in the background
        background_tasks.add_task(
            service.analyze_company_docs,
            request.tenant_id,
            request.folder_list,
            request.company_id
        )

        service.api_client.update_company_info(request.company_id, request.tenant_id, {
            "$set": {"status": "doc_analysis_in_progress"},
            "$push": {
                "logs": {
                    "timestamp": time.time(),
                    "action": "doc_analysis_in_progress"
                }
            }
        })
        
        return {
            "status": "processing",
            "message": "Company document analysis started",
            "company_id": request.company_id
        }
    except Exception as e:
        logger.error(f"Error starting Company document analysis: {e}")
        print(e)
        raise HTTPException(status_code=500, detail=str(e))

# =================================================================
# BID GENERATION ESTIMATION ROUTES
# =================================================================

@app.post("/estimate_bid_generation_cost")
async def estimate_bid_generation_cost(
    request: EstimateBidGenerationCostRequest,
    api_key: str = Depends(verify_api_key)
):
    """Estimate the cost for bid document generation"""
    try:
        result = service.estimate_bid_generation_cost(request.analysis_id, request.tenant_id, request.required_docs)
        return result
    except Exception as e:
        logger.error(f"Error estimating bid generation cost: {e}")
        raise HTTPException(status_code=500, detail=str(e))

# =================================================================
# BID DOCUMENT GENERATION ROUTES
# =================================================================

@app.post("/generate_bid_documents")
async def generate_bid_documents(
    request: GenerateBidDocumentsRequest,
    background_tasks: BackgroundTasks,
    api_key: str = Depends(verify_api_key)
):
    """Generate complete bid documents using enhanced automation"""
    try:
        # Start bid document generation in the background
        background_tasks.add_task(
            service.generate_bid_documents,
            request.bid_generation_id,
            request.tenant_id,
            request.required_docs,
            request.company_id
        )
        
        return {
            "status": "processing",
            "message": "Bid document generation started",
            "bid_generation_id": request.bid_generation_id
        }
    except Exception as e:
        logger.error(f"Error starting bid document generation: {e}")
        raise HTTPException(status_code=500, detail=str(e))

# =================================================================
# NEW: REGENERATE BID DOCUMENT ROUTES
# =================================================================

@app.post("/regenerate_bid_document")
async def regenerate_bid_document(
    request: RegenerateBidDocumentRequest,
    api_key: str = Depends(verify_api_key)
):
    """Regenerate a specific bid document based on user feedback"""
    try:
        result = service.regenerate_bid_document(
            request.bid_generation_id,
            request.tenant_id,
            request.document_id,
            request.user_prompt,
            request.company_id
        )
        return result
    except Exception as e:
        logger.error(f"Error regenerating bid document: {e}")
        raise HTTPException(status_code=500, detail=str(e))

# =================================================================
# CHAT WITH RFP ROUTES
# =================================================================

@app.post("/setup_rfp_chat")
async def setup_rfp_chat(
    request: SetupRfpChatRequest,
    background_tasks: BackgroundTasks,
    api_key: str = Depends(verify_api_key)
):
    """Setup chat functionality for RFP queries"""
    try:
        analysis_id = request.analysis_id
        tenant_id = request.tenant_id
        
        # Validate inputs immediately
        analysis = service.api_client.get_analysis(analysis_id)
        if not analysis:
            raise HTTPException(status_code=404, detail=f"Analysis record not found: {analysis_id}")
        
        # Validate tenant
        if str(analysis["tenant"]) != tenant_id:
            raise HTTPException(status_code=404, detail=f"Analysis record not found: {analysis_id}")
        
        # Get tender details via API
        tender_id = str(analysis["tender"])

        tender = service.api_client.get_tender(tender_id, tenant_id)
        if not tender:
            raise ValueError(f"Tender not found: {analysis['tender']}")

        # Check if already setup
        chat_setup = tender.get("chatSetup", {})
        if chat_setup.get("setupCompleted"):
            return {
                "status": "already_completed",
                "bid_id": chat_setup.get("bidId"),
                "message": "Chat functionality already setup",
                "analysis_id": analysis_id
            }
        
        # Update tender chat setup status to setup_in_progress immediately
        service.api_client.update_tender(tender_id, {
            "$set": {
                "chatSetup": {
                    "bidId": f"analysis_{tender_id}",
                    "setupCompleted": False,
                    "setupInProgress": True,
                    "setupStarted": time.time()
                }
            },
            "$push": {
                "logs": {
                    "timestamp": time.time(),
                    "action": "chat_setup_started",
                    "details": {"started_by": tenant_id}
                }
            }
        })
        # Update analysis status to setup_in_progress immediately
        service.api_client.update_analysis(analysis_id, {
            "$push": {
                "logs": {
                    "timestamp": time.time(),
                    "action": "chat_setup_started",
                    "details": {"started_by": tenant_id}
                }
            }
        })
        
        # Start background task for actual setup
        background_tasks.add_task(
            service.setup_rfp_chat_background,
            analysis_id,
            tenant_id
        )
        
        # Return immediately
        return {
            "status": "processing",
            "message": "Chat setup started in background",
            "analysis_id": analysis_id,
            "bid_id": f"analysis_{tender_id}",
            "estimated_time": "2-5 minutes"
        }
        
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"Error starting chat setup: {e}")
        raise HTTPException(status_code=500, detail=str(e))

# Add new endpoint to check setup status
@app.get("/chat_setup_status/{analysis_id}")
async def get_chat_setup_status(
    analysis_id: str,
    tenant_id: str,
    api_key: str = Depends(verify_api_key)
):
    """Get the status of chat setup process"""
    try:
        # Get analysis record via API
        analysis = service.api_client.get_analysis(analysis_id)
        if not analysis:
            raise HTTPException(status_code=404, detail=f"Analysis record not found: {analysis_id}")
        
        # Validate tenant
        if str(analysis["tenant"]) != tenant_id:
            raise HTTPException(status_code=404, detail=f"Analysis record not found: {analysis_id}")
        
        # Get tender details via API
        tender_id = str(analysis["tender"])

        tender = service.api_client.get_tender(tender_id, tenant_id)
        if not tender:
            raise ValueError(f"Tender not found: {analysis['tender']}")
        
        chat_setup = tender.get("chatSetup", {})
        
        if not chat_setup:
            return {
                "status": "not_started",
                "message": "Chat setup has not been initiated",
                "analysis_id": analysis_id
            }
        
        # Determine current status
        if chat_setup.get("setupCompleted"):
            return {
                "status": "completed",
                "message": "Chat setup completed successfully",
                "analysis_id": analysis_id,
                "bid_id": chat_setup.get("bidId"),
                "completed_at": chat_setup.get("setupCompletedAt")
            }
        elif chat_setup.get("setupFailed"):
            return {
                "status": "failed",
                "message": "Chat setup failed",
                "analysis_id": analysis_id,
                "error": chat_setup.get("errorMessage"),
                "failed_at": chat_setup.get("failedAt")
            }
        elif chat_setup.get("setupInProgress"):
            return {
                "status": "processing",
                "message": "Chat setup is in progress",
                "analysis_id": analysis_id,
                "started_at": chat_setup.get("setupStarted"),
                "estimated_remaining": "1-3 minutes"
            }
        else:
            return {
                "status": "unknown",
                "message": "Chat setup status is unclear",
                "analysis_id": analysis_id,
                "chat_setup": chat_setup
            }
            
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"Error getting chat setup status: {e}")
        raise HTTPException(status_code=500, detail=str(e))

@app.post("/chat_with_rfp")
async def chat_with_rfp(
    request: ChatWithRfpRequest,
    api_key: str = Depends(verify_api_key)
):
    """Chat with RFP documents using enhanced search and Claude"""
    try:
        response = service.chat_with_rfp(
            request.analysis_id,
            request.tenant_id,
            request.tender_id,
            request.query,
            request.client_id
        )
        
        return {
            "response": response,
            "analysis_id": request.analysis_id,
            "query": request.query
        }
    except Exception as e:
        logger.error(f"Error processing chat query: {e}")
        raise HTTPException(status_code=500, detail=str(e))

# =================================================================
# UTILITY ROUTES
# =================================================================

@app.post("/chat_completion")
async def chat_completion(
    request: ChatCompletionRequest,
    api_key: str = Depends(verify_api_key)
):
    """Direct Claude API chat completion (utility endpoint)"""
    try:
        import anthropic
        
        client = anthropic.Client(api_key=ANTHROPIC_API_KEY)
        
        response = client.messages.create(
            model=request.model,
            max_tokens=request.max_tokens,
            temperature=request.temperature,
            messages=[
                {"role": "user", "content": request.prompt}
            ]
        )
        
        return {
            "completion": response.content[0].text,
            "model": response.model,
            "usage": {
                "input_tokens": response.usage.input_tokens,
                "output_tokens": response.usage.output_tokens
            }
        }
    except Exception as e:
        logger.error(f"Error in chat completion: {e}")
        raise HTTPException(status_code=500, detail=str(e))

@app.post("/analyze_document")
async def analyze_document(
    request: AnalyzeDocumentRequest,
    api_key: str = Depends(verify_api_key)
):
    """Analyze a document from URL (utility endpoint)"""
    try:
        import anthropic
        import requests
        from tempfile import NamedTemporaryFile
        import PyPDF2
        
        # Download the document
        response = requests.get(request.file_url)
        if response.status_code != 200:
            raise HTTPException(status_code=400, detail="Failed to download document")
        
        # Create a temporary file
        with NamedTemporaryFile(delete=False, suffix=".pdf") as temp_file:
            temp_file.write(response.content)
            temp_file_path = temp_file.name
        
        try:
            # Extract text content using PyPDF2
            text_content = ""
            try:
                with open(temp_file_path, 'rb') as f:
                    pdf_reader = PyPDF2.PdfReader(f)
                    for page_num in range(len(pdf_reader.pages)):
                        page = pdf_reader.pages[page_num]
                        text_content += page.extract_text() + "\n\n"
            except Exception as pdf_error:
                logger.error(f"Error extracting text from PDF: {pdf_error}")
                text_content = f"[Failed to extract text from PDF: {request.file_url}]"
            
            # Analyze with Claude
            client = anthropic.Client(api_key=ANTHROPIC_API_KEY)
            
            prompt = f"""
            Please analyze this tender document and extract key information such as:
            
            1. Tender title and ID
            2. Issuing organization
            3. Submission deadline
            4. Eligibility criteria
            5. Scope of work
            6. Required documents
            7. Evaluation criteria
            8. Estimated value (if available)
            
            Document content:
            {text_content[:50000]}  # Truncate if too long
            
            Provide your analysis in JSON format with these fields.
            """

            if (llm_model == 'claude'):
                response = client.messages.create(
                    model=ANTHROPIC_MODEL,
                    max_tokens=4000,
                    temperature=0.2,
                    messages=[
                        {"role": "user", "content": prompt}
                    ]
                )
                response_text=response.content[0].text
            elif (llm_model == 'open_llm'):
                response = openai.chat.completions.create(
                    model=OPENAI_MODEL,
                    messages=[
                        {"role": "user", "content": prompt},
                    ],
                )
                response_text = response.choices[0].message.content
            
            # Parse JSON from Claude's response
            import re
            
            # Find JSON in the response
            json_match = re.search(r'```json\n(.*?)\n```', response_text, re.DOTALL)
            if json_match:
                analysis_json = json.loads(json_match.group(1))
            else:
                # Try to parse the whole response as JSON
                try:
                    analysis_json = json.loads(response_text)
                except:
                    # If all else fails, return the raw text
                    analysis_json = {"analysis": response_text}
            
            return {
                "document_type": request.document_type,
                "analysis": analysis_json
            }
            
        finally:
            # Clean up the temporary file
            if os.path.exists(temp_file_path):
                os.unlink(temp_file_path)
                
    except Exception as e:
        logger.error(f"Error analyzing document: {e}")
        raise HTTPException(status_code=500, detail=str(e))

# =================================================================
# PDF MERGER AND COMPRESSION ROUTES
# =================================================================

@app.post("/merge_bid_documents")
async def merge_bid_documents(
    request: MergeBidDocumentsRequest,
    background_tasks: BackgroundTasks,
    api_key: str = Depends(verify_api_key)
):
    """Merge bid documents into a single PDF with index"""
    try:
        # Validate that generated_document_ids is provided
        if not request.generated_document_ids:
            raise HTTPException(
                status_code=400, 
                detail="generated_document_ids is required and cannot be empty"
            )
        
        # Start merge process in the background
        background_tasks.add_task(
            service.merge_bid_documents,
            request.bid_generation_id,
            request.tenant_id,
            request.generated_document_ids,
            request.document_categories,
            request.add_page_numbers
        )
        
        return {
            "status": "processing",
            "message": "Bid document merge started in background",
            "bid_generation_id": request.bid_generation_id,
            "document_count": len(request.generated_document_ids),
            "estimated_time": "2-5 minutes"
        }
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"Error starting bid document merge: {e}")
        raise HTTPException(status_code=500, detail=str(e))

@app.post("/compress_document")
async def compress_document(
    request: CompressDocumentRequest,
    api_key: str = Depends(verify_api_key)
):
    """Compress a PDF document"""
    try:
        result = service.compress_document(
            request.bid_generation_id,
            request.document_id,
            request.tenant_id,
            request.target_size_percent,
            request.preserve_quality
        )
        return result
    except Exception as e:
        logger.error(f"Error compressing document: {e}")
        raise HTTPException(status_code=500, detail=str(e))

@app.post("/batch_compress_documents")
async def batch_compress_documents(
    request: BatchCompressDocumentsRequest,
    background_tasks: BackgroundTasks,
    api_key: str = Depends(verify_api_key)
):
    """Batch compress all PDF documents in a bid generation"""
    try:
        # Start batch compression in the background
        background_tasks.add_task(
            service.batch_compress_bid_documents,
            request.bid_generation_id,
            request.tenant_id,
            request.target_size_percent,
            request.preserve_quality,
            request.document_categories
        )
        
        return {
            "status": "processing",
            "message": "Batch document compression started in background",
            "bid_generation_id": request.bid_generation_id,
            "target_size_percent": request.target_size_percent,
            "estimated_time": "5-10 minutes"
        }
    except Exception as e:
        logger.error(f"Error starting batch document compression: {e}")
        raise HTTPException(status_code=500, detail=str(e))

@app.post("/merge_tender_documents")
async def merge_tender_documents(
    request: MergeTenderDocumentsRequest,
    background_tasks: BackgroundTasks,
    api_key: str = Depends(verify_api_key)
):
    """Merge all tender/RFP documents into a single PDF with index"""
    try:
        # Start merge process in the background
        background_tasks.add_task(
            service.merge_tender_documents,
            request.tender_id,
            request.tenant_id,
            request.add_page_numbers,
            request.include_linked_docs
        )
        
        return {
            "status": "processing",
            "message": "Tender document merge started in background",
            "tender_id": request.tender_id,
            "estimated_time": "3-7 minutes"
        }
    except Exception as e:
        logger.error(f"Error starting tender document merge: {e}")
        raise HTTPException(status_code=500, detail=str(e))

# Synchronous versions for immediate processing of smaller documents
@app.post("/merge_bid_documents_sync")
async def merge_bid_documents_sync(
    request: MergeBidDocumentsRequest,
    api_key: str = Depends(verify_api_key)
):
    """Merge bid documents into a single PDF with index (synchronous)"""
    try:
        result = service.merge_bid_documents(
            request.bid_generation_id,
            request.tenant_id,
            request.document_categories,
            request.add_page_numbers
        )
        return result
    except Exception as e:
        logger.error(f"Error merging bid documents: {e}")
        raise HTTPException(status_code=500, detail=str(e))

@app.post("/batch_compress_documents_sync")
async def batch_compress_documents_sync(
    request: BatchCompressDocumentsRequest,
    api_key: str = Depends(verify_api_key)
):
    """Batch compress all PDF documents in a bid generation (synchronous)"""
    try:
        result = service.batch_compress_bid_documents(
            request.bid_generation_id,
            request.tenant_id,
            request.target_size_percent,
            request.preserve_quality,
            request.document_categories
        )
        return result
    except Exception as e:
        logger.error(f"Error batch compressing documents: {e}")
        raise HTTPException(status_code=500, detail=str(e))

@app.post("/merge_tender_documents_sync")
async def merge_tender_documents_sync(
    request: MergeTenderDocumentsRequest,
    api_key: str = Depends(verify_api_key)
):
    """Merge all tender/RFP documents into a single PDF with index (synchronous)"""
    try:
        result = service.merge_tender_documents(
            request.tender_id,
            request.tenant_id,
            request.add_page_numbers,
            request.include_linked_docs
        )
        return result
    except Exception as e:
        logger.error(f"Error merging tender documents: {e}")
        raise HTTPException(status_code=500, detail=str(e))

@app.get("/merge_status/{bid_generation_id}")
async def get_merge_status(
    bid_generation_id: str,
    tenant_id: str,
    api_key: str = Depends(verify_api_key)
):
    """Get the status of document merge operation"""
    try:
        # Get bid generation record
        bid_gen = service.api_client.get_bid_generation(bid_generation_id, tenant_id)
        if not bid_gen:
            raise HTTPException(status_code=404, detail="Bid generation not found")
        
        # Check for merged documents
        merged_docs = bid_gen.get("mergedDocuments", [])
        logs = bid_gen.get("logs", [])
        
        # Find merge-related logs
        merge_logs = [
            log for log in logs 
            if log.get("action") in ["documents_merged", "merge_started", "merge_failed"]
        ]
        
        if merged_docs:
            latest_merge = max(merge_logs, key=lambda x: x.get("timestamp", 0)) if merge_logs else None
            return {
                "status": "completed",
                "merged_document_ids": merged_docs,
                "completed_at": latest_merge.get("timestamp") if latest_merge else None,
                "details": latest_merge.get("details") if latest_merge else None
            }
        
        # Check for failure
        failed_logs = [log for log in merge_logs if log.get("action") == "merge_failed"]
        if failed_logs:
            latest_failure = max(failed_logs, key=lambda x: x.get("timestamp", 0))
            return {
                "status": "failed",
                "failed_at": latest_failure.get("timestamp"),
                "error": latest_failure.get("details", {}).get("error")
            }
        
        # Check for in-progress
        started_logs = [log for log in merge_logs if log.get("action") == "merge_started"]
        if started_logs:
            latest_start = max(started_logs, key=lambda x: x.get("timestamp", 0))
            return {
                "status": "processing",
                "started_at": latest_start.get("timestamp"),
                "estimated_time": "2-5 minutes"
            }
        
        return {
            "status": "not_started",
            "message": "No merge operation found for this bid generation"
        }
        
    except Exception as e:
        logger.error(f"Error getting merge status: {e}")
        raise HTTPException(status_code=500, detail=str(e))

@app.get("/batch_compress_status/{bid_generation_id}")
async def get_batch_compress_status(
    bid_generation_id: str,
    tenant_id: str,
    api_key: str = Depends(verify_api_key)
):
    """Get the status of batch compression operation"""
    try:
        bid_gen = service.api_client.get_bid_generation(bid_generation_id, tenant_id)
        if not bid_gen:
            raise HTTPException(status_code=404, detail="Bid generation not found")
        
        logs = bid_gen.get("logs", [])
        
        # Find compression-related logs
        compress_logs = [
            log for log in logs 
            if log.get("action") in [
                "batch_documents_compressed", 
                "batch_compression_started", 
                "batch_compression_failed"
            ]
        ]
        
        # Check for completion
        completed_logs = [log for log in compress_logs if log.get("action") == "batch_documents_compressed"]
        if completed_logs:
            latest = max(completed_logs, key=lambda x: x.get("timestamp", 0))
            return {
                "status": "completed",
                "completed_at": latest.get("timestamp"),
                "details": latest.get("details", {}),
                "compressed_count": latest.get("details", {}).get("compressed_count", 0),
                "overall_compression_ratio": latest.get("details", {}).get("overall_compression_ratio", 0)
            }
        
        # Check for failure
        failed_logs = [log for log in compress_logs if log.get("action") == "batch_compression_failed"]
        if failed_logs:
            latest_failure = max(failed_logs, key=lambda x: x.get("timestamp", 0))
            return {
                "status": "failed",
                "failed_at": latest_failure.get("timestamp"),
                "error": latest_failure.get("details", {}).get("error")
            }
        
        # Check for in-progress
        started_logs = [log for log in compress_logs if log.get("action") == "batch_compression_started"]
        if started_logs:
            latest_start = max(started_logs, key=lambda x: x.get("timestamp", 0))
            return {
                "status": "processing",
                "started_at": latest_start.get("timestamp"),
                "estimated_time": "5-10 minutes"
            }
        
        return {
            "status": "not_started",
            "message": "No batch compression operation found"
        }
        
    except Exception as e:
        logger.error(f"Error getting batch compression status: {e}")
        raise HTTPException(status_code=500, detail=str(e))

@app.get("/get_rfp_status/{tender_id}")
async def get_rfp_documents_status(
    tender_id: str,
    tenant_id: str,
    api_key: str = Depends(verify_api_key)
):
    """Get the status of get_rfp_documents operation"""
    try:
        # Get tender record to check status
        tender = service.api_client.get_tender(tender_id, tenant_id)
        if not tender:
            raise HTTPException(status_code=404, detail="Tender not found")
        
        logs = tender.get("logs", [])

        logger.info(f"Logs found: {logs}")
        
        # Find RFP documents related logs
        rfp_logs = [
            log for log in logs 
            if log.get("action") in [
                "linked_documents_added", 
                "get_rfp_documents_failed",
                "get_rfp_documents_completed"
            ]
        ]

        logger.info(f"Filtered RFP Logs: {rfp_logs}")

        for log in reversed(rfp_logs):
            action = log.get("action")
            details = log.get("details", {})
            if action == "get_rfp_documents_completed":
                return {
                    "status": "completed",
                    "completed_at": log.get("timestamp"),
                    "links_found": details.get("links_found", 0),
                    "documents_downloaded": details.get("documents_downloaded", 0),
                    "message": f"Process completed. Found {details.get('links_found', 0)} links, downloaded {details.get('documents_downloaded', 0)} additional documents"
                }
            elif action == "get_rfp_documents_failed":
                return {
                    "status": "failed",
                    "failed_at": log.get("timestamp"),
                    "error": details.get("error"),
                    "message": "RFP documents extraction failed"
                }
        
        # Still processing
        return {
            "status": "processing",
            "message": "Still processing... Check again in a few minutes"
        }
        
    except Exception as e:
        logger.error(f"Error getting RFP documents status: {e}")
        raise HTTPException(status_code=500, detail=str(e))

# Run the app
if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8000)