def contains_any(text: str, tokens: list[str]) -> bool:
    return any(token in text for token in tokens)


REGION_TOKENS = [
    "서울", "경기", "인천", "수원", "용인", "성남", "화성", "동탄", "오산",
    "평택", "안양", "안산", "과천", "광명", "시흥", "하남", "남양주", "김포",
    "파주", "고양", "의정부", "대전", "대구", "부산", "광주", "울산", "세종", "제주"
]

PROPERTY_TOKENS = [
    "아파트", "오피스텔", "빌라", "주택", "상가", "토지", "원룸", "투룸", "다가구"
]

TRANSACTION_TOKENS = [
    "매매", "전세", "월세", "분양", "임대", "급매", "투자", "실거주", "매물"
]

INFO_TOKENS = [
    "시세", "학군", "입지", "교통", "생활권", "호재", "비교", "분석", "체크", "정리"
]

APT_BRAND_TOKENS = [
    "자이", "래미안", "푸르지오", "더샵", "힐스테이트", "롯데캐슬", "아이파크",
    "e편한", "리슈빌", "센트럴", "파크", "캐슬", "하이츠", "SK뷰", "두산위브", "포레나", "베르디움",
	"디에트르", "금호어울림", "하늘채", "데시앙", "엘리프", "제일풍경채", "서희", "센트레빌", "한신더휴",
	"스위첸", "듀크", "우미", "비발디", "유보라", "뜰", "플래티넘", "빌리브", "애시앙", "펜테리움", "헤링턴", "더리브", "파크드림"
]



def summarize_post_features(post_analysis: list[dict]) -> dict:
    total = len(post_analysis or [])
    if total == 0:
        return {
            "count": 0,
            "avg_score": 0,
            "region_titles": 0,
            "property_titles": 0,
            "transaction_titles": 0,
            "info_titles": 0,
            "brand_titles": 0,
        }

    total_score = 0
    region_titles = 0
    property_titles = 0
    transaction_titles = 0
    info_titles = 0
    brand_titles = 0

    for item in post_analysis:
        title = str(item.get("title", "")).strip()
        total_score += float(item.get("score", 0) or 0)

        if contains_any(title, REGION_TOKENS):
            region_titles += 1
        if contains_any(title, PROPERTY_TOKENS):
            property_titles += 1
        if contains_any(title, TRANSACTION_TOKENS):
            transaction_titles += 1
        if contains_any(title, INFO_TOKENS):
            info_titles += 1
        if contains_any(title, APT_BRAND_TOKENS):
            brand_titles += 1

    return {
        "count": total,
        "avg_score": round(total_score / total, 2),
        "region_titles": region_titles,
        "property_titles": property_titles,
        "transaction_titles": transaction_titles,
        "info_titles": info_titles,
        "brand_titles": brand_titles,
    }


