import requests
import json
import os
import argparse
from dotenv import load_dotenv

# Cargar variables del archivo .env
load_dotenv()

# --- Configuración (obtenida de variables de entorno) ---
GITEA_API_KEY = os.getenv("GITEA_API_KEY")
GITEA_API_KEY_URL = os.getenv("GITEA_API_KEY_URL")
GITEA_USERNAME = os.getenv("GITEA_USERNAME")
GITEA_REPO_NAME = os.getenv("GITEA_REPO_NAME")

# Extraer la URL base de Gitea de GITEA_API_KEY_URL
GITEA_BASE_URL = GITEA_API_KEY_URL.split('/api/v1/')[0]

def _make_gitea_request(method, endpoint, payload=None):
    """Helper function to make authenticated requests to Gitea API."""
    api_url = f"{GITEA_BASE_URL}/api/v1/{endpoint}"
    headers = {
        "Accept": "application/json",
        "Authorization": f"token {GITEA_API_KEY}",
        "Content-Type": "application/json"
    }
    try:
        if method == "GET":
            response = requests.get(api_url, headers=headers)
        elif method == "POST":
            response = requests.post(api_url, headers=headers, data=json.dumps(payload))
        elif method == "PATCH":
            response = requests.patch(api_url, headers=headers, data=json.dumps(payload))
        else:
            raise ValueError(f"Unsupported HTTP method: {method}")

        response.raise_for_status()
        # Some endpoints return empty responses (like merge)
        if response.text:
            return response.json()
        return {}
    except requests.exceptions.RequestException as e:
        print(f"Error en la solicitud {method} a {api_url}: {e}")
        if hasattr(e, 'response') and e.response is not None:
            print(f"Respuesta del servidor: {e.response.text}")
        raise

def create_issue(title, body_file):
    """Creates a new issue in the Gitea repository."""
    try:
        with open(body_file, 'r', encoding='utf-8') as f:
            body = f.read()
    except FileNotFoundError:
        print(f"Error: El archivo de cuerpo '{body_file}' no fue encontrado.")
        return

    endpoint = f"repos/{GITEA_USERNAME}/{GITEA_REPO_NAME}/issues"
    payload = {
        "title": title,
        "body": body,
        "closed": False
    }
    print(f"Creando issue: '{title}' desde archivo '{body_file}'...")
    issue_data = _make_gitea_request("POST", endpoint, payload)
    print(f"Issue creado exitosamente:")
    print(f"  Número: {issue_data['number']}")
    print(f"  Título: {issue_data['title']}")
    print(f"  URL: {issue_data['html_url']}")

def create_pull_request(head_branch, base_branch, title, body_file):
    """Creates a new pull request in the Gitea repository."""
    try:
        with open(body_file, 'r', encoding='utf-8') as f:
            body = f.read()
    except FileNotFoundError:
        print(f"Error: El archivo de cuerpo '{body_file}' no fue encontrado.")
        return

    endpoint = f"repos/{GITEA_USERNAME}/{GITEA_REPO_NAME}/pulls"
    payload = {
        "head": head_branch,
        "base": base_branch,
        "title": title,
        "body": body
    }
    print(f"Creando Pull Request: '{title}' de '{head_branch}' a '{base_branch}' desde archivo '{body_file}'...")
    pr_data = _make_gitea_request("POST", endpoint, payload)
    print(f"Pull Request creado exitosamente:")
    print(f"  Número: {pr_data['number']}")
    print(f"  Título: {pr_data['title']}")
    print(f"  URL: {pr_data['html_url']}")

def comment_issue(issue_number, body):
    """Adds a comment to an existing issue."""
    endpoint = f"repos/{GITEA_USERNAME}/{GITEA_REPO_NAME}/issues/{issue_number}/comments"
    payload = {
        "body": body
    }
    print(f"Añadiendo comentario al issue #{issue_number}...")
    _make_gitea_request("POST", endpoint, payload)
    print(f"Comentario añadido al issue #{issue_number} exitosamente.")

def close_issue(issue_number):
    """Closes an existing issue."""
    endpoint = f"repos/{GITEA_USERNAME}/{GITEA_REPO_NAME}/issues/{issue_number}"
    payload = {
        "state": "closed"
    }
    print(f"Cerrando issue #{issue_number}...")
    _make_gitea_request("PATCH", endpoint, payload)
    print(f"Issue #{issue_number} cerrado exitosamente.")

