import os
import tempfile
import time
import streamlit as st
from git import Repo, GitCommandError
from openai import AzureOpenAI
import tiktoken
from datetime import datetime

# --------- File Handling ---------
class FileHandler:
    def __init__(self, repo_path, agent):
        self.repo_path = repo_path
        self.agent = agent
        self.files = []
        self.excluded_dirs = set()
        self.excluded_files = []
        self.total_scanned = 0
        self.encoder = tiktoken.get_encoding("cl100k_base")
        self._load_files()

    def _load_files(self):
        excluded_dir_names = {
            ".git", ".github", "node_modules", "venv", "dist", "build",
            "__pycache__", "bin", "obj", "packages", "lib", "libs",
            "third_party", "dependencies", ".idea", ".vscode", "coverage"
        }

        for root, dirs, files in os.walk(self.repo_path):
            original_dirs = set(dirs)
            dirs[:] = [d for d in dirs if d not in excluded_dir_names]
            
            for excluded_dir in (original_dirs - set(dirs)):
                excluded_path = os.path.join(root, excluded_dir)
                self.excluded_dirs.add(os.path.relpath(excluded_path, self.repo_path))

            for f in files:
                self.total_scanned += 1
                full_path = os.path.join(root, f)
                content = self.read_file_content(full_path)
                
                if not content:
                    self.excluded_files.append(os.path.relpath(full_path, self.repo_path))
                    continue
                
                try:
                    should_analyze = self.agent.should_analyze_file(
                        os.path.relpath(full_path, self.repo_path),
                        content[:2000]
                    )
                except Exception as e:
                    st.error(f"Error analyzing {full_path}: {e}")
                    should_analyze = False
                
                if should_analyze:
                    self.files.append(full_path)
                else:
                    self.excluded_files.append(os.path.relpath(full_path, self.repo_path))

    def read_file_content(self, file_path):
        try:
            with open(file_path, "r", encoding="utf-8") as f:
                return f.read()
        except UnicodeDecodeError:
            try:
                with open(file_path, "r", encoding="iso-8859-1") as f:
                    return f.read()
            except Exception:
                return None
        except Exception:
            return None

# --------- AI Agents ---------
class OpenAIAgent:
    def __init__(self, client, deployment):
        self.client = client
        self.deployment = deployment
        self.encoder = tiktoken.get_encoding("cl100k_base")
        self.activity_log = []

    def log_activity(self, agent_name, action, file_path=""):
        timestamp = datetime.now().strftime("%H:%M:%S")
        log_entry = f"{timestamp} | {agent_name.ljust(15)} | {action.ljust(25)} | {file_path}"
        self.activity_log.append(log_entry)
    
    def should_analyze_file(self, file_path, content_sample):
        self.log_activity("Filter Agent", "Evaluating file", file_path)
        system_msg = """Determine if a file contains original application logic crucial to understanding:
1. Project's primary objectives
2. Core business logic
3. Architectural patterns
4. Key workflows
5. Critical components
6. Does not much focus on Frontend but Give proper analysis of Backend with each file which are used or call by other files

Consider excluding:
- library code
- Generated/compiled files
- Configuration files
- Test files
- Documentation
- Minified assets
- Logs/build artifacts


Return ONLY 'YES' or 'NO' based on these criteria:
1. Is this original application code?
2. Does it contain business logic?
3. Is it human-written (not generated)?
4. Is it source code (not asset/config)?"""
        
        user_msg = f"File: {file_path}\nContent Sample:\n{content_sample}"
        
        response = self.client.chat.completions.create(
            model=self.deployment,
            messages=[
                {"role": "system", "content": system_msg},
                {"role": "user", "content": user_msg}
            ],
            temperature=0.1,
            max_tokens=10
        )
        decision = response.choices[0].message.content.strip().upper()
        return decision.startswith("YES")

    def summarize_file(self, file_path, content):
        self.log_activity("Analysis Agent", "Processing file", file_path)
        system_msg = """Analyze how this file contributes to the project's goals. Include:
1. Primary purpose in project context
2. Key technical implementations
3. Relationship to other components
4. Critical design decisions
Focus on the 'why' behind the code, not just 'what' it does."""
        
        response = self.client.chat.completions.create(
            model=self.deployment,
            messages=[
                {"role":"system", "content": system_msg},
                {"role":"user", "content": f"File: {file_path}\nContent:\n{content}"}
            ],
            temperature=0.1
        )
        return response.choices[0].message.content

    def merge_summaries(self, current_overview, new_summary):
        self.log_activity("Consolidation Agent", "Merging summaries")
        system_msg = """Synthesize analyses into a project blueprint:
[Project Purpose]
- Core objectives
- Key problem statements

[Implementation Strategy]
- Architectural patterns
- Technology choices
- Notable design decisions

[Crucial Components]
- Key files and their roles
- Component interactions
- Business logic locations

[Workflow Overview]
- Main execution flow
- Data transformation points
- Critical integration points"""
        
        response = self.client.chat.completions.create(
            model=self.deployment,
            messages=[
                {"role":"system", "content": system_msg},
                {"role":"user", "content": f"Current:\n{current_overview}\nNew:\n{new_summary}"}
            ],
            temperature=0.05
        )
        return response.choices[0].message.content

    def generate_improvements(self, final_summary):
        system_msg = """Propose technical improvements tied to project goals:
For each suggestion:
1. Objective alignment
2. Affected components
3. Implementation strategy
4. Expected outcomes
Include code samples showing current vs improved state."""
        
        response = self.client.chat.completions.create(
            model=self.deployment,
            messages=[
                {"role":"system", "content": system_msg},
                {"role":"user", "content": final_summary}
            ],
            temperature=0.2
        )
        return response.choices[0].message.content

