import os
import uuid
import json
import streamlit as st
from dotenv import load_dotenv
from azure.search.documents.indexes import SearchIndexClient
from azure.search.documents.indexes.models import (
    SearchIndex, SimpleField, SearchableField, SearchField,
    SearchFieldDataType, VectorSearch, VectorSearchProfile,
    HnswAlgorithmConfiguration, SemanticConfiguration, SemanticPrioritizedFields,
    SemanticField, SemanticSearch
)
from azure.search.documents.models import VectorizedQuery
from azure.search.documents import SearchClient
from azure.core.credentials import AzureKeyCredential
from openai import AzureOpenAI

# --------------------- Environment Setup ---------------------
load_dotenv()

# Azure Cognitive Search Configuration
AZURE_SEARCH_SERVICE_ENDPOINT = os.getenv("AZURE_SEARCH_SERVICE_ENDPOINT")
AZURE_SEARCH_INDEX = os.getenv("AZURE_SEARCH_INDEX")
AZURE_SEARCH_ADMIN_KEY = os.getenv("AZURE_SEARCH_ADMIN_KEY")

# Azure OpenAI Configuration
AZURE_OPENAI_ENDPOINT = os.getenv("AZURE_OPENAI_ENDPOINT")
AZURE_OPENAI_KEY = os.getenv("AZURE_OPENAI_KEY")
AZURE_OPENAI_EMBEDDING_DEPLOYMENT = os.getenv("AZURE_OPENAI_EMBEDDING_DEPLOYMENT")
AZURE_OPENAI_API_VERSION = os.getenv("AZURE_OPENAI_API_VERSION")
AZURE_OPENAI_EMBEDDING_DIMENSIONS = int(os.getenv("AZURE_OPENAI_EMBEDDING_DIMENSIONS", "1536"))

# --------------------- Service Clients ---------------------
credential = AzureKeyCredential(AZURE_SEARCH_ADMIN_KEY)
search_client = SearchClient(AZURE_SEARCH_SERVICE_ENDPOINT, AZURE_SEARCH_INDEX, credential)
index_client = SearchIndexClient(AZURE_SEARCH_SERVICE_ENDPOINT, credential)

openai_client = AzureOpenAI(
    azure_endpoint=AZURE_OPENAI_ENDPOINT,
    api_key=AZURE_OPENAI_KEY,
    api_version=AZURE_OPENAI_API_VERSION
)

# --------------------- Core Functions ---------------------
def create_index():
    """Create or update the search index with appropriate schema"""
    fields = [
        SimpleField(name="id", type=SearchFieldDataType.String, key=True),
        SimpleField(name="userID", type=SearchFieldDataType.Int64, filterable=True),
        SearchableField(name="userName", type=SearchFieldDataType.String, filterable=True),
        SearchableField(name="type", type=SearchFieldDataType.String),
        SearchableField(name="description", type=SearchFieldDataType.String),
        SearchableField(name="lineNumber", type=SearchFieldDataType.String),
        SearchableField(name="text", type=SearchFieldDataType.String),
        SearchableField(name="timestamp", type=SearchFieldDataType.String),
        SearchField(
            name="embedding",
            type=SearchFieldDataType.Collection(SearchFieldDataType.Single),
            searchable=True,
            vector_search_dimensions=AZURE_OPENAI_EMBEDDING_DIMENSIONS,
            vector_search_profile_name="myHnswProfile"
        ),
        SimpleField(name="emailAddress", type=SearchFieldDataType.String),
        SimpleField(name="oesEmailId", type=SearchFieldDataType.String),
    ]

    vector_search = VectorSearch(
        algorithms=[HnswAlgorithmConfiguration(name="myHnsw")],
        profiles=[VectorSearchProfile(name="myHnswProfile", algorithm_configuration_name="myHnsw")]
    )

    semantic_config = SemanticConfiguration(
        name="my-semantic-config",
        prioritized_fields=SemanticPrioritizedFields(
            title_field=SemanticField(field_name="userName"),
            content_fields=[SemanticField(field_name="text")]
        )
    )

    index = SearchIndex(
        name=AZURE_SEARCH_INDEX,
        fields=fields,
        vector_search=vector_search,
        semantic_search=SemanticSearch(configurations=[semantic_config])
    )

    index_client.create_or_update_index(index)

def delete_existing_documents():
    """Remove all documents from the search index"""
    try:
        result = search_client.search(search_text="*", select="id")
        ids = [doc['id'] for doc in result]
        if ids:
            search_client.delete_documents(documents=[{"id": id} for id in ids])
            st.info(f"🧹 Cleared previous data: Removed {len(ids)} documents")
    except Exception as e:
        st.error(f"Error clearing index: {str(e)}")