def build_pairwise_insight(base_result: dict, competitor_result: dict) -> dict:
    base_blog_id = base_result.get("blog", {}).get("blog_id", "")
    comp_blog_id = competitor_result.get("blog", {}).get("blog_id", "")

    base_analysis = base_result.get("analysis", {}) or {}
    comp_analysis = competitor_result.get("analysis", {}) or {}

    base_posts = base_analysis.get("post_analysis", []) or []
    comp_posts = comp_analysis.get("post_analysis", []) or []

    base_summary = summarize_post_features(base_posts)
    comp_summary = summarize_post_features(comp_posts)

    comments = []
    actions = []

    if comp_summary["avg_score"] > base_summary["avg_score"] + 8:
        comments.append(
            f"{comp_blog_id}의 최근 게시글 제목 평균 점수가 {base_blog_id}보다 더 높아 검색형 제목 구조가 더 안정적일 가능성이 큽니다."
        )
        actions.append(
            f"{base_blog_id}는 제목에 지역명, 거래유형, 매물유형 조합을 더 명확히 넣는 방식으로 제목 구조를 개선해보세요."
        )

    if comp_summary["region_titles"] > base_summary["region_titles"]:
        comments.append(
            f"{comp_blog_id}는 지역명 포함 제목 비중이 더 높아 지역 검색 유입 대응이 강한 편입니다."
        )
        actions.append(
            f"{base_blog_id}는 지역명 키워드를 제목 앞부분에 더 자주 배치하는 것이 좋습니다."
        )

    if comp_summary["transaction_titles"] > base_summary["transaction_titles"]:
        comments.append(
            f"{comp_blog_id}는 매매·전세·월세 같은 거래형 키워드 사용 빈도가 더 높습니다."
        )
        actions.append(
            f"{base_blog_id}는 거래유형 키워드를 제목에 적극적으로 넣어 실수요 검색 대응을 강화하세요."
        )

    if comp_summary["info_titles"] > base_summary["info_titles"]:
        comments.append(
            f"{comp_blog_id}는 시세·입지·학군 같은 정보형 제목 비중이 더 높아 검색 유입 폭이 넓을 가능성이 있습니다."
        )
        actions.append(
            f"{base_blog_id}는 매물 소개형 글 외에 시세, 입지, 비교, 체크형 글을 섞어 콘텐츠 폭을 넓히세요."
        )

    if comp_summary["brand_titles"] > base_summary["brand_titles"]:
        comments.append(
            f"{comp_blog_id}는 단지명 또는 브랜드명 중심 제목 비중이 더 높아 특정 매물 검색 대응이 유리할 수 있습니다."
        )
        actions.append(
            f"{base_blog_id}는 자이, 푸르지오, 래미안 등 브랜드명이나 단지명을 제목에 더 적극 반영하세요."
        )

    base_recent30 = int(base_analysis.get("recent_30d_posts", 0) or 0)
    comp_recent30 = int(comp_analysis.get("recent_30d_posts", 0) or 0)

    if comp_recent30 > base_recent30:
        comments.append(
            f"{comp_blog_id}는 최근 30일 발행량이 더 많아 최신성 누적 측면에서 유리합니다."
        )
        actions.append(
            f"{base_blog_id}는 최근 발행량을 늘려 최소 주 1~2회 이상의 꾸준한 발행 패턴을 확보하는 것이 좋습니다."
        )

    base_final = float(base_analysis.get("final_score", 0) or 0)
    comp_final = float(comp_analysis.get("final_score", 0) or 0)

    if comp_final > base_final + 10:
        comments.append(
            f"{comp_blog_id}는 전체 운영 점수에서도 우위를 보이고 있어 콘텐츠 구조와 발행 패턴을 함께 벤치마킹할 가치가 있습니다."
        )

    dedup_comments = []
    seen_comments = set()
    for item in comments:
        if item not in seen_comments:
            seen_comments.add(item)
            dedup_comments.append(item)

    dedup_actions = []
    seen_actions = set()
    for item in actions:
        if item not in seen_actions:
            seen_actions.add(item)
            dedup_actions.append(item)

    return {
        "base_blog_id": base_blog_id,
        "competitor_blog_id": comp_blog_id,
        "base_summary": base_summary,
        "competitor_summary": comp_summary,
        "comments": dedup_comments[:6],
        "actions": dedup_actions[:5],
    }


def build_batch_comparison_insights(results: list[dict], base_blog_id: str = "") -> list[dict]:
    successful = [x for x in results if x.get("success")]
    if len(successful) < 2:
        return []

    base = None

    if base_blog_id:
        for item in successful:
            if item.get("blog", {}).get("blog_id", "") == base_blog_id:
                base = item
                break

    if base is None:
        base = successful[0]

    competitors = [
        x for x in successful
        if x.get("blog", {}).get("blog_id", "") != base.get("blog", {}).get("blog_id", "")
    ]

    insights = []
    for comp in competitors:
        insights.append(build_pairwise_insight(base, comp))

    return insights