from drstats.devrant import Devrant
from drstats.db import get_db
import json
import asyncio
from pprint import pprint as pp
import requests

dr = Devrant()
db = get_db()


def plain_object(obj):
    for key, value in obj.items():
        if isinstance(value, list) or isinstance(value, dict):
            value = json.dumps(value)
            obj[key] = value
    return obj


from datetime import datetime


def timestamp_to_string(timestamp):
    return datetime.fromtimestamp(timestamp).strftime("%Y-%m-%d %H:%M:%S")


async def get_recent_rants(start_from=1, page_size=10):
    loop = asyncio.get_running_loop()
    page = 0
    while True:

        def get_rants():
            return dr.get_rants("recent", page_size, start_from)["rants"]

        rants = await asyncio.wait_for(loop.run_in_executor(None,get_rants), 15)

        page += 1
        for rant in rants:
            if rant is None:
                break
            rant["tags"] = json.dumps("tags" in rant and rant["tags"] or "")
            rant["created"] = timestamp_to_string(rant["created_time"])
            rant = plain_object(rant)

            yield rant
        start_from += page_size


async def _sync_rants(start_from, page_size, count):
    async for rant in get_recent_rants(start_from, page_size):
        start_from += page_size
        count += 1
        rant["tags"] = json.dumps(rant["tags"])
        db["rants"].upsert(rant, ["id"])
        print(f"Upserted {count} rant(s).")
    return count


async def sync_rants():
    count = 0
    start_from = 0

    page_size = 20

    while True:
        try:
            count += await asyncio.wait_for(
                _sync_rants(start_from, page_size, count), 5
            )
            start_from += page_size
        except Exception as ex:
            print(ex)
            print(
                "If exception described above is an timeout related error, it's due ratelimiting and considered OK."
            )
            break


async def sync_comments():
    comments_synced = 0
    rants_synced = 0
    for rant in db["rants"].find(order_by="-id"):
        rants_synced += 1
        try:
            comments = dr.get_rant(rant["id"]).get("comments", [])
        except Exception as ex:
            print(ex)
            print("Sleeping for a second..")
            await asyncio.sleep(1)
            continue

        for comment in comments:
            comments_synced += 1
            comment["created"] = timestamp_to_string(comment["created_time"])
            comment = plain_object(comment)
            comment["rant_id"] = rant["id"]

            db["comments"].upsert(comment, ["id"])
            print(f"Synced {rants_synced} rants with {comments_synced} comments.")


def sync():
    print(asyncio.run(sync_comments()))
    print(asyncio.run(sync_rants()))