def generate_embeddings(text):
    """Generate embeddings using Azure OpenAI"""
    response = openai_client.embeddings.create(
        input=text,
        model=AZURE_OPENAI_EMBEDDING_DEPLOYMENT
    )
    return response.data[0].embedding

def upload_documents(data):
    """Process and upload documents to Azure Cognitive Search"""
    delete_existing_documents()
    
    documents = []
    user_index_count = {}
    
    for item in data:
        # Track user indexes
        user_id = str(item.get("userId", "unknown"))
        user_index_count[user_id] = user_index_count.get(user_id, 0) + 1

        document = {
            "id": str(uuid.uuid4()),
            "userID": int(item.get("userId", 0)),
            "userName": item.get("userName", "unknown"),
            "type": item.get("type", ""),
            "description": item.get("description", ""),
            "lineNumber": item.get("lineNumber", ""),
            "text": item.get("text", ""),
            "timestamp": item.get("timestamp", ""),
            "emailAddress": item.get("additionalElements", {}).get("emailAddress", ""),
            "oesEmailId": item.get("additionalElements", {}).get("oesEmailId", ""),
            "embedding": generate_embeddings(item.get("text", ""))
        }
        documents.append(document)
    
    result = search_client.upload_documents(documents)
    
    # Save user index counts
    st.session_state.user_index_counts = user_index_count
    return len(documents)

def search_by_order(order_id):
    """Search for documents matching a specific order ID"""
    return search_client.search(
        search_text="*",
        filter=f"orderId eq '{order_id}'",
        select=["text", "userName", "timestamp"]
    )

def search_by_user(user_id):
    """Search for documents matching a specific user ID"""
    return search_client.search(
        search_text="*",
        filter=f"userID eq {user_id}",
        select=["text", "orderId", "timestamp"]
    )

def generate_summary(texts):
    """Generate AI-powered summary using GPT-4"""
    prompt = """Analyze these notes and create a comprehensive summary including:
    - Key user details
    - Technical issues
    - Timeline of events
    - Recommended actions
    
    Notes:
    {notes}
    """.format(notes="\n\n".join([f"- {text}" for text in texts]))

    response = openai_client.chat.completions.create(
        model="gpt-4",
        messages=[
            {"role": "system", "content": "You are an expert analyst."},
            {"role": "user", "content": prompt}
        ],
        temperature=0.3,
        max_tokens=500
    )
    return response.choices[0].message.content

# --------------------- Streamlit UI ---------------------
st.set_page_config("Document Analytics Hub", page_icon="📊", layout="wide")
st.title("📊 Document Analytics Hub")

# File Upload Section
with st.expander("📤 Upload Documents", expanded=True):
    uploaded_file = st.file_uploader("Upload JSON documents", type="json")
    if uploaded_file:
        create_index()
        try:
            data = json.load(uploaded_file)
            with st.spinner("Processing documents..."):
                count = upload_documents(data)
                st.success(f"✅ Successfully processed {count} documents")
                
                # Show user index counts
                st.subheader("👤 User Document Counts")
                for user_id, count in st.session_state.get("user_index_counts", {}).items():
                    st.write(f"- User {user_id}: {count} documents")
        except Exception as e:
            st.error(f"Error processing file: {str(e)}")

# Search Section
if 'user_index_counts' in st.session_state:
    st.divider()
    col1, col2 = st.columns(2)
    
    with col1:
        st.subheader("🔍 Search by Order ID")
        order_id = st.text_input("Enter Order ID:")
        if order_id:
            with st.spinner("Searching order..."):
                results = list(search_by_order(order_id))
                if results:
                    st.subheader(f"📄 Order {order_id} Documents")
                    for doc in results:
                        with st.expander(f"{doc['timestamp']} - {doc['userName']}"):
                            st.write(doc['text'])
    
    with col2:
        st.subheader("👤 Search by User ID")
        user_id = st.text_input("Enter User ID:")
        if user_id:
            with st.spinner("Searching user..."):
                results = list(search_by_user(user_id))
                if results:
                    st.subheader(f"📄 User {user_id} Documents")
                    texts = [doc['text'] for doc in results]
                    
                    for doc in results:
                        with st.expander(f"{doc['timestamp']} - Order {doc.get('orderId', '')}"):
                            st.write(doc['text'])
                    
                    st.subheader("📝 AI Summary")
                    summary = generate_summary(texts)
                    st.write(summary)

st.markdown("---")
st.markdown("🔒 Secure Document Management System | v2.2 | Azure AI Powered")


order id is not present for the filter so we can not use it what we can do is that we can search with order id directly without any filter if provided by user and then we can send the llm response to get the user id and from user id we can get how many index are there from our file and then for summarization we can again search with the order id with filter of user id and send n number of indexes all to llm to summarize according to order id