# --------- Streamlit UI ---------
st.set_page_config(page_title="Project Analyzer", layout="wide")

def main():
    st.title("🔍 Project Architecture Analyzer")
    with st.sidebar:
        st.header("⚙️ Settings")
        azure_endpoint = st.text_input("Azure Endpoint", "https://your-resource.openai.azure.com/")
        api_key = st.text_input("API Key", type="password")
        deployment_name = st.text_input("Deployment Name", "gpt-4")
        analysis_mode = st.radio("Analysis Mode", ["Technical Blueprint", "Improvement Plan"])
        pat = st.text_input(
            "GitHub Personal Access Token (for private repos)",
            type="password",
            help="Create a PAT with 'repo' scope at https://github.com/settings/tokens"
        )

    repo_url = st.text_input("GitHub Repository URL", placeholder="https://github.com/user/repo")

    if st.button("Analyze Project"):
        run_analysis(repo_url, pat, azure_endpoint, api_key, deployment_name, analysis_mode)

def run_analysis(repo_url, pat, azure_endpoint, api_key, deployment_name, analysis_mode):
    client = AzureOpenAI(
        azure_endpoint=azure_endpoint,
        api_key=api_key,
        api_version="2023-05-15"
    )

    with tempfile.TemporaryDirectory() as tmp_dir:
        try:
            with st.spinner("🌀 Cloning repository..."):
                # Handle authentication for private repos
                if pat:
                    if not repo_url.startswith("https://"):
                        st.error("PAT can only be used with HTTPS URLs")
                        return
                    auth_repo_url = repo_url.replace("https://", f"https://{pat}@", 1)
                else:
                    auth_repo_url = repo_url

                Repo.clone_from(auth_repo_url, tmp_dir)
                st.success("Repository cloned successfully")

            agent = OpenAIAgent(client, deployment_name)
            file_handler = FileHandler(tmp_dir, agent)

            # Statistics Panel
            st.subheader("📊 Analysis Overview")
            cols = st.columns(4)
            cols[0].metric("Total Files", file_handler.total_scanned)
            cols[1].metric("Included Files", len(file_handler.files))
            cols[2].metric("Excluded Files", len(file_handler.excluded_files))
            cols[3].metric("Focus Ratio", 
                         f"{len(file_handler.files)/file_handler.total_scanned*100:.1f}%")

            # Processing Section
            consolidated_summary = "## Project Architecture Blueprint\n"
            total_files = len(file_handler.files)
            
            progress_bar = st.progress(0)
            status_box = st.empty()
            log_box = st.expander("🧠 Agent Activity Log")

            for idx, file_path in enumerate(file_handler.files):
                content = file_handler.read_file_content(file_path)
                rel_path = os.path.relpath(file_path, tmp_dir)
                
                with st.spinner(f"Analyzing {rel_path}..."):
                    summary = agent.summarize_file(rel_path, content)
                    consolidated_summary = agent.merge_summaries(consolidated_summary, summary)
                
                progress = (idx+1)/total_files
                progress_bar.progress(progress)
                status_box.markdown(f"""
                **Processing:** `{rel_path}`  
                **Progress:** {idx+1}/{total_files} ({progress*100:.1f}%)  
                **Summary Size:** {len(consolidated_summary)//1024} KB
                """)
                
                with log_box:
                    st.code("\n".join(agent.activity_log[-10:]))

            # Final Report
            st.subheader("📄 Architectural Analysis Report")
            if analysis_mode == "Technical Blueprint":
                tab1, tab2 = st.tabs(["Full Report", "Key Components"])
                with tab1:
                    st.markdown(consolidated_summary)
                with tab2:
                    st.markdown("### 🏗️ Architectural Pillars")
                    for file_path in file_handler.files[:10]:
                        st.markdown(f"- `{os.path.basename(file_path)}`")
            else:
                with st.spinner("Generating improvement plan..."):
                    improvements = agent.generate_improvements(consolidated_summary)
                st.markdown(improvements)

            # Excluded Files
            with st.expander("🚫 Excluded Items"):
                st.markdown("#### Directories")
                for d in sorted(file_handler.excluded_dirs):
                    st.markdown(f"- `{d}`")
                st.markdown("#### Files")
                for f in sorted(file_handler.excluded_files):
                    st.markdown(f"- `{f}`")

        except GitCommandError as e:
            st.error(f"Cloning failed: {str(e)}")
        except Exception as e:
            st.error(f"Analysis error: {str(e)}")

if __name__ == "__main__":
    main()

this is my streamlit code each things are make in one all agents all conntection code with azure with repo need to make it with different file structure also make azure credentials can also be taken from env if not provided