"""15-02 / 15-03: 境界値とコードレビュー。Python標準ライブラリのみ。
これは題名検証だけの練習で、認証や永続保存は実装していません。
"""
import sys


def broken(title):
    """受講者用の意図的なバグ。50文字が拒否される。"""
    if not isinstance(title, str):
        raise TypeError('題名は文字列です')
    title = title.strip()
    if not title or len(title) >= 50:
        raise ValueError('題名は1〜50文字です')
    return title


def solution(title):
    """解答例。ここでの文字数はPython lenのコードポイント数。"""
    if not isinstance(title, str):
        raise TypeError('題名は文字列です')
    title = title.strip()
    if not title or len(title) > 50:
        raise ValueError('題名は1〜50文字です')
    return title


def rejects(function, value, error):
    try:
        function(value)
    except error:
        return True
    return False


def self_test():
    assert rejects(broken, 'あ' * 50, ValueError), '意図的バグの再現'
    assert solution('あ' * 50) == 'あ' * 50
    assert solution('  会議準備  ') == '会議準備'
    assert solution('あ') == 'あ'
    assert rejects(solution, ' ', ValueError)
    assert rejects(solution, '', ValueError)
    assert rejects(solution, 'あ' * 51, ValueError)
    assert rejects(solution, None, TypeError)
    print('PASS: 修正前の境界バグを再現。修正版の8項目を確認。')


if __name__ == '__main__':
    if '--self-test' in sys.argv:
        self_test()
    else:
        for value in [' 会議準備 ', 'あ' * 50, 'あ' * 51, '   ']:
            for name, function in [('broken', broken), ('solution', solution)]:
                try:
                    result = f'受理・整形後{len(function(value))}文字'
                except (TypeError, ValueError) as exc:
                    result = f'拒否: {exc}'
                print(f'{name}: 入力{len(value)}文字 -> {result}')
