from datetime import timedelta

from django.db.models import Q
from django.utils import timezone
from loguru import logger

from common.models import BaseJob, JobManager
from mastodon.models import MastodonApplication, detect_server_info


@JobManager.register
class MastodonSiteCheck(BaseJob):
    interval = timedelta(days=1)
    max_unreachable_days = 31

    def run(self):
        logger.info("Mastodon Site Check start.")
        count_checked = 0
        count_unreachable = 0
        count_disabled = 0
        count_refreshed = 0
        q = Q(last_reachable_date__lte=timezone.now() - timedelta(days=1)) | Q(
            last_reachable_date__isnull=True
        )
        for site in MastodonApplication.objects.exclude(disabled=True).filter(q):
            domain = None
            count_checked += 1
            try:
                api_domain = site.api_domain or site.domain_name
                domain, api_domain, v = detect_server_info(api_domain)
                site.server_version = v
                site.last_reachable_date = timezone.now()
                site.detect_configurations()
            except Exception as e:
                logger.warning(
                    f"Failed to detect server info for {site.domain_name}/{site.api_domain}",
                    extra={"exception": e},
                )
                count_unreachable += 1
                if site.last_reachable_date is None:
                    site.last_reachable_date = timezone.now() - timedelta(days=1)
                if timezone.now() > site.last_reachable_date + timedelta(
                    days=self.max_unreachable_days
                ):
                    logger.error(
                        f"Failed to detect server info for {site.domain_name}/{site.api_domain} disabling it."
                    )
                    site.disabled = True
                    count_disabled += 1
            finally:
                site.save(
                    update_fields=[
                        "star_mode",
                        "server_version",
                        "max_status_len",
                        "last_reachable_date",
                        "disabled",
                    ]
                )
            try:
                if (
                    site.server_version.startswith("4.")
                    and "(compatible;" not in site.server_version
                    and not site.verify()
                ):
                    # always verify token from Mastodon 4.x
                    site.refresh()
                    count_refreshed += 1
            except Exception as e:
                logger.error(
                    f"Failed to verify/refresh client app for {site.api_domain}",
                    extra={"exception": e},
                )
        logger.info(
            f"Mastodon Site Check finished, {count_checked} checked, {count_unreachable} unreachable, {count_disabled} disabled, {count_refreshed} refreshed."
        )