#!/usr/bin/env python3
"""Google Ads CLI - Google Ads API 관리 도구"""

import argparse
import json
import sys
from typing import NoReturn

sys.path.insert(0, "/home/jay/workspace")
from utils.google_ads_client import GoogleAdsClient  # type: ignore[import-not-found]

# ---------------------------------------------------------------------------
# 헬퍼
# ---------------------------------------------------------------------------


def mask_token(token: str) -> str:
    """토큰 앞 8자 + '...' + 뒤 4자 마스킹"""
    if not token:
        return "(empty)"
    if len(token) <= 12:
        return "*" * len(token)
    return token[:8] + "..." + token[-4:]


def error_exit(message: str) -> NoReturn:
    """에러 메시지를 stderr로 출력하고 exit 1"""
    print(f"Error: {message}", file=sys.stderr)
    sys.exit(1)


def print_json(data) -> None:
    """JSON 형식으로 출력"""
    print(json.dumps(data, indent=2, ensure_ascii=False, default=str))


# ---------------------------------------------------------------------------
# 명령어 핸들러
# ---------------------------------------------------------------------------


def cmd_status(client: GoogleAdsClient, _args: argparse.Namespace) -> None:
    """status: 계정 정보 출력"""
    try:
        account_info = client.get_account_info()
    except Exception as e:
        error_exit(f"계정 정보 조회 실패: {e}")

    print_json({"account": account_info})


# ---------------------------------------------------------------------------


def cmd_campaigns_list(client: GoogleAdsClient, args: argparse.Namespace) -> None:
    """campaigns list: 캠페인 목록 출력"""
    limit: int = getattr(args, "limit", 25)
    try:
        campaigns = client.list_campaigns(limit=limit)
    except Exception as e:
        error_exit(f"캠페인 목록 조회 실패: {e}")

    print_json(campaigns)


def cmd_campaigns_create(client: GoogleAdsClient, args: argparse.Namespace) -> None:
    """campaigns create: 캠페인 생성 (status=PAUSED 고정)"""
    try:
        result = client.create_campaign(
            name=args.name,
            budget_amount=args.budget,
            status="PAUSED",
        )
    except Exception as e:
        error_exit(f"캠페인 생성 실패: {e}")

    print_json(result)


def cmd_campaigns_get(client: GoogleAdsClient, args: argparse.Namespace) -> None:
    """campaigns get: 단일 캠페인 조회"""
    try:
        result = client.get_campaign(campaign_id=args.id)
    except Exception as e:
        error_exit(f"캠페인 조회 실패: {e}")

    print_json(result)


def cmd_campaigns_delete(client: GoogleAdsClient, args: argparse.Namespace) -> None:
    """campaigns delete: 캠페인 삭제 (REMOVED 상태)"""
    try:
        success = client.delete_campaign(campaign_id=args.id)
    except Exception as e:
        error_exit(f"캠페인 삭제 실패: {e}")

    print_json({"success": success, "campaign_id": args.id})


# ---------------------------------------------------------------------------


def cmd_insights(client: GoogleAdsClient, args: argparse.Namespace) -> None:
    """insights: 광고 성과 리포트 조회"""
    try:
        results = client.get_insights(
            entity_id=args.entity_id,
            entity_type=args.entity_type,
            date_range=args.date_range,
        )
    except Exception as e:
        error_exit(f"인사이트 조회 실패: {e}")

    print_json(results)


# ---------------------------------------------------------------------------


def cmd_keywords_list(client: GoogleAdsClient, args: argparse.Namespace) -> None:
    """keywords list: 키워드 목록 출력"""
    try:
        keywords = client.list_keywords(
            ad_group_id=args.ad_group_id,
            limit=getattr(args, "limit", 25),
        )
    except Exception as e:
        error_exit(f"키워드 목록 조회 실패: {e}")

    print_json(keywords)


