import os, sys
import json
import logging
import re
from uuid import uuid4, UUID
from datetime import datetime

from harvest.drivers.dynamodb_driver import DynamoDbDriver
from harvest.utils.sorters import date_sort

class NotificationController(DynamoDbDriver):

  logger = logging.getLogger(__name__)
  logger.addHandler(logging.NullHandler())
  logger.setLevel(logging.DEBUG)

  def __init__(self, host, port):
    super().__init__(host, port, "Notifications")
    super().set_partition_key("user_id")
    super().set_sort_key("notification_id")

  def set_user_id(self, user_id):
    self.user_id = str(user_id)

  def set_notification_id(self, notification_id):
    self.notification_id = str(notification_id)

  def set_project_id(self, project_id):
    self.project_id = str(project_id)
  
  def list(self, user_id=None):
    if not user_id:
      user_id = self.user_id

    ret = super().query(
        partition_key = user_id
    )
    sorted_items = date_sort(ret["Items"], key="created_at", reverse=True)
    return sorted_items

  def show(self, user_id=None, notification_id=None):
    if not user_id:
      user_id = self.user_id
    if not notification_id:
      notification_id = self.notification_id

    return super().get_item(user_id, notification_id)["Item"]

  def create(self, message, user_id=None, project_id=None):
    if not user_id:
      user_id = self.user_id
    if not project_id:
      project_id = self.project_id

    new_id = str(uuid4())
    now = datetime.now().isoformat()

    ret = super().put_item(
      item = {
        "user_id": user_id,
        "notification_id": new_id,
        "project_id": project_id,
        "created_at": now,
        "updated_at": now,
        "message": message,
        "read": False
      }
    )
    self.logger.info(ret)
    return ret

  def batch_create(self, notifications):
    return super().batch_put_item(notifications)

  def update(self, read, user_id=None, notification_id=None):
    if not user_id:
      user_id = self.user_id
    if not notification_id:
      notification_id = self.notification_id
    if not isinstance(read, bool):
      raise AttributeError

    self.logger.info("notification id: %s update to read status:" % (notification_id, str(read)))
    now = datetime.now().isoformat()
    return super().update_item(
        partition_key = user_id,
        sort_key = notification_id,
        update_exp = "set #read = :read, #updated_at = :updated_at",
        exp_attr_names = {
            '#read': "read",
            "#updated_at": "updated_at",
        },
        exp_attr_values={
            ":read": read,
            ":updated_at": now

        },
        cond_exp = 'attribute_exists(project_id)'
    )

  def delete(self, user_id=None, notification_id=None, notification_ids=None):
    if not user_id:
      user_id = self.user_id
    if not notification_id:
      notification_id = self.notification_id

    if not notification_ids and isinstance(notification_ids, list):
      notification_ids = self.notification_ids
    else:
      ValueError

    if notification_id:
      ret = super().delete_item(user_id, notification_id)
    elif notification_ids:
      keys = [ {"user_id": user_id, "notification_id": notification_id} for notification_id in notification_ids ]
      console.log(keys)
      ret = super().batch_del_item(keys)
    return ret
