import click
import sys
import asyncio
import json
import base64
import mimetypes
from loguru import logger
from .client import SigaClient

@click.group()
@click.option('--username', envvar='SIGA_USERNAME', help='Siga username')
@click.option('--password', envvar='SIGA_PASSWORD', help='Siga password')
@click.option('--instituicao', envvar='SIGA_INSTITUICAO', help='Institution code')
@click.option('--verify/--no-verify', default=True, help='Verify SSL certificates')
@click.pass_context
def cli(ctx, username, password, instituicao, verify):
    """Activesoft Siga CLI automation tool."""
    # Only enforce if a command is actually being run (not help)
    if ctx.invoked_subcommand and ctx.invoked_subcommand != 'help':
        if not username or not password or not instituicao:
            click.echo("Error: Username, password, and institution must be provided via arguments or environment variables.", err=True)
            ctx.exit(1)
    
    ctx.obj = SigaClient(username, password, instituicao, verify=verify)

async def run_async_command(client, coro):
    try:
        # Avoid redundant login if we already have an auth cookie from a loaded session.
        # client._request will handle auto-relogin if a request fails with 401/403.
        if not client.client.cookies.get("auth_jwt"):
            logger.info("No active session found. Logging in...")
            if not await client.login():
                logger.error("Login failed.")
                return None
        
        result = await coro
        return result
    finally:
        await client.client.aclose()

@cli.command()
@click.option('--limit', default=10, help='Number of students to list')
@click.option('--id', 'student_id', type=int, help='Fetch details for a specific student ID')
@click.pass_obj
def students(client, limit, student_id):
    """List students or fetch specific detail."""
    async def run():
        if student_id:
            data = await client.get_aluno_detail(student_id)
            # data contains {"aluno": {...}, "gestao_presenca": {...}, ...}
            student_info = data.get('aluno', {})
            if student_info:
                # Fetch associated turmas
                turmas = await client.get_aluno_turmas(student_id)
                student_info['turmas'] = turmas
                
                # Merge gestao_presenca into the student_info for a complete view
                student_info['gestao_presenca'] = data.get('gestao_presenca', {})
                logger.info(f"Complete Student Data: {json.dumps(student_info, indent=2, ensure_ascii=False)}")
            else:
                logger.error(f"Student ID {student_id} not found or invalid response.")
        else:
            data = await client.list_alunos(limit=limit)
            results = data.get('results', [])
            for student in results:
                info = f"ID: {student.get('id')} | Name: {student.get('nome')}"
                
                # Check for presence info in list view
                presenca = student.get('gestao_presenca', {})
                permissoes = presenca.get('permissoes', {})
                if permissoes:
                    tipo = permissoes.get('tipo_liberacao')
                    if tipo == 'S':
                        info += " | Presença: Pode sair sozinho"
                    elif tipo == 'A':
                        info += " | Presença: Sair com responsável"
                
                logger.info(info)

    
    try:
        asyncio.run(run_async_command(client, run()))
    except Exception as e:
        logger.exception(f"An error occurred: {e}")
        sys.exit(1)

@cli.command()
@click.option('--limit', default=21, help='Number of responsible parties to list')
@click.option('--id', 'responsavel_id', type=int, help='Fetch details for a specific responsible party ID')
@click.pass_obj
def responsaveis(client, limit, responsavel_id):
    """List responsible parties (guardians) or fetch specific detail."""
    async def run():
        if responsavel_id:
            data = await client.get_responsavel_detail(responsavel_id)
            resp_info = data.get('responsavel', data)
            logger.info(f"Detailed Responsible Data: {resp_info}")
        else:
            data = await client.list_responsaveis(limit=limit)
            results = data.get('results', [])
            for resp in results:
                logger.info(f"ID: {resp.get('id')} | Name: {resp.get('nome')}")

    try:
        asyncio.run(run_async_command(client, run()))
    except Exception as e:
        logger.exception(f"An error occurred: {e}")
        sys.exit(1)

@cli.command()
@click.option('--student-id', required=True, type=int, help='Standard student ID')
@click.option('--destinatario-id', required=True, type=int, help='Recipient ID (e.g. parent)')
@click.option('--message', required=True, help='Message text')
@click.option('--title', default="Aviso", help='Message title')
@click.option('--type', default="R", help='Recipient type (R for responsible)')
@click.option('--origem', default=2, type=int, help='Origin code')
@click.pass_obj
def send_message(client, student_id, destinatario_id, message, title, type, origem):
    """Send a message to a student/responsible party."""
    async def run():
        result = await client.send_message(
            student_id=student_id,
            destinatario_id=destinatario_id,
            message_text=message,
            message_title=title,
            destinatario_tipo=type,
            origem=origem
        )
        logger.info(f"Message send result: {result}")
        
    try:
        asyncio.run(run_async_command(client, run()))
    except Exception as e:
        logger.exception(f"An error occurred: {e}")
        sys.exit(1)

@cli.command()
@click.option('--limit', default=10, help='Number of classes to list')
@click.option('--periodo', default=14, help='Period ID (default: 14)')
@click.pass_obj
def turmas(client, limit, periodo):
    """List classes (turmas)."""
    async def run():
        data = await client.list_turmas(limit=limit, periodo=periodo)
        results = data.get('results', [])
        for turma in results:
            logger.info(f"ID: {turma.get('id')} | Name: {turma.get('nome')}")

    try:
        asyncio.run(run_async_command(client, run()))
    except Exception as e:
        logger.exception(f"An error occurred: {e}")
        sys.exit(1)

@cli.command()
@click.option('--student-id', required=True, type=int, help='Student ID')
@click.option('--image-path', required=True, type=click.Path(exists=True), help='Path to the image file')
@click.pass_obj
def upload_avatar(client, student_id, image_path):
    """Upload an avatar/photo for a student."""
    async def run():
        # Read and encode image
        with open(image_path, "rb") as image_file:
            encoded_string = base64.b64encode(image_file.read()).decode('utf-8')
            
        mime_type, _ = mimetypes.guess_type(image_path)
        if not mime_type:
            mime_type = "image/jpeg"
            
        data_uri = f"data:{mime_type};base64,{encoded_string}"
        
        result = await client.upload_avatar(student_id, data_uri)
        if result:
            logger.success("Avatar updated successfully.")
        else:
            logger.error("Failed to update avatar.")
            sys.exit(1)

    try:
        asyncio.run(run_async_command(client, run()))
    except Exception as e:
        logger.exception(f"An error occurred: {e}")
        sys.exit(1)

@cli.command()
@click.option('--ids', help='Comma-separated list of student IDs')
@click.option('--id', 'id_list', type=int, multiple=True, help='Multiple student IDs')
@click.pass_obj
def bulk_fotos(client, ids, id_list):
    """Fetch photo URLs for multiple students in bulk."""
    async def run():
        pks = []
        if ids:
            pks.extend([int(x.strip()) for x in ids.split(',') if x.strip()])
        if id_list:
            pks.extend(id_list)
            
        if not pks:
            logger.error("No student IDs provided.")
            sys.exit(1)
            
        data = await client.get_bulk_fotos(pks)
        logger.info(f"Bulk Photo Data: {json.dumps(data, indent=2)}")

    try:
        asyncio.run(run_async_command(client, run()))
    except Exception as e:
        logger.exception(f"An error occurred: {e}")
        sys.exit(1)

def main():
    cli()

if __name__ == "__main__":
    main()
