from google.cloud import firestore
import logging
from typing import Optional

from schedule.model.user import User
from schedule.model.location import Location

db = firestore.Client()
logger = logging.getLogger(__name__)


def get_user(username: str) -> Optional[User]:
    logger.info(f'retrieving {username}')

    users = [i for i in db.collection(u'user').where(u'username', u'==', username).stream()]

    if len(users) == 0:
        logger.error(f'user {username} not found')
        return None
    if len(users) > 1:
        logger.critical(f"multiple {username}'s found")
        return None

    user = users[0].to_dict()

    return User(username=user.get('username'),
                db_ref=users[0].reference)


def create_user(username: str) -> None:
    logger.info(f'creating {username}')

    user_collection = db.collection(u'user')

    # check if username is already registered
    current_users = [i for i in user_collection.where(u'username', u'==', username).stream()]
    if len(current_users) > 0:
        logger.error(f'user {username} already exists')
        return None

    # USER DATABASE ENTITY MANIFEST
    user_info = {
        'username': username
    }

    user_collection.document().set(user_info)


def update_user(username: str, updates: dict):
    logger.info(f'updating {username}')

    user = get_user(username)

    if user is not None:
        user.db_ref.update(updates)
    else:
        logger.error('no user returned')


def delete_user(username: str) -> None:
    logger.info(f'deleting {username}')

    user = get_user(username)

    if user is not None:
        user.db_ref.delete()
    else:
        logger.error('no user returned')


def get_location(location_id: str) -> Optional[Location]:
    logger.info(f'retrieving {location_id}')

    locations = [i for i in db.collection(u'location').where(u'location_id', u'==', location_id).stream()]

    if len(locations) == 0:
        logger.error(f'location {location_id} not found')
        return None
    if len(locations) > 1:
        logger.critical(f"location {location_id}'s found")
        return None

    location = locations[0].to_dict()

    return Location(location_id=location.get('location_id'),
                    db_ref=locations[0].reference)


def create_location(location_id: str) -> None:
    logger.info(f'creating {location_id}')

    location_collection = db.collection(u'location')

    # check if location is already registered
    current_locations = [i for i in location_collection.where(u'location_id', u'==', location_id).stream()]
    if len(current_locations) > 0:
        logger.error(f'location {location_id} already exists')
        return None

    # LOCATION DATABASE ENTITY MANIFEST
    location_info = {
        'location_id': location_id
    }

    location_collection.document().set(location_info)


def update_location(location_id: str, updates: dict):
    logger.info(f'retrieving {location_id}')

    location = get_location(location_id)

    if location is not None:
        location.db_ref.update(updates)
    else:
        logger.error('no location returned')


def delete_location(location_id: str) -> None:
    logger.info(f'deleting {location_id}')

    location = get_location(location_id)

    if location is not None:
        location.db_ref.delete()
    else:
        logger.error('no location returned')
