# -*- coding: utf-8 -*-

import random
import json
import sys
from pathlib import Path

try:
    from .human_typing import human_type_text
    from .human_profile import (
        get_human_profile,
        get_typing_config,
        detect_property_type_from_context,
        normalize_property_type,
        build_profile_tail_comment,
    )
except Exception:
    from human_typing import human_type_text
    from human_profile import (
        get_human_profile,
        get_typing_config,
        detect_property_type_from_context,
        normalize_property_type,
        build_profile_tail_comment,
    )


BASE_DIR = Path(__file__).resolve().parents[2]
if str(BASE_DIR) not in sys.path:
    sys.path.append(str(BASE_DIR))


def _safe_get(row, key, default=""):
    if not row:
        return default

    try:
        if isinstance(row, dict):
            return row.get(key, default)
        return getattr(row, key, default)
    except Exception:
        return default


def _parse_json_maybe(value):
    if not value:
        return {}

    if isinstance(value, dict):
        return value

    try:
        return json.loads(str(value))
    except Exception:
        return {}


def _get_conn():
    try:
        from db import get_conn
        return get_conn()
    except Exception as e:
        print("[TAIL DB WARN] get_conn failed:", str(e))
        return None


def _fetch_one(cur, sql, params):
    try:
        cur.execute(sql, params)
        return cur.fetchone() or {}
    except Exception:
        return {}


def load_tail_context_from_db(queue=None):
    queue = queue or {}
    draft_id = _safe_get(queue, "draft_id")
    article_no = _safe_get(queue, "article_no")
    realtor_id = _safe_get(queue, "realtor_id")

    result = {
        "queue": dict(queue) if isinstance(queue, dict) else {},
        "draft": {},
        "article": {},
        "realtor": {},
    }

    conn = _get_conn()
    if not conn:
        return result

    try:
        with conn.cursor() as cur:
            if draft_id:
                result["draft"] = _fetch_one(
                    cur,
                    "SELECT * FROM blog_article_drafts WHERE id=%s LIMIT 1",
                    (draft_id,),
                )

            if not article_no:
                article_no = _safe_get(result["draft"], "article_no")

            if article_no:
                result["article"] = _fetch_one(
                    cur,
                    "SELECT * FROM blog_realtor_articles WHERE article_no=%s LIMIT 1",
                    (article_no,),
                )

            if realtor_id:
                result["realtor"] = _fetch_one(
                    cur,
                    "SELECT * FROM blog_realtors WHERE id=%s LIMIT 1",
                    (realtor_id,),
                )

    except Exception as e:
        print("[TAIL DB WARN] context load failed:", str(e))
    finally:
        try:
            conn.close()
        except Exception:
            pass

    return result


def detect_property_type_v2(draft=None, queue=None, article=None):
    draft = draft or {}
    queue = queue or {}
    article = article or {}

    source_json = _parse_json_maybe(_safe_get(draft, "source_json"))
    detail = {}
    if isinstance(source_json, dict):
        detail = source_json.get("detail") or source_json.get("article_detail") or {}

    candidates = [
        _safe_get(draft, "property_type"),
        _safe_get(draft, "real_estate_type"),
        _safe_get(draft, "real_estate_type_name"),
        _safe_get(draft, "article_type"),
        _safe_get(draft, "article_name"),
        _safe_get(draft, "draft_title"),
        _safe_get(article, "property_type"),
        _safe_get(article, "real_estate_type"),
        _safe_get(article, "real_estate_type_name"),
        _safe_get(article, "article_type"),
        _safe_get(article, "article_type_name"),
        _safe_get(article, "realestate_type_code"),
        _safe_get(article, "realestate_type_name"),
        _safe_get(article, "article_name"),
        _safe_get(article, "article_title"),
        _safe_get(article, "building_type_name"),
        _safe_get(article, "trade_building_type_code"),
        _safe_get(queue, "publish_title"),
        _safe_get(queue, "article_no"),
    ]

    if isinstance(detail, dict):
        candidates.extend([
            detail.get("realestateTypeName"),
            detail.get("realestateTypeCode"),
            detail.get("articleTypeCode"),
            detail.get("articleName"),
            detail.get("articleSubName"),
            detail.get("buildingTypeName"),
            detail.get("lawUsage"),
            detail.get("principalUse"),
        ])

    merged = " ".join([str(x or "") for x in candidates])
    normalized = normalize_property_type(merged)

    upper = merged.upper()
    if normalized == "default":
        if any(x in upper for x in ["APT", "ABYG", "JGC"]):
            normalized = "apartment"
        elif any(x in upper for x in ["OPST", "OFFICETEL"]):
            normalized = "officetel"
        elif any(x in upper for x in ["VL", "DDDGG", "JWJT"]):
            normalized = "villa"

    if normalized == "default":
        apartment_keywords = [
            "아파트", "맨션", "단지", "마스터힐스", "힐스테이트", "자이", "푸르지오",
            "래미안", "아이파크", "더샵", "롯데캐슬", "e편한세상", "이편한세상",
            "센트럴", "리버파크", "파크뷰", "파크", "시티", "타워", "스위첸",
            "우미린", "호반", "중흥", "한신", "한화", "꿈에그린", "데시앙",
            "리슈빌", "마을", "주공", "휴먼시아", "LH", "해밀", "가온", "새뜸",
            "도램", "범지기", "수루배", "첫마을"
        ]

        building_keywords = [
            "다가구", "단독주택", "상가주택", "건물", "원룸건물", "꼬마빌딩"
        ]

        store_keywords = [
            "상가", "점포", "사무실", "근린생활", "근생", "상업시설"
        ]

        land_keywords = [
            "토지", "대지", "임야", "전답", "농지", "공장용지"
        ]

        villa_keywords = [
            "빌라", "연립", "다세대", "주택형빌라"
        ]

        officetel_keywords = [
            "오피스텔", "오피스", "생활형숙박"
        ]

        if any(x in merged for x in apartment_keywords):
            normalized = "apartment"
        elif any(x in merged for x in officetel_keywords):
            normalized = "officetel"
        elif any(x in merged for x in villa_keywords):
            normalized = "villa"
        elif any(x in merged for x in store_keywords):
            normalized = "store"
        elif any(x in merged for x in land_keywords):
            normalized = "land"
        elif any(x in merged for x in building_keywords):
            normalized = "building"

    return normalized


