import logging
import mimetypes
import os
import re
from pathlib import Path
from typing import Optional

import httpx

from core.config import settings
from core.s3_keys import SYSTEM_HELP_PREFIX
from core.storage_s3 import object_exists, put_object_bytes

logger = logging.getLogger(__name__)


def _asset_url_to_s3_key(asset_url: str) -> Optional[str]:
    """Deriva la clave S3 bajo system/help/ a partir de una URL de artículo."""
    if "/help-center/files/" in asset_url:
        rel = asset_url.split("/help-center/files/", 1)[1].lstrip("/")
        if ".." in rel:
            return None
        return f"{SYSTEM_HELP_PREFIX}{rel}"
    u = asset_url.replace("/api/uploads/", "uploads/")
    if u.startswith("/"):
        u = u[1:]
    if u.startswith("uploads/help/"):
        return f"{SYSTEM_HELP_PREFIX}{u[len('uploads/help/') :]}"
    return None


def download_file_from_hub(relative_path: str) -> bool:
    """
    Descarga un asset del Hub y lo guarda en MinIO (system/help/...) o en disco si no hay almacenamiento S3 activo.
    relative_path: URL parcial, p. ej. '/api/uploads/help/x.png' o '/api/v1/core/help-center/files/pdfs/x.pdf'
    """
    if not settings.CENTRAL_SERVER_URL or settings.CENTRAL_SERVER_URL == '""':
        return False

    key = _asset_url_to_s3_key(relative_path)
    if not key:
        logger.warning("download_file_from_hub: could not map URL to S3 key: %s", relative_path)
        return False

    if settings.use_s3_object_storage and object_exists(key):
        logger.info("S3 object %s already exists, skipping download.", key)
        return True

    base_url = settings.CENTRAL_SERVER_URL.split("/v1/")[0]
    if "/help-center/files/" in relative_path:
        rel = relative_path.split("/help-center/files/", 1)[1].lstrip("/")
        hub_file_url = f"{base_url.rstrip('/')}/api/v1/core/help-center/files/{rel}"
    else:
        clean_path = relative_path.replace("/api/uploads/", "uploads/")
        if clean_path.startswith("/"):
            clean_path = clean_path[1:]
        hub_file_url = f"{base_url.rstrip('/')}/{clean_path}"

    logger.info("Downloading asset from Hub: %s", hub_file_url)

    try:
        with httpx.Client() as client:
            response = client.get(hub_file_url, timeout=30.0)
            if response.status_code != 200:
                logger.warning(
                    "Failed to download %s: Status %s URL: %s",
                    relative_path,
                    response.status_code,
                    hub_file_url,
                )
                return False
            body = response.content
    except Exception as e:
        logger.error("Error downloading %s: %s", relative_path, str(e))
        return False

    if settings.use_s3_object_storage:
        rel = key[len(SYSTEM_HELP_PREFIX) :]
        ct = mimetypes.guess_type(rel)[0] or "application/octet-stream"
        try:
            put_object_bytes(key, body, content_type=ct)
            logger.info("Stored hub asset in S3: %s", key)
            return True
        except Exception as e:
            logger.error("S3 put failed for %s: %s", key, e)
            return False

    rel = key[len(SYSTEM_HELP_PREFIX) :]
    local_path = Path("uploads/help") / rel
    local_path.parent.mkdir(parents=True, exist_ok=True)
    local_path.write_bytes(body)
    logger.info("Stored hub asset locally: %s", local_path)
    return True


def sync_assets_from_content(content: str):
    """Parsea markdown y descarga imágenes referenciadas (rutas legacy y nuevas)."""
    if not content:
        return

    patterns = [
        r'!\[.*?\]\((/api/uploads/.*?)\)',
        r'!\[.*?\]\((/api/v1/core/help-center/files/.*?)\)',
    ]
    seen = set()
    for pattern in patterns:
        for asset_url in re.findall(pattern, content):
            if asset_url in seen:
                continue
            seen.add(asset_url)
            download_file_from_hub(asset_url)
