import json
import os
import shutil
import tempfile
from project_generator.domain.models.project_models import ProjectRequest, GeneratedProjectInfo
from cookiecutter.main import cookiecutter
from cookiecutter.exceptions import CookiecutterException

class CookiecutterAdapter:
    def generate(self, project_data: ProjectRequest, no_zip: bool = False) -> GeneratedProjectInfo:
        project_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..'))
        original_scaffold_path = os.path.join(project_root, 'scaffold')
        generation_utils_source_path = os.path.join(project_root, 'mcp_generator', 'infrastructure', 'generation_utils.py')

        temp_dir = tempfile.mkdtemp()
        generated_info = GeneratedProjectInfo(temp_dir=temp_dir)

        try:
            copied_scaffold_path = os.path.join(temp_dir, 'scaffold_template')
            shutil.copytree(original_scaffold_path, copied_scaffold_path)

            hook_dir = os.path.join(copied_scaffold_path, 'hooks')
            os.makedirs(hook_dir, exist_ok=True)
            generation_utils_dest_path = os.path.join(hook_dir, 'generation_utils.py')
            if os.path.exists(generation_utils_source_path):
                shutil.copy2(generation_utils_source_path, generation_utils_dest_path)
            else:
                print(f"ADVERTENCIA: No se encontró generation_utils.py en {generation_utils_source_path}")

            cookiecutter_json_path = os.path.join(copied_scaffold_path, 'cookiecutter.json')
            try:
                with open(cookiecutter_json_path, 'r') as f:
                    config_data = json.load(f)
                config_data['dynamic_tools'] = "[]"
                config_data['dynamic_prompts'] = "[]"
                config_data['dynamic_resources'] = "[]"
                with open(cookiecutter_json_path, 'w') as f:
                    json.dump(config_data, f, indent=4)
            except Exception as e:
                print(f"ADVERTENCIA: No se pudo modificar cookiecutter.json: {e}")

            output_dir_temp = os.path.join(temp_dir, 'output')
            os.makedirs(output_dir_temp)

            project_slug = project_data.project_name.lower().replace(' ', '_').replace('-', '_')

            extra_context = {
                "project_name": project_data.project_name,
                "dynamic_tools": json.dumps(project_data.dynamic_tools),
                "dynamic_prompts": json.dumps(project_data.dynamic_prompts),
                "dynamic_resources": json.dumps(project_data.dynamic_resources)
            }

            cookiecutter(
                template=copied_scaffold_path,
                no_input=True,
                extra_context=extra_context,
                output_dir=output_dir_temp,
                replay=False,
                overwrite_if_exists=True
            )

            project_output_path_temp = os.path.join(output_dir_temp, project_slug)

            if not os.path.exists(project_output_path_temp):
                 raise RuntimeError(f"Cookiecutter no generó el directorio esperado: {project_output_path_temp}")

            if no_zip:
                generated_info.output_path = project_output_path_temp
            else:
                zip_base_name = os.path.join(temp_dir, project_slug)
                shutil.make_archive(
                    base_name=zip_base_name,
                    format='zip',
                    root_dir=output_dir_temp,
                    base_dir=project_slug
                )
                generated_info.zip_path = f"{zip_base_name}.zip"
                generated_info.zip_filename = f"{project_slug}.zip"

            return generated_info

        except (CookiecutterException, OSError, IOError, RuntimeError) as e:
            if os.path.exists(temp_dir):
                 shutil.rmtree(temp_dir)
            print(f"Error detallado en CookiecutterAdapter: {type(e).__name__} - {e}")
            raise RuntimeError(f"Error generating project with Cookiecutter: {e}") from e