import os
import json
import networkx as nx
import subprocess
import cssutils
import logging
from pathlib import Path

# Configure logging
logging.basicConfig(level=logging.INFO)
log = logging.getLogger(__name__)

# Configure cssutils to ignore noisy error messages
cssutils.log.setLevel(logging.CRITICAL)

def analyze_react_project(project_path: str) -> dict:
    """
    Analyzes a React project, building a graph of its components and styles.

    Args:
        project_path: The root path of the React project.

    Returns:
        A dictionary containing the component graph and analysis report.
    """
    log.info(f"Starting analysis of project at: {project_path}")
    graph = nx.DiGraph()
    
    # Supported extensions for react/js/ts files
    supported_exts = ('.js', '.jsx', '.ts', '.tsx')
    
    # Path to the parser script
    parser_script_path = Path(__file__).parent / 'parser.js'
    if not parser_script_path.exists():
        raise FileNotFoundError(f"Parser script not found at {parser_script_path}")

    for root, _, files in os.walk(project_path):
        # Ignore node_modules and build directories
        if 'node_modules' in root or 'build' in root or 'dist' in root:
            continue
            
        for file in files:
            file_path = os.path.join(root, file)
            relative_path = os.path.relpath(file_path, project_path)

            # Add a node for every file
            graph.add_node(relative_path, type='file')

            if file.endswith(supported_exts):
                graph.nodes[relative_path]['language'] = 'typescript'
                try:
                    # Call the external node.js parser
                    result = subprocess.run(
                        ['node', str(parser_script_path), file_path],
                        capture_output=True,
                        text=True,
                        check=True
                    )
                    # The AST is now in result.stdout as a JSON string.
                    # ast = json.loads(result.stdout)
                    
                except subprocess.CalledProcessError as e:
                    log.error(f"Failed to parse {file_path} with babel. Error: {e.stderr}")
                except Exception as e:
                    log.error(f"Could not process file {file_path}: {e}")

            elif file.endswith('.css'):
                graph.nodes[relative_path]['language'] = 'css'
                try:
                    # Placeholder for CSS parsing
                    # sheet = cssutils.parseFile(file_path)
                    pass
                except Exception as e:
                    log.error(f"Could not parse css file {file_path}: {e}")

    log.info(f"Analysis complete. Found {graph.number_of_nodes()} files.")
    
    # Convert graph to a serializable format
    serializable_graph = nx.node_link_data(graph)
    
    return serializable_graph

def save_analysis_to_project(project_path: str, analysis_data: dict):
    """
    Saves the analysis data to a file in the project's .dss directory.
    """
    # In the context of dss-mvp1, the .dss directory for metadata might be at the root.
    dss_dir = os.path.join(project_path, '.dss')
    os.makedirs(dss_dir, exist_ok=True)
    
    output_path = os.path.join(dss_dir, 'analysis_graph.json')
    
    with open(output_path, 'w', encoding='utf-8') as f:
        json.dump(analysis_data, f, indent=2)
        
    log.info(f"Analysis data saved to {output_path}")

def run_project_analysis(project_path: str):
    """
    High-level function to run analysis and save the result.
    """
    analysis_result = analyze_react_project(project_path)
    save_analysis_to_project(project_path, analysis_result)
    return analysis_result

def _read_ds_config(project_path: str) -> dict:
    """
    Reads the ds.config.json file from the project root.
    """
    config_path = os.path.join(project_path, 'ds.config.json')
    if not os.path.exists(config_path):
        return {}
    try:
        with open(config_path, 'r', encoding='utf-8') as f:
            return json.load(f)
    except Exception as e:
        log.error(f"Could not read or parse ds.config.json: {e}")
        return {}

def export_project_context(project_path: str) -> dict:
    """
    Exports a comprehensive project context for agents.

    This context includes the analysis graph, project configuration,
    and a summary of the project's structure.
    """
    analysis_graph_path = os.path.join(project_path, '.dss', 'analysis_graph.json')

    if not os.path.exists(analysis_graph_path):
        # If the analysis hasn't been run, run it first.
        log.info(f"Analysis graph not found for {project_path}. Running analysis now.")
        run_project_analysis(project_path)

    try:
        with open(analysis_graph_path, 'r', encoding='utf-8') as f:
            analysis_graph = json.load(f)
    except Exception as e:
        log.error(f"Could not read analysis graph for {project_path}: {e}")
        analysis_graph = {}

    project_config = _read_ds_config(project_path)

    # Create the project context
    project_context = {
        "schema_version": "1.0",
        "project_name": project_config.get("name", "Unknown"),
        "analysis_summary": {
            "file_nodes": len(analysis_graph.get("nodes", [])),
            "dependencies": len(analysis_graph.get("links", [])),
            "analyzed_at": log.info(f"Analysis data saved to {analysis_graph_path}")
        },
        "project_config": project_config,
        "analysis_graph": analysis_graph,
    }
    
    return project_context

if __name__ == '__main__':
    # This is for standalone testing of the analyzer.
    # Provide a path to a project to test.
    # e.g., python -m dss.analyze.project_analyzer ../../admin-ui
    import sys
    if len(sys.argv) > 1:
        target_project_path = sys.argv[1]
        if not os.path.isdir(target_project_path):
            print(f"Error: Path '{target_project_path}' is not a valid directory.")
            sys.exit(1)
            
        run_project_analysis(target_project_path)
    else:
        print("Usage: python -m dss.analyze.project_analyzer <path_to_project>")

