import os
import logging

from aleph.core import db, archive
from aleph.settings import SETTINGS
from aleph.model import Document
from aleph.queues import ingest_entity
from aleph.logic.aggregator import get_aggregator, MODEL_ORIGIN
from aleph.util import random_id

log = logging.getLogger(__name__)


def ingest_flush(collection, entity_id=None, include_ingest=False):
    """Clear entity fragments generated by the ingest process."""
    aggregator = get_aggregator(collection)
    aggregator.delete(entity_id=entity_id, origin=MODEL_ORIGIN)
    if include_ingest:
        aggregator.delete(entity_id=entity_id, origin=SETTINGS.STAGE_INGEST)
    for stage in SETTINGS.INGEST_PIPELINE:
        aggregator.delete(entity_id=entity_id, origin=stage)


def crawl_directory(collection, path, parent=None, job_id=None):
    """Crawl the contents of the given path."""
    try:
        content_hash = None
        if not path.is_dir():
            content_hash = archive.archive_file(path)
        foreign_id = path.name
        if parent is not None:
            foreign_id = os.path.join(parent.foreign_id, foreign_id)

        # if the job_id is not set yet and path.is_dir(), we know it is the
        # first iteration and we don't create an initial root folder as parent
        # to be consistent with the behaviour of alephclient
        if path.is_dir() and job_id is None:
            document = None
            job_id = random_id()
        else:
            meta = {"file_name": path.name}
            document = Document.save(
                collection,
                parent=parent,
                foreign_id=foreign_id,
                content_hash=content_hash,
                meta=meta,
            )
            db.session.commit()
            job_id = job_id or random_id()
            proxy = document.to_proxy()
            ingest_flush(collection, entity_id=proxy.id)
            ingest_entity(collection, proxy, job_id=job_id)
            log.info("Crawl [%s]: %s -> %s", collection.id, path, document.id)

        if path.is_dir():
            for child in path.iterdir():
                crawl_directory(collection, child, document, job_id)
    except OSError:
        log.exception("Cannot crawl directory: %s", path)
