# -*- coding: utf-8 -*-
#  @date    160902 - Enhanced user profile update
"""
Business logic for User management.
"""
import uuid
from datetime import timezone

import pytz
from django.core.exceptions import ObjectDoesNotExist

from website.local_settings import DISPLAY_TIMEZONE
from auth_sys.models import MyUser, GroupPermission
from utils.auth_permission import pwd_validation


def get_user_list():
    """Get user list."""
    users = MyUser.objects.all()

    group_mapping = {}
    [group_mapping.update(
        {q.id: q.name}) for q in GroupPermission.objects.all()]

    output = {
        'data': [],
        'recordsTotal': len(users),     # show total of records
        "recordsFiltered": len(users),  # reconrd number for page filter
    }

    for u in users:
        output['data'] += [{
            'user_id': u.id,
            'username': u.username,
            'company_name': u.company_name,
            'employee_id': u.employee_id,
            'realname': u.realname,
            'email': u.email,
            'job_position': u.job_position,
            'group_id': u.group_id,
            'group_name': group_mapping[u.group_id],
        }]

    return True, output


def add_user(usr_input):
    """Add a user."""
    username = usr_input.get('username', '')
    password = usr_input.get('password', '')
    realname = usr_input.get('realname', '')
    email = usr_input.get('email', '')
    company_name = usr_input.get('company_name', '')
    job_position = usr_input.get('job_position', '')
    employee_id = usr_input.get('employee_id', '')
    group_id = usr_input.get('group_id', '9')

    # checking value format
    try:
        group_id = int(group_id)
        GroupPermission.objects.filter(id=group_id).get()
    except (ValueError, TypeError):
        return False
    except ObjectDoesNotExist:
        return False

    # checking value if it must input
    if not all([username, password]):
        return False

    # checking duplication
    if MyUser.objects.filter(username=username).first():
        return False

    MyUser.objects.create_user(
        username=username,
        password=password,
        is_active=True,
        group_id=group_id,
        realname=realname,
        email=email,
        company_name=company_name,
        job_position=job_position,
        employee_id=employee_id,
    )
    return True


def update_profile(usr_input):
    """Update user's profile information."""
    new_pwd = usr_input.get('new_pwd', '')
    user_id = usr_input.get('id', '')
    group_id = usr_input.get('group_id', None)

    # checking value format
    try:
        # Checking UUID format
        uuid.UUID(user_id, version=4)
    except (ValueError, TypeError):
        return False
    except ObjectDoesNotExist:
        return False

    is_updated = False
    try:
        if user_id:
            the_user = MyUser.objects.filter(id=user_id).first()
            if the_user:
                # password updated
                if new_pwd and pwd_validation(new_pwd):
                    is_updated = True
                    the_user.set_password(new_pwd)

                # group updated
                try:
                    if group_id:
                        is_updated = True
                        GroupPermission.objects.filter(id=int(group_id)).get()
                        the_user.group_id = group_id
                except ObjectDoesNotExist:
                    return False

                # other information
                update_attr = {
                    'realname': usr_input.get('realname', ''),
                    'company_name': usr_input.get('company_name', ''),
                    'employee_id': usr_input.get('employee_id', ''),
                    'email': usr_input.get('email', ''),
                    'job_position': usr_input.get('job_position', ''),
                }

                for key, value in update_attr.items():
                    if value:
                        is_updated = True
                        setattr(the_user, key, value)

                if is_updated:
                    the_user.save()

                return True
    except ValueError:
        pass

    return False


def delete_user(user, usr_input):
    """Delete user (not include himself)."""
    user_id = usr_input.get('id', '')

    try:
        if user_id:
            try:
                the_user = MyUser.objects.filter(id=user_id).first()
            except ValueError:
                raise

            if the_user and user.id != the_user.id:
                the_user.delete()
                return True
            else:
                raise ValueError
    except ValueError:
        pass

    return False


def get_group_list():
    """Get group list."""
    groups = GroupPermission.objects.all()

    output = {
        'data': [],
        'recordsTotal': len(groups),
        "recordsFiltered": len(groups),
    }

    for g in groups:
        output['data'] += [{
            'id': g.id,
            'name': g.name,
            'permission': g.permission,
            'created_at': g.created_at.replace(tzinfo=timezone.utc).astimezone(
                tz=pytz.timezone(DISPLAY_TIMEZONE)).strftime(
                "%Y-%m-%d %H:%M:%S"),
            'updated_at': g.updated_at.replace(tzinfo=timezone.utc).astimezone(
                tz=pytz.timezone(DISPLAY_TIMEZONE)).strftime(
                "%Y-%m-%d %H:%M:%S"),
        }]
    return True, output


def add_group(usr_input):
    """Add a group."""
    group_id = usr_input.get('id', '')
    group_name = usr_input.get('name', '')
    permission = usr_input.get('permission', '0' * 32)

    # checking value format
    try:
        group_id = int(group_id)
        int(permission, 2)

        if len(permission) != 32:
            raise TypeError

    except (ValueError, TypeError):
        return False

    # checking duplidation
    if GroupPermission.objects.filter(id=group_id).first():
        return False

    GroupPermission(
        id=group_id,
        name=group_name,
        permission=permission,
    ).save()
    return True


def delete_group(usr_input):
    """Delete a group."""
    group_id = usr_input.get('id', '')

    # checking value format
    try:
        group_id = int(group_id)
    except (ValueError, TypeError):
        return False

    # checking already be used or admin (group_id = 0)
    if group_id == 0 or MyUser.objects.filter(group_id=group_id).first():
        return False

    GroupPermission.objects.filter(id=group_id).delete()
    return True


def update_group(usr_input):
    """Update a group."""
    group_id = usr_input.get('id', '')
    group_name = usr_input.get('name', None)
    permission = usr_input.get('permission', None)

    # checking value format
    try:
        if group_id:
            group_id = int(group_id)

        # admin can't be modified
        if group_id == 0:
            raise ValueError

        if permission is not None:
            int(permission, 2)

            if len(permission) != 32:
                raise TypeError

    except (ValueError, TypeError):
        return False

    the_group = GroupPermission.objects.filter(id=group_id).first()

    if the_group:
        update_attr = {
            'name': group_name,
            'permission': permission
        }

        is_updated = False
        for key, value in update_attr.items():
            if value is not None:
                is_updated = True
                setattr(the_group, key, value)

        if is_updated:
            the_group.save()

        return True

    return False
