# -*- coding: utf-8 -*-
"""
STEP105 Human Profile Engine
중개사별 고정 작성 습관 + 매물종류별 tail template 선택.
"""

import json
import random
import hashlib
from pathlib import Path

BASE_DIR = Path(__file__).resolve().parent
PROFILE_DIR = BASE_DIR / "human_profiles"
TEMPLATE_DIR = BASE_DIR / "tail_comment_templates"

DEFAULT_PROFILE = {
    "profile_id": "default",
    "name": "기본형",
    "typing": {
        "min_delay_ms": 35,
        "max_delay_ms": 125,
        "pause_chance": 0.055,
        "long_pause_chance": 0.018,
        "typo_chance": 0.002
    },
    "review": {
        "short_review_min_ms": 5000,
        "short_review_max_ms": 15000,
        "before_publish_min_sec": 30,
        "before_publish_max_sec": 120
    },
    "tail": {
        "min_chars": 260,
        "max_chars": 720,
        "style_weights": {
            "friendly": 4,
            "checklist": 2,
            "question": 2,
            "concise": 2
        }
    }
}


def _safe_json_load(path):
    try:
        return json.loads(Path(path).read_text(encoding="utf-8"))
    except Exception:
        return None


def list_profiles():
    if not PROFILE_DIR.exists():
        return []

    rows = []
    for path in sorted(PROFILE_DIR.glob("profile_*.json")):
        data = _safe_json_load(path)
        if data:
            rows.append(data)
    return rows


def stable_profile_index(realtor_id, profile_count):
    if profile_count <= 0:
        return 0

    key = str(realtor_id or "0").encode("utf-8")
    digest = hashlib.sha256(key).hexdigest()
    return int(digest[:8], 16) % profile_count


def get_human_profile(realtor_id=None, profile_id=None):
    profiles = list_profiles()

    if profile_id:
        for profile in profiles:
            if str(profile.get("profile_id")) == str(profile_id):
                return profile

    if profiles:
        idx = stable_profile_index(realtor_id, len(profiles))
        return profiles[idx]

    return DEFAULT_PROFILE


def get_typing_config(profile):
    profile = profile or DEFAULT_PROFILE
    cfg = dict(DEFAULT_PROFILE["typing"])
    cfg.update(profile.get("typing") or {})
    return cfg


def get_review_config(profile):
    profile = profile or DEFAULT_PROFILE
    cfg = dict(DEFAULT_PROFILE["review"])
    cfg.update(profile.get("review") or {})
    return cfg


def normalize_property_type(value):
    text = str(value or "").strip().lower()

    if text in ["apt", "apartment", "아파트"]:
        return "apartment"
    if text in ["villa", "빌라", "연립", "다세대"]:
        return "villa"
    if text in ["officetel", "오피스텔"]:
        return "officetel"
    if text in ["store", "상가", "상업시설", "사무실"]:
        return "store"
    if text in ["land", "토지", "대지", "임야", "전", "답"]:
        return "land"
    if text in ["building", "건물", "다가구", "단독", "상가주택"]:
        return "building"

    if "아파트" in text:
        return "apartment"
    if "오피스텔" in text:
        return "officetel"
    if any(x in text for x in ["빌라", "연립", "다세대"]):
        return "villa"
    if any(x in text for x in ["상가", "사무실"]):
        return "store"
    if any(x in text for x in ["토지", "대지", "임야"]):
        return "land"
    if any(x in text for x in ["다가구", "단독", "건물", "상가주택"]):
        return "building"

    return "default"


def detect_property_type_from_context(draft=None, queue=None):
    draft = draft or {}
    queue = queue or {}

    candidates = [
        draft.get("real_estate_type"),
        draft.get("real_estate_type_name"),
        draft.get("property_type"),
        draft.get("draft_title"),
        queue.get("real_estate_type"),
        queue.get("publish_title"),
        queue.get("article_no"),
    ]

    source = draft.get("source_json")
    if isinstance(source, dict):
        detail = source.get("detail") or {}
        if isinstance(detail, dict):
            candidates.extend([
                detail.get("real_estate_type"),
                detail.get("real_estate_type_name"),
                detail.get("article_name"),
                detail.get("building_name"),
            ])

    merged = " ".join([str(x or "") for x in candidates])
    return normalize_property_type(merged)


def _weighted_choice(weight_map):
    items = []
    for key, weight in (weight_map or {}).items():
        try:
            w = int(weight)
        except Exception:
            w = 1
        items.extend([key] * max(1, w))

    if not items:
        return "friendly"

    return random.choice(items)


def load_tail_templates(property_type, style=None):
    property_type = normalize_property_type(property_type)
    style = str(style or "").strip()

    dirs = [
        TEMPLATE_DIR / property_type,
        TEMPLATE_DIR / "default",
    ]

    files = []
    for d in dirs:
        if not d.exists():
            continue

        if style:
            files.extend(sorted(d.glob(f"*_{style}_*.txt")))
            files.extend(sorted(d.glob(f"{style}_*.txt")))

        files.extend(sorted(d.glob("*.txt")))

    unique = []
    seen = set()
    for f in files:
        if str(f) in seen:
            continue
        seen.add(str(f))
        unique.append(f)

    return unique


def render_tail_template(text, context=None):
    context = context or {}

    values = {
        "title": context.get("title") or "오늘 소개드린 매물",
        "office_name": context.get("office_name") or "중개사무소",
        "trade_type": context.get("trade_type") or "거래",
        "property_type": context.get("property_type") or "매물",
        "price": context.get("price") or "",
        "region": context.get("region") or "",
    }

    for key, value in values.items():
        text = text.replace("{" + key + "}", str(value or ""))

    return text.strip()


def build_profile_tail_comment(realtor_id=None, profile=None, property_type="default", context=None):
    profile = profile or get_human_profile(realtor_id=realtor_id)
    tail_cfg = dict(DEFAULT_PROFILE["tail"])
    tail_cfg.update(profile.get("tail") or {})

    style = _weighted_choice(tail_cfg.get("style_weights") or {})
    files = load_tail_templates(property_type=property_type, style=style)

    if not files:
        return ""

    path = random.choice(files)
    text = path.read_text(encoding="utf-8", errors="replace").strip()
    text = render_tail_template(text, context=context or {})

    min_chars = int(tail_cfg.get("min_chars") or 260)
    max_chars = int(tail_cfg.get("max_chars") or 720)

    if len(text) > max_chars:
        text = text[:max_chars].rsplit(" ", 1)[0].strip()

    if len(text) < min_chars:
        extra_files = load_tail_templates(property_type="default", style="concise")
        if extra_files:
            extra = random.choice(extra_files).read_text(encoding="utf-8", errors="replace").strip()
            extra = render_tail_template(extra, context=context or {})
            text = (text + "\n\n" + extra).strip()

    return text


def profile_summary(profile):
    profile = profile or DEFAULT_PROFILE
    return {
        "profile_id": profile.get("profile_id"),
        "name": profile.get("name"),
        "typing": get_typing_config(profile),
        "review": get_review_config(profile),
        "tail": profile.get("tail") or {},
    }
