# -*- coding: utf-8 -*-
"""
STEP109 Draft Engine v1

목표:
- 기존 운영 generate_blog_drafts.py는 그대로 보호한다.
- 신규 플랫폼용 초안 선택 엔진을 분리한다.
- 최신 collected + detail_collected=1 + draft 없음 + queue 없음 매물 1건을 선택한다.
- 실제 초안 생성 본문/이미지/HTML 생성은 기존 jobs.generate_blog_drafts.process_article()을 재사용한다.

주의:
- 이 엔진은 신규 Workday/Client 플랫폼용이다.
- 기존 운영 배치에는 바로 연결하지 않는다.
"""

import sys
import json
import subprocess
from pathlib import Path
from datetime import datetime

BASE_DIR = Path(__file__).resolve().parents[1]
if str(BASE_DIR) not in sys.path:
    sys.path.append(str(BASE_DIR))

from db import get_conn

DRAFT_JOB = BASE_DIR / "jobs" / "generate_blog_drafts.py"
PYTHON = sys.executable


def log(*args):
    print(*args, flush=True)


def safe_json(row):
    return json.dumps(row or {}, ensure_ascii=False, default=str)


def fetch_latest_collected_article(conn, realtor_id):
    """
    최신 collected article 중 아직 draft/queue가 없는 1건을 선택한다.
    """
    with conn.cursor() as cur:
        cur.execute("""
            SELECT a.*
            FROM blog_realtor_articles a
            LEFT JOIN blog_article_drafts d
              ON d.realtor_id = a.realtor_id
             AND d.article_no = a.article_no
             AND COALESCE(d.status, '') NOT IN ('regenerated_old', 'cancelled', 'deleted')
             AND COALESCE(d.draft_status, '') NOT IN ('regenerated_old', 'cancelled', 'deleted')
            LEFT JOIN blog_publish_queue q
              ON q.realtor_id = a.realtor_id
             AND q.article_no = a.article_no
             AND COALESCE(q.queue_status, '') NOT IN ('cancelled', 'deleted')
            WHERE a.realtor_id = %s
              AND COALESCE(a.collect_status, '') = 'collected'
              AND COALESCE(a.detail_collected, 0) = 1
              AND d.id IS NULL
              AND q.id IS NULL
            ORDER BY
              COALESCE(a.first_posted_at, a.detail_collected_at, a.created_at) DESC,
              CAST(a.article_no AS UNSIGNED) DESC,
              a.id DESC
            LIMIT 1
        """, (int(realtor_id),))
        return cur.fetchone()


def fetch_article_by_no(conn, realtor_id, article_no):
    with conn.cursor() as cur:
        cur.execute("""
            SELECT *
            FROM blog_realtor_articles
            WHERE realtor_id = %s
              AND article_no = %s
            LIMIT 1
        """, (int(realtor_id), str(article_no)))
        return cur.fetchone()


def fetch_latest_draft_and_queue(conn, realtor_id, article_no):
    with conn.cursor() as cur:
        cur.execute("""
            SELECT *
            FROM blog_article_drafts
            WHERE realtor_id=%s AND article_no=%s
            ORDER BY id DESC
            LIMIT 1
        """, (int(realtor_id), str(article_no)))
        draft = cur.fetchone()

        cur.execute("""
            SELECT *
            FROM blog_publish_queue
            WHERE realtor_id=%s AND article_no=%s
            ORDER BY id DESC
            LIMIT 1
        """, (int(realtor_id), str(article_no)))
        queue = cur.fetchone()

    return {
        "draft": draft,
        "queue": queue,
    }


def validate_article_for_draft(row):
    if not row:
        return False, "article not found"

    if str(row.get("collect_status") or "") != "collected":
        return False, f"collect_status={row.get('collect_status')}"

    try:
        if int(row.get("detail_collected") or 0) != 1:
            return False, f"detail_collected={row.get('detail_collected')}"
    except Exception:
        return False, "detail_collected invalid"

    return True, ""


