import os
import pathlib

import owncloud as nextcloud
from django.conf import settings

from api import util
from api.directory_watcher import handle_new_image
from api.image_similarity import build_image_similarity_index
from api.models import LongRunningJob


def isValidNCMedia(file_obj):
    file_attr = file_obj.attributes
    filetype = file_attr.get("{DAV:}getcontenttype", "")
    try:
        return (
            "jpeg" in filetype
            or "png" in filetype
            or "bmp" in filetype
            or "gif" in filetype
            or "heic" in filetype
            or "heif" in filetype
        )
    except Exception:
        util.logger.exception("An image thrown an exception")
        return False


def collect_photos(nc, path, photos):
    for x in nc.list(path):
        if not x.is_dir() and isValidNCMedia(x):
            photos.append(x.path)
        elif x.is_dir():
            collect_photos(nc, x.path, photos)


def scan_photos(user, job_id):
    lrj = LongRunningJob.get_or_create_job(
        user=user,
        job_type=LongRunningJob.JOB_SCAN_PHOTOS,
        job_id=job_id,
    )

    nc = nextcloud.Client(user.nextcloud_server_address)
    nc.login(user.nextcloud_username, user.nextcloud_app_password)

    photos = []

    paths = []

    collect_photos(nc, user.nextcloud_scan_directory, photos)

    for photo in photos:
        local_dir = os.path.join(
            settings.DATA_ROOT,
            "nextcloud_media",
            user.username,
            os.path.dirname(photo)[1:],
        )
        local_path = os.path.join(
            settings.DATA_ROOT, "nextcloud_media", user.username, photo[1:]
        )
        paths.append(local_path)

        if not os.path.exists(local_dir):
            pathlib.Path(local_dir).mkdir(parents=True, exist_ok=True)

        if not os.path.exists(local_path):
            nc.get_file(photo, local_path)
        util.logger.info("Downloaded photo from nextcloud to " + local_path)

    try:
        paths.sort()

        added_photo_count = 0
        to_add_count = len(paths)
        for idx, image_path in enumerate(paths):
            util.logger.info("begin handling of photo %d/%d" % (idx + 1, to_add_count))
            handle_new_image(user, image_path, job_id)
            lrj.update_progress(current=idx + 1, target=to_add_count)

        util.logger.info(f"Added {len(paths)} photos")
        build_image_similarity_index(user)

        lrj.complete()
    except Exception as e:
        util.logger.exception(str(e))
        lrj.fail(error=e)
    return {"new_photo_count": added_photo_count, "status": True}
