# services/bulk_worker.py
import os
import sqlite3
from typing import Tuple, Optional, Dict, Any

from services.auth import get_access_token_for_alias
from services.creator import creator_can_post_now
from services.media import video_duration_seconds_ffprobe, build_public_media_url

from tiktok_client import (
    query_creator_info,
    upload_video_direct_post,
    fetch_post_status,
)


def resolve_access_token_for_job(row: sqlite3.Row) -> str:
    """
    Si el job tiene account_alias, resolvemos token desde token_store
    (con refresh automático). Si no, usamos el access_token guardado (legacy).
    """
    alias = (row["account_alias"] or "").strip() if "account_alias" in row.keys() else ""
    if alias:
        return get_access_token_for_alias(alias)
    return row["access_token"]


def process_one_scheduled_job(
    row: sqlite3.Row,
    *,
    upload_dir: str,
    public_base_url: str,
    signing_secret: str,
    ttl_seconds: int,
) -> Tuple[bool, str, Optional[Dict[str, Any]]]:
    """
    Returns:
      (ok, msg, init_resp)
        - if ok: msg=publish_id
        - if not ok: msg=reason
    """
    access_token = resolve_access_token_for_job(row)
    privacy_level = row["privacy_level"]

    # creator_info (siempre al momento de publicar)
    try:
        creator_info = query_creator_info(access_token)
    except Exception as e:
        return False, f"creator_info_failed: {e}", None

    can_post_now, reason = creator_can_post_now(creator_info)
    if not can_post_now:
        return False, f"cannot_post_now: {reason}", None

    # Validate privacy actual
    options = creator_info.get("privacy_level_options") or []
    if privacy_level not in options:
        return False, f"invalid_privacy_level: {privacy_level} options={options}", None

    # Respect creator settings
    allow_comment = bool(row["allow_comment"])
    allow_duet = bool(row["allow_duet"])
    allow_stitch = bool(row["allow_stitch"])

    if creator_info.get("comment_disabled") is True:
        allow_comment = False
    if creator_info.get("duet_disabled") is True:
        allow_duet = False
    if creator_info.get("stitch_disabled") is True:
        allow_stitch = False

    disable_comment = not allow_comment
    disable_duet = not allow_duet
    disable_stitch = not allow_stitch

    stored_filename = row["stored_filename"]
    local_path = os.path.join(upload_dir, stored_filename)
    if not os.path.exists(local_path):
        return False, "file_not_found_on_server", None

    # Duration enforcement (best-effort)
    max_dur = creator_info.get("max_video_post_duration_sec")
    dur = video_duration_seconds_ffprobe(local_path)
    if isinstance(max_dur, int) and max_dur > 0 and dur > 0 and dur > max_dur:
        return False, f"duration_exceeds_max: dur={dur} max={max_dur}", None

    # IMPORTANTE:
    # Para scheduled jobs, el URL firmado DEBE generarse justo al publicar.
    # No reutilizar row["video_url"] porque puede estar caducado.
    video_url = build_public_media_url(
        stored_filename=stored_filename,
        public_base_url=public_base_url,
        signing_secret=signing_secret,
        ttl_seconds=ttl_seconds,
    )

    try:
        init_resp = upload_video_direct_post(
            access_token=access_token,
            caption=row["title"] or "",
            privacy_level=privacy_level,
            disable_comment=disable_comment,
            disable_duet=disable_duet,
            disable_stitch=disable_stitch,
            brand_content_toggle=bool(row["brand_content_toggle"]),
            brand_organic_toggle=bool(row["brand_organic_toggle"]),
            is_aigc=bool(row["is_aigc"]),
            mode="PULL_FROM_URL",
            video_url=video_url,
        )
    except Exception as e:
        return False, f"direct_post_failed: {e}", None

    publish_id = (init_resp.get("data") or {}).get("publish_id")
    if not publish_id:
        return False, f"missing_publish_id init_resp={init_resp}", init_resp

    return True, publish_id, init_resp


def refresh_submitted_job_status(row: sqlite3.Row) -> Tuple[Optional[str], Optional[str]]:
    """
    fetch_post_status() devuelve dict data de TikTok (no envuelto).
    """
    publish_id = row["publish_id"]
    if not publish_id:
        return None, None

    access_token = resolve_access_token_for_job(row)
    data = fetch_post_status(access_token, publish_id)
    status = data.get("status")
    fail_reason = data.get("fail_reason")
    return status, fail_reason
