import os
import requests
import json
import chromadb
from chromadb.utils import embedding_functions
from datetime import datetime
from typing import Dict, List, Set, Tuple, Optional

# Configuration
OLLAMA_API = "http://localhost:11434/api/generate"
MODEL_NAME = "llama3.2"  # Updated to latest stable version
DEBUG = True
MAX_FILE_SIZE = 5000  # Max characters to send to API
TIMEOUT = 120  # seconds

def debug_print(message: str) -> None:
    """Print debug messages if DEBUG is enabled"""
    if DEBUG:
        print(f"[DEBUG] {datetime.now().strftime('%H:%M:%S')} {message}")

def analyze_file_with_ollama(file_path: str, content: str) -> List[str]:
    """Analyze file content using Ollama API to detect navigation targets"""
    prompt = f"""Analyze this Flutter file and identify all screen navigation targets.
Return ONLY JSON in this format:
{{"related_screens": ["route1", "route2"]}}

Important:
1. Only return screens that are explicitly navigated to (push, pop, etc.)
2. Include both full paths and screen names
3. Skip non-existent screens

Code:
```dart
{content[:MAX_FILE_SIZE]}
```"""
    
    try:
        response = requests.post(
            OLLAMA_API,
            json={
                "model": MODEL_NAME,
                "prompt": prompt,
                "format": "json",
                "stream": False,
                "options": {"temperature": 0.3}  # More deterministic output
            },
            timeout=TIMEOUT
        )
        response.raise_for_status()
        result = response.json().get("response", "{}")
        
        # Handle different response formats
        try:
            if isinstance(result, str):
                # Sometimes Ollama wraps JSON in markdown
                if result.startswith("```json"):
                    result = result[7:-3].strip()
                result = json.loads(result)
            
            screens = result.get("related_screens", [])
            return [s for s in screens if isinstance(s, str)]
        except json.JSONDecodeError as e:
            debug_print(f"Failed to parse response: {e}\nResponse: {result}")
            return []
            
    except requests.exceptions.RequestException as e:
        debug_print(f"API request failed: {str(e)}")
        return []
    except Exception as e:
        debug_print(f"Unexpected error: {str(e)}")
        return []

def normalize_path(path: str, project_path: str) -> Tuple[str, str]:
    """Normalize paths to consistent format and return absolute/normalized paths"""
    # Handle common Dart imports
    if path.startswith('package:'):
        path = path.replace('package:', 'lib/')
    
    if not path.endswith('.dart'):
        path += '.dart'
    if not path.startswith('lib/'):
        path = os.path.join('lib', path)
    
    abs_path = os.path.join(project_path, path)
    norm_path = os.path.relpath(abs_path, project_path)
    
    return abs_path, norm_path

def find_dart_files(project_path: str) -> Set[str]:
    """Recursively find all Dart files in the project"""
    dart_files = set()
    lib_path = os.path.join(project_path, 'lib')
    
    if not os.path.exists(lib_path):
        debug_print(f"Warning: 'lib' directory not found in {project_path}")
        return dart_files
    
    for root, _, files in os.walk(lib_path):
        for file in files:
            if file.endswith('.dart'):
                full_path = os.path.relpath(os.path.join(root, file), project_path)
                dart_files.add(full_path)
    
    return dart_files

def process_project(project_path: str) -> Dict[str, List[str]]:
    """Process the entire Flutter project to find navigation connections"""
    debug_print(f"Scanning project: {project_path}")
    
    # Initialize ChromaDB
    chroma_client = chromadb.PersistentClient(path=".vector_db")
    collection = chroma_client.get_or_create_collection(
        name="flutter_navigation",
        metadata={"model": MODEL_NAME, "created": datetime.now().isoformat()}
    )
    
    all_files = find_dart_files(project_path)
    debug_print(f"Found {len(all_files)} Dart files")
    
    connections = {}
    for i, file_path in enumerate(all_files, 1):
        debug_print(f"\n[{i}/{len(all_files)}] Analyzing: {file_path}")
        
        try:
            with open(os.path.join(project_path, file_path), 'r', encoding='utf-8') as f:
                content = f.read()
                related = analyze_file_with_ollama(file_path, content)
                
                valid_connections = []
                for target in related:
                    abs_path, norm_path = normalize_path(target, project_path)
                    if os.path.exists(abs_path) and norm_path in all_files:
                        valid_connections.append(norm_path)
                    else:
                        debug_print(f"Target file not found: {target}")
                
                if valid_connections:
                    connections[file_path] = valid_connections
                    debug_print(f"Found connections: {valid_connections}")
        
        except UnicodeDecodeError:
            debug_print(f"Skipping binary file: {file_path}")
        except Exception as e:
            debug_print(f"Error processing {file_path}: {str(e)}")
    
    return connections