def cmd_keywords_add(client: GoogleAdsClient, args: argparse.Namespace) -> None:
    """keywords add: 키워드 추가

    --keywords 인자는 JSON 배열 문자열로 전달.
    예: '[{"text": "보험", "match_type": "BROAD"}]'
    """
    try:
        keywords_data = json.loads(args.keywords)
    except json.JSONDecodeError as e:
        error_exit(f"--keywords JSON 파싱 실패: {e}")

    try:
        result = client.add_keywords(
            ad_group_id=args.ad_group_id,
            keywords=keywords_data,
        )
    except Exception as e:
        error_exit(f"키워드 추가 실패: {e}")

    print_json(result)


# ---------------------------------------------------------------------------


def cmd_ad_groups_list(client: GoogleAdsClient, args: argparse.Namespace) -> None:
    """ad-groups list: 광고그룹 목록 출력"""
    campaign_id: str | None = getattr(args, "campaign_id", None)
    limit: int = getattr(args, "limit", 25)
    try:
        ad_groups = client.list_ad_groups(campaign_id=campaign_id, limit=limit)
    except Exception as e:
        error_exit(f"광고그룹 목록 조회 실패: {e}")

    print_json(ad_groups)


def cmd_ad_groups_create(client: GoogleAdsClient, args: argparse.Namespace) -> None:
    """ad-groups create: 광고그룹 생성 (status=PAUSED 고정)"""
    try:
        result = client.create_ad_group(
            campaign_id=args.campaign_id,
            name=args.name,
            cpc_bid=args.cpc_bid,
            status="PAUSED",
        )
    except Exception as e:
        error_exit(f"광고그룹 생성 실패: {e}")

    print_json(result)


# ---------------------------------------------------------------------------
# 파서 구성
# ---------------------------------------------------------------------------


def build_parser() -> argparse.ArgumentParser:
    parser = argparse.ArgumentParser(
        description="Google Ads CLI - Google Ads API 관리 도구",
        formatter_class=argparse.RawDescriptionHelpFormatter,
    )

    subparsers = parser.add_subparsers(dest="command", metavar="COMMAND")

    # ---- status ----
    subparsers.add_parser(
        "status",
        help="계정 정보 확인",
    )

    # ---- campaigns ----
    campaigns_parser = subparsers.add_parser(
        "campaigns",
        help="캠페인 관리",
    )
    campaigns_sub = campaigns_parser.add_subparsers(dest="action", metavar="ACTION")

    # campaigns list
    list_p = campaigns_sub.add_parser("list", help="캠페인 목록 조회")
    list_p.add_argument("--limit", type=int, default=25, help="최대 결과 수 (기본: 25)")

    # campaigns create
    create_p = campaigns_sub.add_parser("create", help="캠페인 생성 (PAUSED 상태)")
    create_p.add_argument("--name", required=True, help="캠페인 이름")
    create_p.add_argument(
        "--budget",
        type=int,
        required=True,
        help="일일 예산 (마이크로 단위, 예: 1000000 = 1원)",
    )

    # campaigns get
    get_p = campaigns_sub.add_parser("get", help="단일 캠페인 조회")
    get_p.add_argument("--id", required=True, help="캠페인 ID")

    # campaigns delete
    delete_p = campaigns_sub.add_parser("delete", help="캠페인 삭제 (REMOVED)")
    delete_p.add_argument("--id", required=True, help="캠페인 ID")

    # ---- insights ----
    insights_parser = subparsers.add_parser(
        "insights",
        help="광고 성과 리포트 조회",
    )
    insights_parser.add_argument(
        "--entity-id",
        dest="entity_id",
        required=True,
        help="조회할 캠페인/광고그룹/키워드 ID",
    )
    insights_parser.add_argument(
        "--entity-type",
        dest="entity_type",
        default="campaign",
        choices=["campaign", "ad_group", "keyword"],
        help="엔티티 타입 (기본: campaign)",
    )
    insights_parser.add_argument(
        "--date-range",
        dest="date_range",
        default="LAST_7_DAYS",
        help="날짜 범위 프리셋 (기본: LAST_7_DAYS). LAST_30_DAYS, THIS_MONTH 등 지원.",
    )

    # ---- keywords ----
    keywords_parser = subparsers.add_parser(
        "keywords",
        help="키워드 관리",
    )
    keywords_sub = keywords_parser.add_subparsers(dest="action", metavar="ACTION")

    # keywords list
    kw_list_p = keywords_sub.add_parser("list", help="키워드 목록 조회")
    kw_list_p.add_argument(
        "--ad-group-id",
        dest="ad_group_id",
        required=True,
        help="광고그룹 ID",
    )
    kw_list_p.add_argument("--limit", type=int, default=25, help="최대 결과 수 (기본: 25)")

    # keywords add
    kw_add_p = keywords_sub.add_parser("add", help="키워드 추가")
    kw_add_p.add_argument(
        "--ad-group-id",
        dest="ad_group_id",
        required=True,
        help="광고그룹 ID",
    )
    kw_add_p.add_argument(
        "--keywords",
        required=True,
        help='JSON 배열 문자열. 예: \'[{"text": "보험", "match_type": "BROAD"}]\'',
    )

    # ---- ad-groups ----
    ad_groups_parser = subparsers.add_parser(
        "ad-groups",
        help="광고그룹 관리",
    )
    ad_groups_sub = ad_groups_parser.add_subparsers(dest="action", metavar="ACTION")

    # ad-groups list
    ag_list_p = ad_groups_sub.add_parser("list", help="광고그룹 목록 조회")
    ag_list_p.add_argument(
        "--campaign-id",
        dest="campaign_id",
        default=None,
        help="캠페인 ID (생략 시 계정 전체 광고그룹 반환)",
    )
    ag_list_p.add_argument("--limit", type=int, default=25, help="최대 결과 수 (기본: 25)")

    # ad-groups create
    ag_create_p = ad_groups_sub.add_parser("create", help="광고그룹 생성 (PAUSED 상태)")
    ag_create_p.add_argument(
        "--campaign-id",
        dest="campaign_id",
        required=True,
        help="상위 캠페인 ID",
    )
    ag_create_p.add_argument("--name", required=True, help="광고그룹 이름")
    ag_create_p.add_argument(
        "--cpc-bid",
        dest="cpc_bid",
        type=int,
        required=True,
        help="CPC 입찰가 (마이크로 단위, 예: 1000000 = 1원)",
    )

    return parser