def _build_context(draft=None, queue=None, article=None, realtor=None, property_type=""):
    draft = draft or {}
    queue = queue or {}
    article = article or {}
    realtor = realtor or {}

    source_json = _parse_json_maybe(_safe_get(draft, "source_json"))
    detail = {}
    if isinstance(source_json, dict):
        detail = source_json.get("detail") or source_json.get("article_detail") or {}

    title = (
        _safe_get(draft, "draft_title")
        or _safe_get(article, "article_name")
        or (detail.get("articleName") if isinstance(detail, dict) else "")
        or _safe_get(queue, "publish_title")
        or _safe_get(queue, "article_no")
        or "오늘 소개드린 매물"
    )

    trade_type = (
        _safe_get(article, "trade_type_name")
        or _safe_get(article, "trade_type")
        or (detail.get("tradeTypeName") if isinstance(detail, dict) else "")
        or ""
    )

    price = (
        _safe_get(article, "price_text")
        or _safe_get(draft, "price_text")
        or (detail.get("dealOrWarrantPrc") if isinstance(detail, dict) else "")
        or ""
    )

    region = (
        _safe_get(article, "exposure_address")
        or _safe_get(article, "address")
        or _safe_get(draft, "address")
        or (detail.get("exposureAddress") if isinstance(detail, dict) else "")
        or ""
    )

    return {
        "title": str(title or "").strip(),
        "office_name": str(_safe_get(realtor, "office_name") or _safe_get(draft, "office_name") or "").strip(),
        "trade_type": str(trade_type or "").strip(),
        "property_type": str(property_type or "").strip(),
        "price": str(price or "").strip(),
        "region": str(region or "").strip(),
    }


def _sentence_key(text):
    text = str(text or "").strip()
    text = text.replace("\n", " ")
    text = " ".join(text.split())
    return text[:42]


