from canvas_sak.core import *


def process_assignment(assignment, update_kwargs, group_names=None):
    """Update a single assignment and display its attributes."""
    if update_kwargs:
        info(f"updating assignment '{assignment.name}' with: {update_kwargs}")
        assignment.edit(assignment=update_kwargs)
        output("assignment updated successfully")
    else:
        info(f"no changes specified for '{assignment.name}', showing current settings")

    # Display assignment attributes
    output("")
    output(f"Assignment Settings: {assignment.name}")
    output(f"  Points Possible: {getattr(assignment, 'points_possible', 'N/A')}")
    output(f"  Submission Types: {getattr(assignment, 'submission_types', 'N/A')}")
    output(f"  Grading Type: {getattr(assignment, 'grading_type', 'N/A')}")
    output(f"  Published: {getattr(assignment, 'published', 'N/A')}")
    output(f"  Allowed Attempts: {getattr(assignment, 'allowed_attempts', 'N/A')}")
    output(f"  Allowed Extensions: {getattr(assignment, 'allowed_extensions', 'N/A')}")
    output(f"  Omit From Final Grade: {getattr(assignment, 'omit_from_final_grade', 'N/A')}")
    output(f"  Peer Reviews: {getattr(assignment, 'peer_reviews', 'N/A')}")
    output(f"  Due At: {getattr(assignment, 'due_at', 'N/A')}")
    output(f"  Unlock At: {getattr(assignment, 'unlock_at', 'N/A')}")
    output(f"  Lock At: {getattr(assignment, 'lock_at', 'N/A')}")
    group_id = getattr(assignment, 'assignment_group_id', None)
    group_display = group_names.get(group_id, group_id) if group_names and group_id else 'N/A'
    output(f"  Assignment Group: {group_display}")


@canvas_sak.command()
@click.argument('course_name', metavar='course')
@click.argument('assignment_name', metavar='assignment', default='')
@click.option('--active/--inactive', default=True, help="Search active or inactive courses")
@click.option('--all', 'process_all', is_flag=True, default=False,
              help="Process all matching assignments instead of requiring a single match")
@click.option('--create', is_flag=True, default=False,
              help="Create the assignment if it does not exist (requires exact assignment name)")
@click.option('--points', type=float, default=None,
              help="Points possible")
@click.option('--published/--unpublished', default=None,
              help="Publish or unpublish the assignment")
@click.option('--submission-types', default=None,
              help="Comma-separated submission types: online_upload,online_text_entry,online_url,media_recording,none,on_paper,external_tool,online_quiz")
@click.option('--grading-type', type=click.Choice(['points', 'percent', 'letter_grade', 'gpa_scale', 'pass_fail', 'not_graded']),
              default=None, help="Grading type")
@click.option('--attempts', type=int, default=None,
              help="Number of attempts allowed (-1 for unlimited)")
@click.option('--allowed-extensions', default=None,
              help="Comma-separated file extensions (e.g., pdf,docx)")
@click.option('--omit-from-final-grade/--include-in-final-grade', default=None,
              help="Omit or include assignment in final grade")
@click.option('--peer-reviews/--no-peer-reviews', default=None,
              help="Enable or disable peer reviews")
@click.option('--assignment-group', default=None,
              help="Only process assignments whose assignment group name contains this substring")
