from nanoid import generate


class DBModel:
  def __init__(self, connection, cursor):
    self.connection = connection
    self.cursor = cursor

  def login(self, email):
    self.cursor.execute("SELECT * FROM accounts WHERE email = %s", (email, ))
    if len(self.cursor.fetchall()) == 0:
      self.cursor.execute("INSERT INTO accounts (email) VALUES (%s)", (email, ))

    self.cursor.execute("SELECT token FROM login_tokens WHERE email = %s", (email, ))
    if len(self.cursor.fetchall()) > 2:
      return None

    token = generate()
    self.cursor.execute("INSERT INTO login_tokens (email, token) VALUES (%s, %s)", (email, token))
    self.connection.commit()

    return token
    
  def consume_token(self, token):
    self.cursor.execute("SELECT email FROM login_tokens WHERE token = %s", (token, ))
    rows = self.cursor.fetchall()
    if len(rows) > 0:
      email = rows[0][0]
      self.cursor.execute("DELETE FROM login_tokens WHERE email = %s", (email, ))
      self.connection.commit()
      return email
    return None

  def all_vm_ids(self,):
    self.cursor.execute("SELECT id FROM vms")
    return list(map(lambda x: x[0], self.cursor.fetchall()))

  def operating_systems_dict(self,):
    self.cursor.execute("SELECT id, template_image_file_name, description FROM os_images")

    operatingSystems = dict()
    for row in self.cursor.fetchall():
      operatingSystems[row[0]] = dict(template_image_file_name=row[1], description=row[2])

    return operatingSystems

  def vm_sizes_dict(self,):
    self.cursor.execute("SELECT id, dollars_per_month, vcpus, memory_mb, bandwidth_gb_per_month FROM vm_sizes")

    vmSizes = dict()
    for row in self.cursor.fetchall():
      vmSizes[row[0]] = dict(dollars_per_month=row[1], vcpus=row[2], memory_mb=row[3], bandwidth_gb_per_month=row[4])

    return vmSizes

  def list_ssh_public_keys_for_account(self, email):
    self.cursor.execute("SELECT name, content, created FROM ssh_public_keys WHERE email = %s", (email, ))
    return list(map(
      lambda x: dict(name=x[0], content=x[1], created=x[2]), 
      self.cursor.fetchall()
    ))

  def ssh_public_key_name_exists(self, email, name):
    self.cursor.execute( "SELECT name FROM ssh_public_keys where email = %s AND name = %s", (email, name) )
    return len(self.cursor.fetchall()) > 0

  def create_ssh_public_key(self, email, name, content):
    self.cursor.execute(""" 
      INSERT INTO ssh_public_keys (email, name, content)
      VALUES  (%s, %s, %s)
      """, 
      (email, name, content)
    )
    self.connection.commit()

  def delete_ssh_public_key(self, email, name):
    self.cursor.execute( "DELETE FROM ssh_public_keys where email = %s AND name = %s", (email, name) )
    self.connection.commit()

  def list_vms_for_account(self, email):
    self.cursor.execute(""" 
      SELECT vms.id, vms.last_seen_ipv4, vms.last_seen_ipv6, vms.size, vms.os, vms.created, vms.deleted, vm_sizes.dollars_per_month
        FROM vms JOIN vm_sizes on vms.size = vm_sizes.id
      WHERE vms.email = %s""", 
      (email, )
    )
    return list(map(
      lambda x: dict(id=x[0], ipv4=x[1], ipv6=x[2], size=x[3], os=x[4], created=x[5], deleted=x[6], dollars_per_month=x[7]), 
      self.cursor.fetchall()
    ))

  def updateVm(self, email, id, ipv4):
    self.cursor.execute("UPDATE vms SET last_seen_ipv4 = %s WHERE email = %s AND id = %s", (ipv4, email, id))
    self.connection.commit()

  def create_vm(self, email, id, size, os, ssh_public_keys):
    self.cursor.execute(""" 
      INSERT INTO vms (email, id, size, os)
      VALUES  (%s, %s, %s, %s)
      """, 
      (email, id, size, os)
    )
    
    for ssh_public_key in ssh_public_keys:
      self.cursor.execute(""" 
        INSERT INTO vm_ssh_public_key (email, vm_id, ssh_public_key_name)
        VALUES  (%s, %s, %s)
        """, 
        (email, id, ssh_public_key)
      )
    self.connection.commit()

  def get_vm_detail(self, email, id):
    self.cursor.execute(""" 
      SELECT vms.id, vms.last_seen_ipv4, vms.last_seen_ipv6, os_images.description, vms.created, vms.deleted,
            vm_sizes.id, vm_sizes.dollars_per_month, vm_sizes.vcpus, vm_sizes.memory_mb, vm_sizes.bandwidth_gb_per_month
      FROM vms 
        JOIN os_images on vms.os = os_images.id
        JOIN vm_sizes on vms.size = vm_sizes.id
      WHERE vms.email = %s AND vms.id = %s""", 
      (email, id)
    )
    rows = self.cursor.fetchall()
    if len(rows) == 0:
      return None

    x = rows[0]
    vm = dict(
      id=x[0], ipv4=x[1], ipv6=x[2], os_description=x[3], created=x[4], deleted=x[5],
      size=x[6], dollars_per_month=x[7], vcpus=x[8], memory_mb=x[9], bandwidth_gb_per_month=x[10]
    )

    self.cursor.execute(""" 
      SELECT ssh_public_key_name FROM vm_ssh_public_key 
      WHERE vm_ssh_public_key.email = %s AND vm_ssh_public_key.vm_id = %s""", 
      (email, id)
    )
    vm["ssh_public_keys"] = list(map( lambda x: x[0], self.cursor.fetchall() ))

    return vm

  def list_payments_for_account(self, email):
    self.cursor.execute(""" 
      SELECT  payments.dollars, payments.created
      FROM payments WHERE payments.email = %s""", 
      (email, )
    )
    return list(map(
      lambda x: dict(dollars=x[0], created=x[1]), 
      self.cursor.fetchall()
    ))