#!/usr/bin/env python3
import datetime
import os
import sys

import click
import mongoengine.errors

sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from rsvp import app
from rsvp.models import Event, User, ANONYMOUS_EMAIL
from rsvp.utils import format_date


def find_event(event_id):
    try:
        return Event.objects.get(id=event_id)

    except (
        mongoengine.errors.ValidationError,
        mongoengine.errors.DoesNotExist,
    ):
        click.echo("Could not find the specified event")


@click.group()
def cli():
    """A CLI to manage events"""
    pass


@click.command()
def archive_events():
    """Archive old events."""
    click.echo("Archiving events...")
    now = datetime.datetime.now()
    upcoming_events = Event.objects.filter(_end_date__gte=now)
    archived_events = Event.objects.filter(_end_date__lt=now)
    upcoming_events.update(archived=False)
    archived_events.update(archived=True)


@click.command()
@click.argument("event_id", type=str)
def cancel_event(event_id):
    """Cancel the specified event."""
    _toggle_cancel(event_id, cancel=True)


@click.command()
@click.argument("event_id", type=str)
def uncancel_event(event_id):
    """Un-cancel the specified event."""
    _toggle_cancel(event_id, cancel=False)


def _toggle_cancel(event_id, cancel=False):
    event = find_event(event_id)
    if not event:
        return

    action = "cancel" if cancel else "uncancel"
    click.echo("{}ing event {}".format(action.capitalize(), event.id))
    confirmation = click.confirm(
        "Are you sure you want to {} the event - {} - {}".format(
            action, event.name, format_date(event.date)
        )
    )
    if confirmation:
        event.cancelled = cancel
        event.save()


@click.command()
@click.argument("event_id", type=str)
def delete_event(event_id):
    """Delete the specified event."""
    event = find_event(event_id)
    if not event:
        return

    click.echo("Deleting event {}".format(event.id))
    confirmation = click.confirm(
        "Are you sure you want to delete the event - {} - {}".format(
            event.name, format_date(event.date)
        )
    )
    if confirmation:
        event.delete()


@click.command()
def delete_unrsvped_events():
    """Delete events which have been cancelled and don't have any RSVPs."""
    for event in Event.objects.filter(cancelled=True):
        if len(event.active_rsvps) == 0:
            click.echo("Deleting event {}: {}".format(event.id, event.name))
            event.delete()


@click.command()
@click.argument("event_id", type=str)
@click.argument("email", type=str)
def delete_rsvp(event_id, email):
    """Delete users' rsvp for an event."""
    event = find_event(event_id)
    if not event:
        return

    user = User.objects.get(email=email)
    rsvp = event.rsvps.get(user=user)
    event.update(pull__rsvps=rsvp)


@click.command()
@click.argument("event_id", type=str)
@click.argument("description", type=str)
def edit_description(event_id, description):
    """Edit the description of an event."""
    event = find_event(event_id)
    if not event:
        return

    click.echo("Updating the description for {}".format(event.id))
    event.description = description
    event.save()


@click.command()
@click.argument("event_id", type=str)
@click.option("--include-cancelled", default=False, is_flag=True)
def show_rsvp_info(event_id, include_cancelled):
    """Print RSVP emails for an event."""
    event = find_event(event_id)
    if not event:
        return

    rsvps = (
        event.rsvps
        if include_cancelled
        else [rsvp for rsvp in event.rsvps if not rsvp.cancelled]
    )
    for i, rsvp in enumerate(rsvps, start=1):
        user = rsvp.user.fetch()
        FMT = "{name}\t{dob}\t{email}"
        click.echo(
            FMT.format(
                name=user.name,
                email=user.id,
                dob=user.dob.strftime("%d-%m-%Y") if user.dob else "",
            )
        )


cli.add_command(archive_events)
cli.add_command(cancel_event)
cli.add_command(uncancel_event)
cli.add_command(delete_event)
cli.add_command(delete_rsvp)
cli.add_command(edit_description)
cli.add_command(delete_unrsvped_events)
cli.add_command(show_rsvp_info)
if __name__ == "__main__":
    cli()
