"""
kinto.plugins.quotas.scripts: scripts to maintain quotas and fix them when they're broken
"""
import logging

from kinto.core.storage import Sort
from kinto.core.storage.utils import paginated
from .listener import BUCKET_QUOTA_OBJECT_ID, COLLECTION_QUOTA_OBJECT_ID
from .utils import record_size

logger = logging.getLogger(__name__)

OLDEST_FIRST = Sort('last_modified', 1)


def rebuild_quotas(storage, dry_run=False):
    for bucket in paginated(storage, collection_id='bucket',
                            parent_id='', sorting=[OLDEST_FIRST]):
        bucket_id = bucket['id']
        bucket_path = '/buckets/{}'.format(bucket['id'])
        bucket_collection_count = 0
        bucket_record_count = 0
        bucket_storage_size = record_size(bucket)

        for collection in paginated(storage, collection_id='collection',
                                    parent_id=bucket_path, sorting=[OLDEST_FIRST]):
            collection_info = rebuild_quotas_collection(storage, bucket_id, collection, dry_run)
            (collection_record_count, collection_storage_size) = collection_info
            bucket_collection_count += 1
            bucket_record_count += collection_record_count
            bucket_storage_size += collection_storage_size

        bucket_record = {
            'record_count': bucket_record_count,
            'storage_size': bucket_storage_size,
            'collection_count': bucket_collection_count,
        }
        if not dry_run:
            storage.update(collection_id='quota', parent_id=bucket_path,
                           object_id=BUCKET_QUOTA_OBJECT_ID, record=bucket_record)

        logger.info('Bucket {}. Final size: {} collections, {} records, {} bytes.'.format(
            bucket_id, bucket_collection_count, bucket_record_count, bucket_storage_size))


def rebuild_quotas_collection(storage, bucket_id, collection, dry_run=False):
    """Helper method for rebuild_quotas that updates a single collection."""
    collection_id = collection['id']
    collection_record_count = 0
    collection_storage_size = record_size(collection)
    collection_path = '/buckets/{}/collections/{}'.format(bucket_id, collection_id)
    for record in paginated(storage, collection_id='record',
                            parent_id=collection_path, sorting=[OLDEST_FIRST]):
        collection_record_count += 1
        collection_storage_size += record_size(record)

    logger.info('Bucket {}, collection {}. Final size: {} records, {} bytes.'.format(
        bucket_id, collection_id, collection_record_count, collection_storage_size))
    new_quota_info = {
        'record_count': collection_record_count,
        'storage_size': collection_storage_size,
    }
    if not dry_run:
        storage.update(collection_id='quota', parent_id=collection_path,
                       object_id=COLLECTION_QUOTA_OBJECT_ID, record=new_quota_info)
    return (collection_record_count, collection_storage_size)
