import re


REGION_TOKENS = [
    "서울", "경기", "인천", "수원", "용인", "성남", "화성", "동탄", "오산",
    "평택", "안양", "안산", "과천", "광명", "시흥", "하남", "남양주", "김포",
    "파주", "고양", "의정부", "대전", "대구", "부산", "광주", "울산", "세종", "제주"
]

PROPERTY_TOKENS = [
    "아파트", "오피스텔", "빌라", "주택", "상가", "토지", "원룸", "투룸", "다가구"
]

TRANSACTION_TOKENS = [
    "매매", "전세", "월세", "분양", "임대", "급매", "투자", "실거주", "매물"
]

INFO_TOKENS = [
    "시세", "실거래가", "입지", "학군", "교통", "호재", "생활권",
    "분석", "비교", "체크", "정리", "가격"
]

CTA_TOKENS = [
    "문의", "상담", "연락", "안내", "확인", "체크포인트",
    "상담 전", "문의주세요", "연락주세요", "방문", "예약"
]

URGENCY_TOKENS = [
    "급매", "추천", "희소", "저렴", "인기", "마감", "빠른",
    "좋은 조건", "실속", "놓치면", "바로"
]


def clean_text(text):
    return re.sub(r"\s+", " ", str(text or "")).strip()


def has_any(text, tokens):
    text = clean_text(text)
    return any(token in text for token in tokens)


def count_posts_with(posts, tokens):
    count = 0

    for post in posts or []:
        title = clean_text(post.get("title", ""))
        if has_any(title, tokens):
            count += 1

    return count


def grade_by_score(score):
    score = float(score or 0)

    if score >= 85:
        return "A+"
    if score >= 75:
        return "A"
    if score >= 60:
        return "B"
    if score >= 45:
        return "C"
    return "D"


def build_conversion_score(posts, analysis=None):
    analysis = analysis or {}
    posts = posts or []
    total = len(posts)

    if total == 0:
        return {
            "score": 0,
            "grade": "D",
            "summary": "게시글 데이터가 부족해 문의 전환 가능성을 판단하기 어렵습니다.",
            "strong_points": [],
            "weak_points": ["최근 게시글 데이터가 없습니다."],
            "actions": ["먼저 게시글 수집 상태를 확인하세요."],
            "metrics": {
                "total_posts": 0,
                "region_count": 0,
                "property_count": 0,
                "transaction_count": 0,
                "info_count": 0,
                "cta_count": 0,
                "urgency_count": 0,
                "recent_30d_posts": 0
            }
        }

    region_count = count_posts_with(posts, REGION_TOKENS)
    property_count = count_posts_with(posts, PROPERTY_TOKENS)
    transaction_count = count_posts_with(posts, TRANSACTION_TOKENS)
    info_count = count_posts_with(posts, INFO_TOKENS)
    cta_count = count_posts_with(posts, CTA_TOKENS)
    urgency_count = count_posts_with(posts, URGENCY_TOKENS)

    recent_30d = int(analysis.get("recent_30d_posts", 0) or 0)

    score = 20
    score += min(region_count / total * 18, 18)
    score += min(property_count / total * 15, 15)
    score += min(transaction_count / total * 15, 15)
    score += min(info_count / total * 14, 14)
    score += min(cta_count / total * 18, 18)
    score += min(urgency_count / total * 10, 10)

    if recent_30d >= 8:
        score += 10
    elif recent_30d >= 4:
        score += 6
    elif recent_30d >= 1:
        score += 3

    score = round(max(0, min(100, score)), 2)
    grade = grade_by_score(score)

    strong_points = []
    weak_points = []
    actions = []

    if region_count > 0:
        strong_points.append("지역명이 포함되어 지역 검색 유입에 유리합니다.")
    else:
        weak_points.append("지역명이 부족해 주변 고객 검색에 약할 수 있습니다.")
        actions.append("제목에 동네명, 역명, 단지명을 더 명확히 넣으세요.")

    if property_count > 0:
        strong_points.append("매물 유형이 포함되어 고객이 글의 목적을 쉽게 파악할 수 있습니다.")
    else:
        weak_points.append("아파트, 오피스텔, 상가 등 매물 유형 표현이 부족합니다.")
        actions.append("매물 유형 키워드를 제목 앞부분에 넣으세요.")

    if transaction_count > 0:
        strong_points.append("매매·전세·월세 등 거래 의도가 드러납니다.")
    else:
        weak_points.append("거래유형 키워드가 부족해 실수요 검색 대응이 약합니다.")
        actions.append("매매, 전세, 월세, 급매 같은 거래유형을 제목에 포함하세요.")

    if info_count > 0:
        strong_points.append("시세·입지·실거래가 등 상담 전 정보 요소가 있습니다.")
    else:
        weak_points.append("상담을 유도할 정보형 키워드가 부족합니다.")
        actions.append("시세, 실거래가, 입지, 학군, 교통 같은 정보형 키워드를 보강하세요.")

    if cta_count > 0:
        strong_points.append("상담 또는 문의로 이어질 수 있는 표현이 포함되어 있습니다.")
    else:
        weak_points.append("문의 전환을 유도하는 문구가 부족합니다.")
        actions.append("상담 전 확인사항, 문의 안내, 체크포인트 같은 문구를 추가하세요.")

    if urgency_count > 0:
        strong_points.append("급매·추천 등 즉시 클릭을 유도할 표현이 일부 있습니다.")
    else:
        weak_points.append("고객이 지금 눌러야 할 이유가 약합니다.")
        actions.append("급매, 추천, 체크포인트, 주의사항 같은 클릭 유도 표현을 자연스럽게 넣으세요.")

    if score >= 75:
        summary = "문의 전환 가능성이 높은 편입니다. 현재 방향을 유지하면서 상담 유도 문구를 더 강화하면 좋습니다."
    elif score >= 60:
        summary = "문의 전환 가능성은 보통 이상입니다. 제목에 상담 전 확인사항과 실거래가 정보를 더 넣으면 좋아집니다."
    elif score >= 45:
        summary = "문의 전환 가능성이 다소 약합니다. 지역명, 거래유형, 상담 유도 문구를 우선 보강해야 합니다."
    else:
        summary = "문의 전환 가능성이 낮은 편입니다. 고객이 클릭하고 문의할 이유를 제목에서 더 분명히 보여줘야 합니다."

    return {
        "score": score,
        "grade": grade,
        "summary": summary,
        "strong_points": strong_points[:5],
        "weak_points": weak_points[:5],
        "actions": actions[:6],
        "metrics": {
            "total_posts": total,
            "region_count": region_count,
            "property_count": property_count,
            "transaction_count": transaction_count,
            "info_count": info_count,
            "cta_count": cta_count,
            "urgency_count": urgency_count,
            "recent_30d_posts": recent_30d
        }
    }