def get_issue_details(issue_number):
    """Gets details and comments for a specific issue."""
    # Get issue details
    endpoint = f"repos/{GITEA_USERNAME}/{GITEA_REPO_NAME}/issues/{issue_number}"
    print(f"Obteniendo detalles del issue #{issue_number}...")
    
    try:
        issue = _make_gitea_request("GET", endpoint)
        
        # Display issue information
        print(f"\n{'=' * 80}")
        print(f"Issue #{issue.get('number', 'N/A')}: {issue.get('title', 'Sin título')}")
        print(f"{'=' * 80}")
        print(f"Estado: {'Abierto' if issue.get('state') == 'open' else 'Cerrado'}")
        print(f"Autor: {issue.get('user', {}).get('login', 'Desconocido')}")
        print(f"Creado: {issue.get('created_at', '').replace('T', ' ').split('+')[0] if issue.get('created_at') else 'N/A'}")
        
        if issue.get('closed_at'):
            print(f"Cerrado: {issue.get('closed_at', '').replace('T', ' ').split('+')[0]}")
        
        labels = [label.get('name', '') for label in issue.get('labels', [])]
        if labels:
            print(f"Etiquetas: {', '.join(labels)}")
        
        print(f"URL: {issue.get('html_url', 'N/A')}")
        
        print(f"\nDescripción:")
        print("-" * 40)
        print(issue.get('body', 'Sin descripción'))
        
        # Get comments
        comments_endpoint = f"{endpoint}/comments"
        comments = _make_gitea_request("GET", comments_endpoint)
        
        if comments:
            print(f"\nComentarios ({len(comments)}):")
            print("-" * 40)
            for i, comment in enumerate(comments, 1):
                author = comment.get('user', {}).get('login', 'Desconocido')
                created = comment.get('created_at', '').replace('T', ' ').split('+')[0] if comment.get('created_at') else 'N/A'
                body = comment.get('body', '')
                
                print(f"\nComentario {i} - {author} ({created}):")
                print(body)
                if i < len(comments):
                    print("-" * 40)
        else:
            print(f"\nNo hay comentarios en este issue.")
        
        print(f"\n{'=' * 80}\n")
        
    except Exception as e:
        print(f"Error al obtener el issue #{issue_number}: {e}")

def list_open_issues():
    """Lists all open issues in the repository."""
    endpoint = f"repos/{GITEA_USERNAME}/{GITEA_REPO_NAME}/issues"
    print(f"Obteniendo issues abiertos del repositorio {GITEA_REPO_NAME}...")
    
    try:
        # Get open issues (state=open is default)
        issues = _make_gitea_request("GET", endpoint + "?state=open")
        
        if not issues:
            print("No hay issues abiertos en este momento.")
            return
        
        print(f"\nIssues abiertos ({len(issues)}):")
        print("-" * 80)
        
        for issue in issues:
            # Format issue information
            number = issue.get('number', 'N/A')
            title = issue.get('title', 'Sin título')
            author = issue.get('user', {}).get('login', 'Desconocido')
            created = issue.get('created_at', '').split('T')[0] if issue.get('created_at') else 'N/A'
            labels = [label.get('name', '') for label in issue.get('labels', [])]
            labels_str = f" [{', '.join(labels)}]" if labels else ""
            
            print(f"#{number}: {title}{labels_str}")
            print(f"  Autor: {author} | Creado: {created}")
            print(f"  URL: {issue.get('html_url', 'N/A')}")
            print()
        
        print("-" * 80)
        print(f"Total: {len(issues)} issues abiertos")
        
    except Exception as e:
        print(f"Error al obtener los issues: {e}")

