# filepath: /c:/Users/josem/Documents/RSE/TEMPLATES/rse-templates/src/rse_templates/main.py
import argparse
import subprocess
import os
import argparse
import sys
import re
import subprocess
from DjangoProjectCLI.DjangoProjectCLI import DjangoProjectCLI
from VueProjectCLI.VueProjectCLI import VueProjectCLI
from DjangoProjectCLI.consts import description_guidelines, django_project_run_message, vue_project_run_message, vue_gitignore_content, django_gitignore_content

def get_input(prompt, default=None, validation=None, error_msg="Entrada no válida. Por favor, inténtalo de nuevo."):
    while True:
        value = input(prompt).strip()
        if not value and default is not None:
            return default
        if validation and not validation(value):
            print(f"❌ {error_msg}")
        else:
            return value

def increment_directory_name(path, name):
    base_name = name
    match = re.search(r'(\d{2})$', name)
    if match:
        number = int(match.group(1))
        base_name = name[:-2]
    else:
        number = 0

    while os.path.exists(os.path.join(path, name)):
        number += 1
        name = f"{base_name}{number:02d}"
    return name

def get_multiline_input(prompt="\nIngrese una breve descripción del projecto:\n"):
    print(prompt)   
    print(description_guidelines)
    print("\nPresione Enter dos veces para finalizar la descripción\n")
    lines = []
    empty_line_count = 0
    
    while empty_line_count < 2:
        line = input()
        if line.strip() == "":
            empty_line_count += 1
        else:
            empty_line_count = 0
            lines.append(line)
    
    return "\n".join(lines)

def configure_git_remote(project_path: str):
    try:
        want_remote = get_input(
            "¿Desea conectar con un repositorio remoto? (y/n): ",
            default='n',
            validation=lambda x: x.lower() in ['y', 'n', 'yes', 'no'],
            error_msg="Por favor, responda con 'y' o 'n'"
        ).lower()

        if want_remote in ['y', 'yes']:
            remote_url = get_input(
                "Ingrese la URL del repositorio remoto: ",
                validation=lambda x: x.startswith(('https://', 'git@')),
                error_msg="Por favor, ingrese una URL válida de Git (https:// o git@)"
            )
            
            subprocess.run(['git', 'remote', 'add', 'origin', remote_url], cwd=project_path, check=True)
            subprocess.run(['git', 'branch', '-M', 'main'], cwd=project_path, check=True)
            print("✅ Repositorio remoto configurado exitosamente")
            
            push_now = get_input(
                "¿Desea hacer push al repositorio remoto ahora? (y/n): ",
                default='n',
                validation=lambda x: x.lower() in ['y', 'n', 'yes', 'no']
            ).lower()
            
            if push_now in ['y', 'yes']:
                subprocess.run(['git', 'push', '-u', 'origin', 'main'], cwd=project_path, check=True)
                print("✅ Código subido al repositorio remoto")
    
    except Exception as e:
        print(f"❌ Error al configurar el repositorio remoto: {str(e)}")

def add_description(description:str, project_path:str, host:str):
    
    readme_path = os.path.join(project_path, 'README.md')
    project_name = os.path.basename(project_path)
    if not description.strip():
        description = description_guidelines
    
    # Create content with project name and description
    content = f"# {project_name}\n\n{description}\n"
    if host:
        content += f"\n## Servidor\nEl servicio estará corriendo en el host: \n - `{host}`\n"
    
    
    try:
        # Write content to README.md (creates new file or overwrites existing)
        with open(readme_path, 'w', encoding='utf-8') as f:
            f.write(content)
        print(f"Successfully updated README.md at {readme_path}")
    except Exception as e:
        print(f"Error writing to README.md: {str(e)}")

def add_run_instructions(project_type, project_path):
    if project_type == 'django':
        file_path = os.path.join(project_path, 'README.md')
        with open(file_path, 'a') as file:
            file.write(django_project_run_message)
        print(django_project_run_message) 
    elif project_type == 'vue':
        file_path = os.path.join(project_path, 'README.md')
        with open(file_path, 'a') as file:
            file.write(f"""\n## Instrucciones:"
1. Muevase al directorio"
    - `cd {project_path}`
    """)
            file.write(vue_project_run_message)
        print(f"""\n## Instrucciones:"
1. Muevase al directorio"
    - `cd {project_path}`
    """, vue_project_run_message)


def verify_git_installation():
    try:
        subprocess.run(['git', '--version'], check=True, capture_output=True)
        return True
    except (subprocess.CalledProcessError, FileNotFoundError):
        print("❌ Git no está instalado en el sistema")
        return False


