import subprocess
import re
from pathlib import Path
from typing import Optional, List


def get_latest_git_tag(project_dir: Path) -> Optional[str]:
    try:
        result = subprocess.run(
            ['git', 'describe', '--tags', '--abbrev=0'],
            cwd=project_dir,
            capture_output=True,
            text=True,
            check=True
        )
        tag = result.stdout.strip().lstrip('v')
        return tag if tag else None
    except (subprocess.CalledProcessError, FileNotFoundError):
        return None


def get_commits_since_tag(project_dir: Path, tag: str) -> List[str]:
    try:
        result = subprocess.run(
            ['git', 'log', f'{tag}..HEAD', '--pretty=format:%s'],
            cwd=project_dir,
            capture_output=True,
            text=True,
            check=True
        )
        return result.stdout.strip().splitlines()
    except (subprocess.CalledProcessError, FileNotFoundError):
        return []


def infer_next_version(current_version: str, commits: List[str]) -> str:
    """
    根据 conventional commits 推断下一个版本号。
    规则：
        - 如果有 "BREAKING CHANGE" 或提交类型为 "feat!" 等，则 major+1, minor=0, patch=0
        - 否则如果有 "feat" 类型，则 minor+1, patch=0
        - 否则 patch+1
    """
    match = re.match(r'(\d+)\.(\d+)\.(\d+)(?:[-+].*)?$', current_version)
    if not match:
        # 如果版本不符合 semver，则简单增加 patch
        return current_version + '.1' if '.' not in current_version else current_version + '.0.1'
    major, minor, patch = map(int, match.groups())

    breaking = False
    has_feat = False
    for commit in commits:
        if 'BREAKING CHANGE' in commit or commit.startswith('feat!'):
            breaking = True
            break
        if commit.startswith('feat'):
            has_feat = True
    if breaking:
        return f"{major+1}.0.0"
    elif has_feat:
        return f"{major}.{minor+1}.0"
    else:
        return f"{major}.{minor}.{patch+1}"


def prompt_version_update(current_version: str, suggested_version: str) -> Optional[str]:
    print(f"当前版本: {current_version}")
    print(f"建议版本: {suggested_version}")
    resp = input("是否采用建议版本？(Y/n) 或手动输入新版本: ").strip()
    if not resp or resp.lower() == 'y':
        return suggested_version
    if resp.lower() == 'n':
        return None
    return resp