def _ensure_min_tail_length(comment, context=None, min_len=300):
    comment = str(comment or "").strip()

    extras = [
        "방문 전에는 현재 매물 가능 여부와 조건 변동 여부를 먼저 확인해 주세요. 같은 조건처럼 보여도 실제 현장에서는 채광, 소음, 주차, 동선에서 차이가 날 수 있습니다.",
        "사진과 기본 정보만으로는 판단하기 어려운 부분이 있으니 가능하다면 직접 방문해서 구조와 주변 분위기를 함께 보시는 것을 추천드립니다.",
        "가격과 입주 가능일, 관리비, 수리 여부는 상담 시점에 다시 확인하는 것이 가장 정확합니다. 문의 주시면 현재 확인 가능한 기준으로 안내드리겠습니다.",
        "생활권을 함께 비교하시면 선택이 더 쉬워집니다. 출퇴근 동선, 장보기, 병원, 학교, 대중교통 접근성처럼 매일 이용하는 부분도 함께 체크해보시면 좋습니다.",
        "실제 방문하실 때는 낮 시간대의 채광과 저녁 시간대의 주변 분위기를 함께 비교해보시면 더 현실적인 판단에 도움이 됩니다.",
        "계약을 검토하실 때는 등기, 대출 가능 여부, 잔금 일정처럼 실제 진행 과정에서 필요한 부분도 함께 확인하는 것이 좋습니다.",
        "조건이 마음에 드신다면 비슷한 매물과 가격, 위치, 내부 상태를 함께 비교해보시는 것도 좋은 방법입니다.",
        "문의 주시면 현재 확인 가능한 매물 상태와 방문 가능 시간을 기준으로 차분히 안내드리겠습니다.",
    ]

    existing_keys = set()
    for block in comment.split("\n\n"):
        key = _sentence_key(block)
        if key:
            existing_keys.add(key)

    random.shuffle(extras)

    for extra in extras:
        if len(comment) >= min_len:
            break

        key = _sentence_key(extra)
        if not key or key in existing_keys:
            continue

        if extra[:28] in comment or extra[-28:] in comment:
            continue

        comment = (comment + "\n\n" + extra).strip()
        existing_keys.add(key)

    if len(comment) < min_len:
        fallback = "매물 조건은 시점에 따라 달라질 수 있으니 상담 시 최신 기준으로 다시 확인해드리겠습니다."
        if fallback not in comment:
            comment = (comment + "\n\n" + fallback).strip()

    return comment


def build_human_tail_comment(draft=None, queue=None, realtor_id=None, profile_id=None):
    dbctx = load_tail_context_from_db(queue=queue)

    loaded_draft = dbctx.get("draft") or {}
    loaded_article = dbctx.get("article") or {}
    loaded_realtor = dbctx.get("realtor") or {}

    merged_draft = {}
    merged_draft.update(loaded_draft)
    if isinstance(draft, dict):
        merged_draft.update(draft)

    merged_queue = {}
    merged_queue.update(dbctx.get("queue") or {})
    if isinstance(queue, dict):
        merged_queue.update(queue)

    rid = realtor_id or _safe_get(merged_queue, "realtor_id") or _safe_get(loaded_realtor, "id")
    profile = get_human_profile(realtor_id=rid, profile_id=profile_id)

    property_type = detect_property_type_v2(
        draft=merged_draft,
        queue=merged_queue,
        article=loaded_article,
    )

    context = _build_context(
        draft=merged_draft,
        queue=merged_queue,
        article=loaded_article,
        realtor=loaded_realtor,
        property_type=property_type,
    )

    comment = build_profile_tail_comment(
        realtor_id=rid,
        profile=profile,
        property_type=property_type,
        context=context,
    )

    comment = _ensure_min_tail_length(comment, context=context, min_len=300)

    if comment:
        print(
            "[TAIL PROFILE]",
            f"profile={profile.get('profile_id')}",
            f"name={profile.get('name')}",
            f"property_type={property_type}",
            f"title={context.get('title')}",
            f"len={len(comment)}",
        )
        return comment

    return _ensure_min_tail_length(
        "방문 전에는 현재 매물 가능 여부와 조건 변동 여부를 먼저 확인해 주세요.",
        context=context,
        min_len=300,
    )


def type_tail_comment_after_body(page, frame=None, draft=None, queue=None, realtor_id=None, profile_id=None):
    rid = realtor_id or _safe_get(queue, "realtor_id")
    comment = build_human_tail_comment(
        draft=draft,
        queue=queue,
        realtor_id=rid,
        profile_id=profile_id,
    )

    if not comment:
        print("[TAIL COMMENT SKIP] empty")
        return False

    profile = get_human_profile(realtor_id=rid, profile_id=profile_id)
    typing_cfg = get_typing_config(profile)

    print("[TAIL COMMENT START]", f"len={len(comment)}")

    try:
        page.keyboard.press("End")
        page.wait_for_timeout(random.randint(400, 900))
        page.keyboard.press("Enter")
        page.keyboard.press("Enter")
        page.wait_for_timeout(random.randint(500, 1300))

        typed = human_type_text(
            page=page,
            text=comment,
            min_delay_ms=typing_cfg.get("min_delay_ms", 35),
            max_delay_ms=typing_cfg.get("max_delay_ms", 125),
            pause_chance=typing_cfg.get("pause_chance", 0.055),
        )

        page.wait_for_timeout(random.randint(800, 1800))

        print("[TAIL COMMENT DONE]", f"len={len(comment)}", f"typed={typed}")
        return True

    except Exception as e:
        print("[TAIL COMMENT ERROR]", str(e))
        return False
