import logging

from apscheduler.triggers.interval import IntervalTrigger
from django.utils.timezone import now

from core.scheduler import scheduler

logger = logging.getLogger(__name__)


def check_watcher(watcher_pk: int) -> None:
    from pricemon.models import PriceWatcher, PriceSnapshot, PriceAlert
    from pricemon.scraper import fetch_price
    from pricemon.notifications import notify_telegram

    try:
        watcher = PriceWatcher.objects.get(pk=watcher_pk)
    except PriceWatcher.DoesNotExist:
        logger.warning(f'PriceWatcher {watcher_pk} no longer exists, skipping')
        return

    price, raw_text, error = fetch_price(watcher)

    PriceSnapshot.objects.create(
        watcher=watcher,
        price=price,
        raw_text=raw_text or '',
        error=error or '',
    )

    if price is not None and watcher.alert_price_threshold:
        if price <= watcher.alert_price_threshold:
            should_alert = True

            if not watcher.recurring_notification:
                # Only alert if there is no undismissed alert already
                if PriceAlert.objects.filter(watcher=watcher, dismissed=False).exists():
                    should_alert = False

            if should_alert:
                old_price = watcher.last_price
                drop_pct = 0
                if old_price and old_price > price:
                    drop_pct = (old_price - price) / old_price * 100

                alert = PriceAlert.objects.create(
                    watcher=watcher,
                    old_price=old_price,
                    new_price=price,
                    drop_pct=drop_pct,
                )
                notify_telegram(watcher, alert)

    update_fields = ['last_checked_at']
    if price is not None:
        if watcher.initial_price is None:
            watcher.initial_price = price
            update_fields.append('initial_price')
        watcher.last_price = price
        update_fields.append('last_price')
    watcher.last_checked_at = now()
    watcher.save(update_fields=update_fields)
    logger.info(f'Checked watcher {watcher_pk} ({watcher.name}): price={price}')


def schedule_watcher(watcher) -> None:
    job_id = f'pricemon_watcher_{watcher.pk}'
    scheduler.add_job(
        check_watcher,
        trigger=IntervalTrigger(hours=watcher.check_interval_hours),
        id=job_id,
        args=[watcher.pk],
        replace_existing=True,
    )
    logger.info(f'Scheduled pricemon job {job_id} every {watcher.check_interval_hours}h')


def unschedule_watcher(watcher) -> None:
    job_id = f'pricemon_watcher_{watcher.pk}'
    if scheduler.get_job(job_id):
        scheduler.remove_job(job_id)
        logger.info(f'Removed pricemon job {job_id}')