def create_draft_for_article_row(conn, row):
    # 운영 품질 보강: process_article 직접 호출 대신 운영 CLI를 사용한다.
    article_no = str(row.get("article_no") or "").strip()
    realtor_id = int(row.get("realtor_id") or 0)

    if not article_no or not realtor_id:
        return {
            "ok": False,
            "article_no": article_no,
            "reason": "article_no or realtor_id empty",
            "result": "invalid_target",
        }

    if not DRAFT_JOB.exists():
        return {
            "ok": False,
            "article_no": article_no,
            "reason": f"draft job not found: {DRAFT_JOB}",
            "result": "draft_job_missing",
        }

    cmd = [
        PYTHON,
        str(DRAFT_JOB),
        "--realtor-id",
        str(realtor_id),
        "--article-no",
        article_no,
        "--limit",
        "1",
        "--no-db-lock",
    ]

    log("[STEP110 OPERATING DRAFT CLI]", " ".join(cmd))

    result = subprocess.run(
        cmd,
        cwd=str(BASE_DIR),
        text=True,
        encoding="utf-8",
        errors="replace",
        timeout=1800,
    )

    if result.returncode != 0:
        return {
            "ok": False,
            "article_no": article_no,
            "reason": f"generate_blog_drafts.py returncode={result.returncode}",
            "result": "operating_cli_failed",
        }

    return {
        "ok": True,
        "article_no": article_no,
        "result": "created_by_operating_cli",
    }


def create_one_latest_draft(realtor_id, article_no=None, dry_run=False):
    """
    특정 article_no가 있으면 그 매물을 우선 처리.
    없으면 최신 collected 미초안/미큐 매물 1건 선택.
    """
    conn = get_conn()

    try:
        log("=" * 80)
        log("[STEP109 DRAFT ENGINE START]")
        log("TIME:", datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
        log("realtor_id:", realtor_id)
        log("article_no:", article_no or "(latest)")
        log("dry_run:", dry_run)
        log("=" * 80)

        if article_no:
            row = fetch_article_by_no(conn, realtor_id, article_no)
        else:
            row = fetch_latest_collected_article(conn, realtor_id)

        if not row:
            log("[STEP109 TARGET NONE]")
            return {
                "ok": False,
                "reason": "target_not_found",
            }

        log("[STEP109 TARGET]", safe_json({
            "article_no": row.get("article_no"),
            "article_name": row.get("article_name"),
            "collect_status": row.get("collect_status"),
            "detail_collected": row.get("detail_collected"),
            "first_posted_at": row.get("first_posted_at"),
            "detail_collected_at": row.get("detail_collected_at"),
            "created_at": row.get("created_at"),
        }))

        valid, reason = validate_article_for_draft(row)
        if not valid:
            log("[STEP109 VALIDATION FAIL]", reason)
            return {
                "ok": False,
                "reason": reason,
                "article_no": row.get("article_no"),
            }

        before = fetch_latest_draft_and_queue(conn, realtor_id, row.get("article_no"))
        log("[STEP109 BEFORE]", safe_json(before))

        if dry_run:
            log("[STEP109 DRY RUN] generation skipped")
            return {
                "ok": True,
                "dry_run": True,
                "target": row,
                "before": before,
            }

        result = create_draft_for_article_row(conn, row)
        log("[STEP109 GENERATE RESULT]", safe_json(result))

        after = fetch_latest_draft_and_queue(conn, realtor_id, row.get("article_no"))
        log("[STEP109 AFTER]", safe_json(after))

        log("=" * 80)
        log("[STEP109 DRAFT ENGINE DONE]")
        log("=" * 80)

        return {
            "ok": bool(result.get("ok")),
            "result": result,
            "after": after,
        }

    finally:
        try:
            conn.close()
        except Exception:
            pass