def is_git_repository(path: str) -> bool:
    return os.path.exists(os.path.join(path, '.git'))

def create_gitignore(project_path: str, project_type: str):
    if not verify_git_installation():
        sys.exit(1)
    try:
        if is_git_repository(project_path):
            print("⚠️ Ya existe un repositorio Git en este directorio")
            raise(Exception("Repositorio Git existente"))
        # Create .gitignore based on project type
        gitignore_content = vue_gitignore_content if project_type == 'vue' else django_gitignore_content
        with open(os.path.join(project_path, '.gitignore'), 'w') as f:
            f.write(gitignore_content)
        # Initialize git repo and create initial commit
        subprocess.run(['git', 'init'], cwd=project_path, check=True)
        subprocess.run(['git', 'add', '.'], cwd=project_path, check=True)
        subprocess.run(['git', 'commit', '-m', 'Initial commit'], cwd=project_path, check=True)
        
        print("✅ Repositorio Git inicializado y primer commit creado")
        configure_git_remote(project_path)
    except Exception as e:
        print(f"❌ Error al configurar Git: {str(e)}")

def main():
    parser = argparse.ArgumentParser(description='CLI para generar proyectos Django o Vue con configuraciones específicas')
    parser.add_argument('--project_type', choices=['django', 'vue'], help='Tipo de proyecto a crear (django/vue)')
    parser.add_argument('--project_name', help='Nombre del proyecto')
    parser.add_argument('--project_path', help='Ruta donde se creará el proyecto (default: directorio actual)')
    parser.add_argument('--https_enabled', action='store_true', help='Configurar desarrollo local con HTTPS')
    parser.add_argument('--host', help='Host para el proyecto (default: localhost)')
    args = parser.parse_args()

    project_type = args.project_type or get_input(
        "¿Desea crear un proyecto de Django o Vue? (django/vue): ",
        validation=lambda x: x.lower() in ['django', 'vue'],
        error_msg="Por favor, ingrese 'django' o 'vue'"
    )

    project_name = args.project_name or get_input(
        "Nombre del proyecto: ",
        validation=lambda x: re.match(r'^[a-zA-Z0-9-_]+$', re.sub(r'\s+', '-', x)),
        error_msg="El nombre del proyecto solo puede contener letras, números y guiones"
    )
    project_name = re.sub(r'\s+', '-', project_name)
    if not re.match(r'^[a-zA-Z0-9-_]+$', project_name):
        print("❌ El nombre del proyecto solo puede contener letras, números y guiones")
        sys.exit(1)

    project_path = args.project_path or get_input(
        "Ruta donde se creará el proyecto (default: directorio actual): ",
        default=os.getcwd(),
        validation=os.path.isdir,
        error_msg="La ruta especificada no existe o no es un directorio válido"
    )

    if os.path.exists(os.path.join(project_path, project_name)):
        print(f"❌ Ya existe una carpeta con el nombre '{project_name}' en el directorio especificado.")
        project_name = increment_directory_name(project_path, project_name)
        print(f"✅ Se ha incrementado el nombre del proyecto a '{project_name}'")

    https_enabled = args.https_enabled or get_input(
        "¿Desea configurar el desarrollo local con HTTPS? (y/n): ",
        default='n',
        validation=lambda x: x.lower() in ['y', 'n', 'yes', 'no'],
        error_msg="Por favor, responda con 'y' o 'n'"
    ).lower() in ['y', 'yes']

    host = args.host or get_input(
        "Host para el proyecto (default: localhost): ",
        default='localhost',
        validation=lambda x: re.match(r'^[a-zA-Z0-9.-]+$', x),
        error_msg="El host solo puede contener letras, números, puntos y guiones"
    )
    confirmation = get_input(
        f"¿Confirma que desea crear un projecto con las especificaciones?\n Tipo: {project_type}\n Nombre: {project_name}\n Ruta: {project_path}\n HTTPS habilitado: {https_enabled} \n Host: {host}\n\n(y/n):  ",
        default='n', validation=lambda x: x in ['y', 'n'])
    if confirmation == 'no':
        sys.exit(1)
    if project_type == 'django':
        cli = DjangoProjectCLI(project_name)
    elif project_type == 'vue':
        cli = VueProjectCLI(project_name)
    # noinspection PyUnboundLocalVariable
    cli.create_project(project_path, https_enabled, host)

    description = get_multiline_input()
    full_path = project_path + "\\" + project_name
    add_description(description, full_path, host)
    
    create_gitignore(full_path, project_type)
    add_run_instructions(project_type, full_path)



if __name__ == "__main__":
    main()