def merge_pull_request(pr_number, merge_method="merge"):
    """Merges a pull request (only allowed to dev branch)."""
    # First, get PR information to check the base branch
    endpoint = f"repos/{GITEA_USERNAME}/{GITEA_REPO_NAME}/pulls/{pr_number}"
    print(f"Obteniendo información del PR #{pr_number}...")
    pr_info = _make_gitea_request("GET", endpoint)
    
    # Check if PR is already merged
    if pr_info.get('merged', False):
        print(f"INFO: El PR #{pr_number} ya fue mergeado.")
        return
    
    # Check if PR is closed
    if pr_info.get('state') == 'closed':
        print(f"ERROR: El PR #{pr_number} está cerrado y no se puede mergear.")
        return
    
    # Check if base branch is 'dev'
    base_branch = pr_info.get('base', {}).get('ref', '')
    if base_branch != 'dev':
        print(f"ERROR: Solo se permite hacer merge a la rama 'dev'.")
        print(f"Este PR tiene como destino la rama '{base_branch}'.")
        return
    
    # Check if PR is mergeable
    if not pr_info.get('mergeable', False):
        print(f"ERROR: El PR #{pr_number} no se puede mergear. Puede tener conflictos.")
        return
    
    # Proceed with merge
    merge_endpoint = f"repos/{GITEA_USERNAME}/{GITEA_REPO_NAME}/pulls/{pr_number}/merge"
    payload = {
        "do": merge_method,
        "merge_title_field": pr_info.get('title', ''),
        "merge_message_field": f"Merge pull request #{pr_number} from {pr_info.get('head', {}).get('ref', '')}\n\n{pr_info.get('title', '')}"
    }
    
    print(f"Haciendo merge del PR #{pr_number} a la rama 'dev' usando método '{merge_method}'...")
    try:
        _make_gitea_request("POST", merge_endpoint, payload)
        print(f"PR #{pr_number} mergeado exitosamente a la rama 'dev'.")
    except Exception as e:
        print(f"Error al hacer merge del PR #{pr_number}: {e}")

def main():
    parser = argparse.ArgumentParser(description="Helper CLI para interactuar con la API de Gitea.")
    subparsers = parser.add_subparsers(dest="command", help="Comandos disponibles")

    # Subparser para crear issue
    create_issue_parser = subparsers.add_parser("create-issue", help="Crea un nuevo issue.")
    create_issue_parser.add_argument("--title", required=True, help="Título del issue.")
    create_issue_parser.add_argument("--body-file", required=True, help="Ruta al archivo de texto con el cuerpo/descripción del issue.")

    # Subparser para crear pull request
    create_pr_parser = subparsers.add_parser("create-pr", help="Crea un nuevo pull request.")
    create_pr_parser.add_argument("--head", required=True, help="Rama de origen (head branch).")
    create_pr_parser.add_argument("--base", required=True, help="Rama de destino (base branch).")
    create_pr_parser.add_argument("--title", required=True, help="Título del pull request.")
    create_pr_parser.add_argument("--body-file", required=True, help="Ruta al archivo de texto con el cuerpo/descripción del pull request.")

    # Subparser para comentar issue
    comment_issue_parser = subparsers.add_parser("comment-issue", help="Añade un comentario a un issue existente.")
    comment_issue_parser.add_argument("--issue-number", type=int, required=True, help="Número del issue.")
    comment_issue_parser.add_argument("--body", required=True, help="Cuerpo del comentario (soporta multilínea con \n).")

    # Subparser para cerrar issue
    close_issue_parser = subparsers.add_parser("close-issue", help="Cierra un issue existente.")
    close_issue_parser.add_argument("--issue-number", type=int, required=True, help="Número del issue a cerrar.")
    
    # Subparser para merge PR
    merge_pr_parser = subparsers.add_parser("merge-pr", help="Hace merge de un pull request (solo a rama dev).")
    merge_pr_parser.add_argument("--pr-number", type=int, required=True, help="Número del pull request.")
    merge_pr_parser.add_argument("--merge-method", choices=["merge", "squash", "rebase"], default="merge",
                                help="Método de merge: merge, squash o rebase (default: merge).")
    
    # Subparser para listar issues abiertos
    list_issues_parser = subparsers.add_parser("list-open-issues", help="Lista todos los issues abiertos del repositorio.")
    
    # Subparser para obtener detalles de un issue
    get_issue_parser = subparsers.add_parser("get-issue", help="Obtiene detalles y comentarios de un issue específico.")
    get_issue_parser.add_argument("--issue-number", type=int, required=True, help="Número del issue a consultar.")

    args = parser.parse_args()

    if args.command == "create-issue":
        create_issue(args.title, args.body_file)
    elif args.command == "create-pr":
        create_pull_request(args.head, args.base, args.title, args.body_file)
    elif args.command == "comment-issue":
        comment_issue(args.issue_number, args.body)
    elif args.command == "close-issue":
        close_issue(args.issue_number)
    elif args.command == "merge-pr":
        merge_pull_request(args.pr_number, args.merge_method)
    elif args.command == "list-open-issues":
        list_open_issues()
    elif args.command == "get-issue":
        get_issue_details(args.issue_number)
    else:
        parser.print_help()

if __name__ == "__main__":
    main()
