"""
Celery task: weekly MaxMind GeoLite2-City database update.
"""
import logging
import os
import tarfile
import tempfile

import httpx
from celery import shared_task

from src.core.config import settings

logger = logging.getLogger(__name__)


@shared_task(name="update_maxmind_db", bind=True, max_retries=3)
def update_maxmind_db(self):
    """Weekly task: download the latest GeoLite2-City.mmdb from MaxMind."""
    license_key = getattr(settings, "MAXMIND_LICENSE_KEY", None)
    db_path = getattr(settings, "MAXMIND_DB_PATH", None)

    if not license_key:
        logger.warning("MAXMIND_LICENSE_KEY not set — skipping MaxMind DB update")
        return {"status": "skipped", "reason": "MAXMIND_LICENSE_KEY not configured"}

    if not db_path:
        logger.warning("MAXMIND_DB_PATH not set — skipping MaxMind DB update")
        return {"status": "skipped", "reason": "MAXMIND_DB_PATH not configured"}

    url = (
        "https://download.maxmind.com/app/geoip_download"
        f"?edition_id=GeoLite2-City&license_key={license_key}&suffix=tar.gz"
    )

    tmp_path = None
    try:
        logger.info("Downloading GeoLite2-City database from MaxMind...")
        with httpx.Client(timeout=120.0, follow_redirects=True) as client:
            response = client.get(url)
            response.raise_for_status()

        with tempfile.NamedTemporaryFile(suffix=".tar.gz", delete=False) as tmp:
            tmp.write(response.content)
            tmp_path = tmp.name

        db_dir = os.path.dirname(db_path)
        if db_dir:
            os.makedirs(db_dir, exist_ok=True)

        # Track whether extraction succeeded
        mmdb_extracted = False
        with tarfile.open(tmp_path, "r:gz") as tar:
            for member in tar.getmembers():
                if member.name.endswith(".mmdb"):
                    member.name = os.path.basename(member.name)
                    tar.extract(member, path=os.path.dirname(db_path) or ".")
                    extracted = os.path.join(os.path.dirname(db_path) or ".", member.name)
                    os.replace(extracted, db_path)
                    logger.info("MaxMind DB updated successfully at %s", db_path)
                    mmdb_extracted = True
                    break

        if not mmdb_extracted:
            logger.error("No .mmdb file found in MaxMind download archive")
            return {"status": "error", "reason": "No .mmdb file found in archive"}

        return {"status": "success", "path": db_path}

    except Exception as exc:
        logger.error("MaxMind DB update failed: %s", exc)
        raise self.retry(exc=exc, countdown=3600)

    finally:
        if tmp_path and os.path.exists(tmp_path):
            try:
                os.unlink(tmp_path)
            except OSError:
                pass
