import os
import boto3
from botocore.client import Config
import requests
import time
from fastapi import FastAPI, UploadFile, File, Form, HTTPException, Request
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import FileResponse
from starlette.background import BackgroundTask
from pydantic import BaseModel
import tempfile
import uvicorn
import json
from botocore.exceptions import ClientError
from typing import Optional, Protocol
import base64
from abc import ABC, abstractmethod
from dataclasses import dataclass
from enum import Enum
from core import MessageType, ResponseStatus, AppConfig
from schemas import WebhookResponse, TextMessage
from repositories import StorageRepository, MinIOStorageRepository
from repositories import WebhookClient, N8NWebhookClient
from handlers import AudioMessageHandler, TextMessageHandler
from services import AudioService, ChatService, HealthService, ResponseService, ResponseManager, WebhookService, OpenAIService

class DIContainer:
    def __init__(self):
        self.config = AppConfig.from_env()
        self.storage_repo = MinIOStorageRepository(self.config)
        self.webhook_client = N8NWebhookClient(self.config.n8n_webhook_url)
        self.response_manager = ResponseManager()
        
        # Initialize OpenAI service
        self.openai_service = OpenAIService()
        
        # Updated services to use OpenAI service
        self.audio_service = AudioService(self.storage_repo, self.config.minio_bucket)
        self.chat_service = ChatService(
            self.storage_repo, 
            self.webhook_client, 
            self.response_manager, 
            self.config,
            self.openai_service  # Pass OpenAI service
        )
        self.webhook_service = WebhookService(
            self.response_manager, 
            self.storage_repo, 
            self.config.minio_bucket,
            self.openai_service  # Pass OpenAI service
        )
        self.response_service = ResponseService(self.response_manager, self.audio_service)
        self.health_service = HealthService(self.storage_repo, self.config)

# FastAPI App Factory
def create_app() -> FastAPI:
    app = FastAPI(title="Unified Chat API")
    
    # Add CORS middleware
    app.add_middleware(
        CORSMiddleware,
        allow_origins=["*"],
        allow_credentials=True,
        allow_methods=["*"],
        allow_headers=["*"],
        expose_headers=["X-Response-Text"],
    )
    
    # Initialize dependencies
    container = DIContainer()
    
    # Print configuration
    print("MinIO Endpoint:", container.config.minio_endpoint)
    print("MinIO Bucket:", container.config.minio_bucket)
    print("n8n Webhook URL:", container.config.n8n_webhook_url)

    @app.post("/chat")
    async def chat_handler(
        file: Optional[UploadFile] = File(None), 
        text: Optional[str] = Form(None)
    ):
        """Handles incoming chat messages (either text or audio). Forwards the message to the n8n webhook."""
        return container.chat_service.process_message(file, text)

    @app.post("/n8n_webhook_receiver")
    async def n8n_webhook_receiver(response: WebhookResponse):
        """Receives and processes webhook data from n8n."""
        return container.webhook_service.process_webhook_response(response)

    @app.get("/get-audio-response")
    async def get_audio_response():
        """Fetches the agent's text and audio response."""
        return container.response_service.get_agent_response()

    @app.get("/health")
    async def health_check():
        """Health check endpoint"""
        return container.health_service.get_health_status()

    @app.get("/")
    async def root():
        """Root endpoint with API info"""
        return {
            "service": "Unified Chat API",
            "version": "1.0.0",
            "description": "Unified backend for audio/text chat with an agent, powered by n8n.",
            "endpoints": {
                "chat": "/chat (accepts audio or text, forwards to n8n)",
                "n8n_webhook_receiver": "/n8n-webhook-receiver (receives agent responses from n8n)",
                "get_audio_response": "/get-audio-response (fetches agent's audio and text response)",
            },
        }
    
    return app


# Application entry point
app = create_app()

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