def generate_mermaid_diagram(connections: Dict[str, List[str]]) -> str:
    """Generate Mermaid diagram from navigation connections"""
    debug_print("Generating diagram...")
    
    mermaid_lines = ["graph TD"]
    used_pairs = set()
    node_names = {}
    
    # Create consistent node names
    for path in set().union(*connections.values(), connections.keys()):
        name = os.path.splitext(os.path.basename(path))[0]
        node_names[path] = name
    
    # Add connections
    for source, targets in connections.items():
        src_name = node_names[source]
        for target in targets:
            dst_name = node_names[target]
            pair = (src_name, dst_name)
            if pair not in used_pairs:
                mermaid_lines.append(f"    {src_name} --> {dst_name}")
                used_pairs.add(pair)
    
    if len(mermaid_lines) == 1:
        mermaid_lines.append("    NoConnections[No navigation links found]")
    
    return "```mermaid\n" + "\n".join(mermaid_lines) + "\n```"

def generate_report(connections: Dict[str, List[str]], project_path: str) -> str:
    """Generate full markdown report"""
    timestamp = datetime.now().strftime('%d.%m.%Y %H:%M')
    diagram = generate_mermaid_diagram(connections)
    
    # Count unique connections
    unique_connections = set()
    for src, targets in connections.items():
        for tgt in targets:
            unique_connections.add((src, tgt))
    
    return f"""# Flutter Navigation Analysis Report
*Generated {timestamp}*

## Project Overview
- **Project Path**: `{project_path}`
- **Model Used**: `{MODEL_NAME}`
- **Files Analyzed**: {len(connections)}
- **Unique Navigation Links Found**: {len(unique_connections)}

## Navigation Diagram

{diagram}

## Detailed Connections
{"No navigation links found" if not connections else ""}
""" + "\n".join(
    f"- `{src}` → `{', '.join(tgts)}`"
    for src, tgts in connections.items()
)

def main():
    print(f"Configuration:\nOLLAMA_API: {OLLAMA_API}\nModel: {MODEL_NAME}")
    
    project_path = "/Users/lk/Developer/type-vitrina/vrts/vrts-source-copy"
    if not os.path.exists(project_path):
        project_path = input("Enter project path: ").strip()
        if not os.path.exists(project_path):
            print("Error: Path does not exist")
            return
    
    print("\nStarting analysis...")
    connections = process_project(project_path)
    
    print("\nGenerating report...")
    report = generate_report(connections, project_path)
    
    report_path = "navigation_report.md"
    with open(report_path, 'w', encoding='utf-8') as f:
        f.write(report)
    
    print(f"\nDone! Report saved to {report_path}")
    print("\nDiagram preview:")
    print(generate_mermaid_diagram(connections))

if __name__ == "__main__":
    main()


lk@lks-MacBook-Air ollama % p3 fm3.py
Configuration:
OLLAMA_API: http://localhost:11434/api/generate
Model: llama3.2

Starting analysis...
[DEBUG] 04:20:51 Scanning project: /Users/lk/Developer/type-vitrina/vrts/vrts-source-copy
[DEBUG] 04:20:51 Found 40 Dart files
[DEBUG] 04:20:51 
[1/40] Analyzing: lib/screens/menu/phone_input_screen.dart
[DEBUG] 04:21:04 Target file not found: home_screen
[DEBUG] 04:21:04 
[2/40] Analyzing: lib/widgets/phone_confirmation_widget.dart
[DEBUG] 04:21:14 Target file not found: PhoneConfirmationSheet
[DEBUG] 04:21:14 Target file not found: HomeScreen
[DEBUG] 04:21:14 
[3/40] Analyzing: lib/screens/home_screen.dart


fix using my code and use 3.2 version