# ---------------------------------------------------------------------------
# 디스패처
# ---------------------------------------------------------------------------


def dispatch(client: GoogleAdsClient, args: argparse.Namespace) -> None:
    command = args.command

    if command == "status":
        cmd_status(client, args)

    elif command == "campaigns":
        action = getattr(args, "action", None)
        if action == "list":
            cmd_campaigns_list(client, args)
        elif action == "create":
            cmd_campaigns_create(client, args)
        elif action == "get":
            cmd_campaigns_get(client, args)
        elif action == "delete":
            cmd_campaigns_delete(client, args)
        else:
            print(
                "campaigns 서브 명령어를 지정하세요: list | create | get | delete",
                file=sys.stderr,
            )
            sys.exit(1)

    elif command == "insights":
        cmd_insights(client, args)

    elif command == "keywords":
        action = getattr(args, "action", None)
        if action == "list":
            cmd_keywords_list(client, args)
        elif action == "add":
            cmd_keywords_add(client, args)
        else:
            print("keywords 서브 명령어를 지정하세요: list | add", file=sys.stderr)
            sys.exit(1)

    elif command == "ad-groups":
        action = getattr(args, "action", None)
        if action == "list":
            cmd_ad_groups_list(client, args)
        elif action == "create":
            cmd_ad_groups_create(client, args)
        else:
            print("ad-groups 서브 명령어를 지정하세요: list | create", file=sys.stderr)
            sys.exit(1)

    else:
        print("명령어를 지정하세요. --help 로 도움말을 확인하세요.", file=sys.stderr)
        sys.exit(1)


# ---------------------------------------------------------------------------
# 진입점
# ---------------------------------------------------------------------------


def main() -> None:
    parser = build_parser()
    args = parser.parse_args()

    if not args.command:
        parser.print_help()
        sys.exit(0)

    try:
        client = GoogleAdsClient()
    except Exception as e:
        msg = str(e)
        print(f"Error: GoogleAdsClient 초기화 실패 - {msg}", file=sys.stderr)
        sys.exit(1)

    dispatch(client, args)


if __name__ == "__main__":
    main()
