import locale
import os.path

from django.contrib.auth.models import User
from django.core.files import File
from django.core.management.base import BaseCommand, CommandError
from django.db import transaction
from django.utils.encoding import force_str

from docbow_project.docbow.models import AttachedFile, Document, FileType, MailingList


def get_object(model, ref, name='name'):
    '''Try to get a model by id or by name'''
    if ref.isdigit():
        return model.objects.get(id=int(ref))
    else:
        return model.objects.get(**{name: ref})


class Command(BaseCommand):
    help = '''Send a document'''

    def add_arguments(self, parser):
        parser.add_argument('file_tosend', nargs='+', type=str, help='File to send')
        parser.add_argument('--sender')
        parser.add_argument('--to-list', action='append')
        parser.add_argument('--to-user', action='append')
        parser.add_argument('--filetype')
        parser.add_argument('--description')

    @transaction.atomic
    def handle(self, **options):
        locale.setlocale(locale.LC_ALL, '')
        locale_encoding = locale.nl_langinfo(locale.CODESET)
        if 'sender' not in options:
            raise CommandError('missing --sender parameter')
        try:
            sender = get_object(User, force_str(options['sender'], locale_encoding), 'username')
        except User.DoesNotExist:
            raise CommandError('user %r does not exist' % options['sender'])
        to_lists = []
        for name in options.get('to_list') or []:
            ml = get_object(MailingList, force_str(name, locale_encoding))
            to_lists.append(ml)
        to_users = []
        for username in options.get('to_user') or []:
            user = get_object(User, force_str(username, locale_encoding), 'username')
            to_users.append(user)
        if 'filetype' not in options:
            raise CommandError('missing --filetype parameter')
        try:
            filetype = get_object(FileType, force_str(options['filetype'], locale_encoding))
        except FileType.DoesNotExist:
            raise CommandError('filetype %r does not exist' % options['filetype'])
        if not to_users and not to_lists:
            print(to_users, to_lists, options)
            raise CommandError(
                'you must specify at least one list or user ' 'recipient using --to-list and --to-user.'
            )
        document = Document(sender=sender, filetype=filetype)
        document.save()
        document.to_user.set(to_users)
        document.to_list.set(to_lists)
        for arg in options['file_tosend']:
            if not os.path.isfile(arg):
                raise CommandError('file %r does not exist')
            AttachedFile.objects.create(
                name=force_str(arg, locale_encoding), content=File(open(arg)), document=document
            )
        document.post()