def update_assignment(course_name, assignment_name, active, process_all, create, points,
                      published, submission_types, grading_type, attempts,
                      allowed_extensions, omit_from_final_grade, peer_reviews, assignment_group):
    """Update assignment settings and display the resulting attributes.

    Examples:

        canvas-sak update-assignment "My Course" "Homework 1" --points 100

        canvas-sak update-assignment "My Course" "Essay" --submission-types online_upload,online_text_entry

        canvas-sak update-assignment "My Course" --inactive  # list all assignments

        canvas-sak update-assignment "My Course" "Lab" --all --published  # publish all assignments containing "Lab"

        canvas-sak update-assignment "My Course" "Final" --grading-type letter_grade --omit-from-final-grade

        canvas-sak update-assignment "My Course" "New Assignment" --create --points 50  # create if not exists

        canvas-sak update-assignment "My Course" "Lab" --assignment-group "Labs" --all --published  # publish all "Lab" assignments in groups matching "Labs"
    """
    canvas = get_canvas_object()
    course = get_course(canvas, course_name, is_active=active)
    info(f"found {course.name}")

    # Get all assignments and assignment groups
    all_assignments = list(course.get_assignments())
    group_names = {g.id: g.name for g in course.get_assignment_groups()}

    # Filter by assignment group if specified
    if assignment_group is not None:
        groups = group_names
        matching_group_ids = {gid for gid, name in groups.items() if assignment_group in name}
        if not matching_group_ids:
            error(f"no assignment groups matched '{assignment_group}'. available groups:")
            for name in groups.values():
                error(f"    {name}")
            sys.exit(2)
        info(f"filtering to assignment groups: {[groups[gid] for gid in matching_group_ids]}")
        all_assignments = [a for a in all_assignments if a.assignment_group_id in matching_group_ids]

    # Find matching assignments (substring match)
    if assignment_name:
        assignments = [a for a in all_assignments if assignment_name in a.name]
    elif process_all:
        # No assignment name but --all specified: process all assignments
        assignments = all_assignments
    else:
        assignments = []

    if len(assignments) == 0:
        if assignment_name and create:
            # Create the assignment since --create was specified
            info(f"no assignments matched '{assignment_name}', creating new assignment")
            # Build create kwargs (same as update_kwargs, but include name)
            create_kwargs = {'name': assignment_name}

            if points is not None:
                create_kwargs['points_possible'] = points

            if published is not None:
                create_kwargs['published'] = published

            if submission_types is not None:
                create_kwargs['submission_types'] = [s.strip() for s in submission_types.split(',')]

            if grading_type is not None:
                create_kwargs['grading_type'] = grading_type

            if attempts is not None:
                create_kwargs['allowed_attempts'] = attempts

            if allowed_extensions is not None:
                create_kwargs['allowed_extensions'] = [e.strip() for e in allowed_extensions.split(',')]

            if omit_from_final_grade is not None:
                create_kwargs['omit_from_final_grade'] = omit_from_final_grade

            if peer_reviews is not None:
                create_kwargs['peer_reviews'] = peer_reviews

            assignment = course.create_assignment(assignment=create_kwargs)
            output("assignment created successfully")
            process_assignment(assignment, {}, group_names)  # Display attributes, no further updates needed
            sys.exit(0)

        if assignment_name:
            error(f"no assignments matched '{assignment_name}'")
        output(f"available assignments in {course.name}:")
        for a in all_assignments:
            output(f"    {a.name}")
        sys.exit(0 if not assignment_name else 2)

    if len(assignments) > 1 and not process_all:
        error(f"multiple assignments matched '{assignment_name}' (use --all to process all):")
        for a in assignments:
            error(f"    {a.name}")
        sys.exit(2)

    # Build update kwargs
    update_kwargs = {}

    if points is not None:
        update_kwargs['points_possible'] = points

    if published is not None:
        update_kwargs['published'] = published

    if submission_types is not None:
        update_kwargs['submission_types'] = [s.strip() for s in submission_types.split(',')]

    if grading_type is not None:
        update_kwargs['grading_type'] = grading_type

    if attempts is not None:
        update_kwargs['allowed_attempts'] = attempts

    if allowed_extensions is not None:
        update_kwargs['allowed_extensions'] = [e.strip() for e in allowed_extensions.split(',')]

    if omit_from_final_grade is not None:
        update_kwargs['omit_from_final_grade'] = omit_from_final_grade

    if peer_reviews is not None:
        update_kwargs['peer_reviews'] = peer_reviews

    # Process assignments
    info(f"processing {len(assignments)} assignment(s)")
    for assignment in assignments:
        process_assignment(assignment, update_kwargs, group_names)
