import re


REGION_TOKENS = [
    "서울", "경기", "인천", "수원", "용인", "성남", "화성", "동탄", "오산",
    "평택", "안양", "안산", "과천", "광명", "시흥", "하남", "남양주", "김포",
    "파주", "고양", "의정부", "대전", "대구", "부산", "광주", "울산", "세종", "제주"
]

PROPERTY_TOKENS = [
    "아파트", "오피스텔", "빌라", "주택", "상가", "토지", "원룸", "투룸", "다가구"
]

TRANSACTION_TOKENS = [
    "매매", "전세", "월세", "분양", "임대", "급매", "투자", "실거주", "매물"
]

INFO_TOKENS = [
    "시세", "학군", "입지", "교통", "생활권", "호재", "비교", "분석", "체크", "정리"
]

CTA_TOKENS = [
    "문의", "상담", "연락", "안내", "추천", "도와드", "문의주세요"
]

APT_BRAND_TOKENS = [
    "자이", "래미안", "푸르지오", "더샵", "힐스테이트", "롯데캐슬", "아이파크",
    "e편한", "리슈빌", "센트럴", "파크", "캐슬", "하이츠", "SK뷰", "두산위브", "포레나", "베르디움",
	"디에트르", "금호어울림", "하늘채", "데시앙", "엘리프", "제일풍경채", "서희", "센트레빌", "한신더휴",
	"스위첸", "듀크", "우미", "비발디", "유보라", "뜰", "플래티넘", "빌리브", "애시앙", "펜테리움", "헤링턴", "더리브", "파크드림"
]


def contains_any(text: str, tokens: list[str]) -> bool:
    return any(token in text for token in tokens)


def keyword_flags(title: str) -> dict:
    return {
        "has_region": contains_any(title, REGION_TOKENS),
        "has_property": contains_any(title, PROPERTY_TOKENS),
        "has_transaction": contains_any(title, TRANSACTION_TOKENS),
        "has_info": contains_any(title, INFO_TOKENS),
        "has_cta": contains_any(title, CTA_TOKENS),
        "has_apt_brand": contains_any(title, APT_BRAND_TOKENS),
    }


def clean_spaces(text: str) -> str:
    return re.sub(r"\s+", " ", text or "").strip()


def score_title(title: str) -> tuple[int, list[str]]:
    issues = []
    score = 100
    t = clean_spaces(title)
    flags = keyword_flags(t)

    title_len = len(t)

    if title_len < 8:
        score -= 20
        issues.append("제목 길이가 너무 짧습니다.")
    elif title_len < 12:
        score -= 10
        issues.append("제목 길이가 다소 짧은 편입니다.")
    elif title_len > 40:
        score -= 8
        issues.append("제목 길이가 다소 긴 편입니다.")

    if not flags["has_region"]:
        score -= 15
        issues.append("지역 키워드가 없습니다.")

    if not flags["has_property"]:
        score -= 12
        issues.append("매물 유형 키워드가 없습니다.")

    if not flags["has_transaction"]:
        score -= 12
        issues.append("거래 유형 키워드가 없습니다.")

    if not flags["has_info"] and not flags["has_cta"]:
        score -= 8
        issues.append("정보형 또는 상담 유도형 표현이 부족합니다.")

    if not flags["has_apt_brand"]:
        issues.append("단지명 또는 브랜드명 키워드가 보이지 않습니다.")

    score = max(0, min(100, score))
    return score, issues


def extract_best_tokens(title: str) -> dict:
    t = clean_spaces(title)

    region = next((x for x in REGION_TOKENS if x in t), "")
    prop = next((x for x in PROPERTY_TOKENS if x in t), "")
    txn = next((x for x in TRANSACTION_TOKENS if x in t), "")
    info = next((x for x in INFO_TOKENS if x in t), "")
    brand = next((x for x in APT_BRAND_TOKENS if x in t), "")

    return {
        "region": region,
        "property": prop,
        "transaction": txn,
        "info": info,
        "brand": brand,
    }


def generate_title_suggestions(title: str) -> list[str]:
    tokens = extract_best_tokens(title)

    region = tokens["region"] or "지역"
    prop = tokens["property"] or "아파트"
    txn = tokens["transaction"] or "매물"
    brand = tokens["brand"]
    info = tokens["info"] or "시세"

    suggestions = []

    if brand:
        suggestions.append(f"{region} {brand} {prop} {txn} {info} 총정리")
        suggestions.append(f"{region} {brand} {prop} {txn} 실거래 및 체크포인트")
        suggestions.append(f"{region} {brand} {prop} {txn} 상담 안내")
    else:
        suggestions.append(f"{region} {prop} {txn} {info} 총정리")
        suggestions.append(f"{region} {prop} {txn} 추천 포인트 및 체크사항")
        suggestions.append(f"{region} {prop} {txn} 문의 전 꼭 볼 내용")

    # 중복 제거
    out = []
    seen = set()
    for s in suggestions:
        s = clean_spaces(s)
        if s and s not in seen:
            seen.add(s)
            out.append(s)

    return out[:3]


def classify_exposure(score: int) -> str:
    if score >= 80:
        return "high"
    if score >= 55:
        return "medium"
    return "low"


def analyze_single_post(post: dict) -> dict:
    title = clean_spaces(post.get("title", ""))
    published_at = post.get("published_at", "")
    category = post.get("category", "")
    post_url = post.get("post_url", "")

    score, issues = score_title(title)
    suggestions = generate_title_suggestions(title)

    strengths = []
    flags = keyword_flags(title)

    if flags["has_region"]:
        strengths.append("지역 키워드가 포함되어 있습니다.")
    if flags["has_property"]:
        strengths.append("매물 유형 키워드가 포함되어 있습니다.")
    if flags["has_transaction"]:
        strengths.append("거래 유형 키워드가 포함되어 있습니다.")
    if flags["has_info"]:
        strengths.append("정보형 키워드가 포함되어 있습니다.")
    if flags["has_cta"]:
        strengths.append("상담 유도형 표현이 포함되어 있습니다.")

    return {
        "title": title,
        "published_at": published_at,
        "category": category,
        "post_url": post_url,
        "score": score,
        "exposure_level": classify_exposure(score),
        "issues": issues[:5],
        "strengths": strengths[:5],
        "suggestions": suggestions,
    }


def analyze_posts_in_detail(posts: list[dict], max_items: int = 10) -> list[dict]:
    results = []
    for post in posts[:max_items]:
        results.append(analyze_single_post(post))
    return results