# core/parser.py

import logging
from pathvalidate import sanitize_filename

from .models import Video, VideoStatus, Creator
from .db import DB
from .file_io import load_json
from .config import Config


COOMER_PAYSITES = ["onlyfans", "fansly", "candfans"]


def get_domain(arg) -> str:
    def _service(service: str) -> str:
        if service in COOMER_PAYSITES:
            return "coomer"
        return "kemono"

    def _get_domain_from_post(post: dict) -> str:
        return _service(post["service"])

    if isinstance(arg, dict):
        return _get_domain_from_post(arg)

    return _service(arg)


def get_title(post: dict) -> str:
    title = post["title"]
    if title == "":
        if "content" in post:
            title = post["content"]
        elif "substring" in post:
            title = post["substring"]
    return sanitize_filename(title)


def get_date(post: dict) -> str:
    if "published" in post:
        date = post["published"][0:10]
    elif "added" in post:
        date = post["added"][0:10]
    else:
        logging.error(f"Could not extract date from {post['id']}")
        date = "NA"
    return date


def get_part(post: dict, url: str) -> int:
    urls = extract_video_urls(post)
    part = 0
    if len(urls) == 1:
        return 0

    for u in urls:
        if u == url:
            return part
        part += 1

    logging.error(
        f"Could not extract part number for post id {post['id']} with url {url}"
    )
    return -1


def get_filename(post: dict, url: str) -> str:
    title = get_title(post)
    date = get_date(post)
    part = get_part(post, url)
    file_title = f"{date}_{title}".replace("'", " ").replace('"', "")
    filename = f"{file_title}_p{part}.mp4"
    return filename


def convert_post_to_video(post: dict, url: str, discover=False) -> Video:
    part = get_part(post, url)
    title = get_title(post)
    date = get_date(post)
    filename = get_filename(post, url)

    if discover:
        filename = f"{post['user']}_{post['id']}.mp4"

    return Video(
        post_id=post["id"],
        creator_id=post["user"],
        service=post["service"],
        relative_path=filename,
        url=url,
        domain=get_domain(post),
        part=part,
        published=date,
        title=title,
        status=VideoStatus.NOT_DOWNLOADED,
        fail_count=0,
    )


def convert_posts_to_videos(posts: list[dict], discover: bool = False) -> list[Video]:
    videos = []
    for post in posts:
        urls = extract_video_urls(post)
        if not discover:
            for url in urls:
                videos.append(convert_post_to_video(post, url))
        else:
            if len(urls) == 0:
                continue
            videos.append(convert_post_to_video(post, urls[0], discover=True))
    return videos


def extract_video_urls(post: dict) -> list:
    video_extensions = (".mp4", ".webm", ".mov", ".avi", ".mkv", ".flv", ".wmv", ".m4v")
    urls = set()

    # Check main file
    if post["file"]:
        if post["file"]["path"]:
            path = post["file"]["path"]
            if path.endswith(video_extensions):
                urls.add(f"{path}")

    if post["attachments"]:
        attachments = post["attachments"]
        for attachment in attachments:
            if attachment["path"]:
                if attachment["path"].endswith(video_extensions):
                    urls.add(f"{attachment['path']}")

    return list(urls)


def filter_posts_with_videos_from_list(data: list[dict]) -> list[dict]:
    """Return posts with video url from a json with a list of posts"""

    posts_with_videos = []
    for post in data:
        if len(extract_video_urls(post)) > 0:
            posts_with_videos.append(post)
    return posts_with_videos


def filter_posts_with_videos_from_json(path: str) -> list:
    """Return posts with video url from a json with a list of posts"""
    posts = load_json(path)

    posts_with_videos = []
    for post in posts:
        if len(extract_video_urls(post)) > 0:
            posts_with_videos.append(post)
    return posts_with_videos


def filter_undownloaded_videos(videos: list[Video]) -> list[Video]:
    with DB() as db:
        downloaded_videos = db.query_videos(status=VideoStatus.DOWNLOADED)

    downloaded_keys = set()
    for v in downloaded_videos:
        downloaded_keys.add((v.service, v.url))

    videos_to_dl = []
    for v in videos:
        key = (v.service, v.url)
        if key not in downloaded_keys:
            videos_to_dl.append(v)
    return videos_to_dl


def _convert_creator_dict_to_creator(creator: dict):
    return Creator(
        creator_id=creator["creator_id"],
        service=creator["service"],
        domain=creator["domain"],
        status=None,
    )


def get_creators() -> list[Creator]:
    data = load_json(Config.CREATORS_FILE)
    creators = []
    for creator in data:
        creators.append(_convert_creator_dict_to_creator(creator))
    return creators


def get_creators_from_posts(posts: list[dict]) -> list[Creator]:
    creators = list()
    seen = set()

    for post in posts:
        key = (post["user"], post["service"], "coomer")
        if key in seen:
            continue

        seen.add(key)
        creators.append(
            Creator(
                creator_id=post["user"],
                service=post["service"],
                domain="coomer",
                status="to_be_treated",
            )
        )
    return creators
