#!/usr/bin/env python
"""
DS_L10N - 던전 스토커즈 현지화 통합 툴
Unified localization workflow tool for DungeonStalkers

Usage:
    python ds_l10n.py extract [--gui]     # 미번역 항목 추출
    python ds_l10n.py validate [input]    # 번역 검증
    python ds_l10n.py update [input]      # PO 파일 업데이트
    python ds_l10n.py merge               # CSV 병합
    python ds_l10n.py cleanup             # 파일 정리
"""
import sys
import argparse
from pathlib import Path
from datetime import datetime

# 라이브러리 임포트
from lib.config_loader import load_config
from lib.logger import init_logger, Icons
from lib.validator import TranslationValidator
from lib.po_handler import POHandler
from lib.file_manager import FileManager


def get_timestamp() -> str:
    """타임스탬프 생성"""
    return datetime.now().strftime('%Y%m%d_%H%M%S')


def command_extract(args, config, logger):
    """미번역 항목 추출"""
    logger.section('미번역 항목 추출', Icons.SEARCH)

    # GUI 모드
    if args.gui:
        logger.info('GUI 모드로 실행합니다...')
        import tkinter as tk
        from tkinter import filedialog

        root = tk.Tk()
        root.withdraw()

        logger.info('PO 파일을 선택하세요...')
        po_path = filedialog.askopenfilename(
            title='미번역 항목을 추출할 PO 파일 선택',
            filetypes=[('PO Files', '*.po'), ('All files', '*.*')]
        )

        if not po_path:
            logger.warning('파일을 선택하지 않았습니다.')
            return False

        po_path = Path(po_path)

    else:
        # CLI 모드: config에서 경로 가져오기
        unreal_loc = config.get_path('paths.unreal_localization')
        source_lang = config.get('languages.source', 'ko')
        po_path = unreal_loc / source_lang / config.get('files.po_filename', 'LocalExport.po')

        if not po_path.exists():
            logger.error(f'PO 파일을 찾을 수 없습니다: {po_path}')
            return False

    # 출력 파일 경로
    output_dir = config.get_path('paths.output_dir')
    output_dir.mkdir(parents=True, exist_ok=True)

    timestamp = get_timestamp()
    pattern = config.get('files.untranslated_pattern', 'untranslated_{timestamp}.tsv')
    output_filename = pattern.format(timestamp=timestamp)
    output_path = output_dir / output_filename

    # 추출 실행
    po_handler = POHandler(config.data, logger)
    count = po_handler.extract_untranslated(po_path, output_path)

    if count > 0:
        logger.success(f'\n✅ 미번역 항목 {count}건 추출 완료')
        logger.info(f'📄 출력 파일: {output_path}')
    else:
        logger.success(f'\n✅ 모든 텍스트가 번역되어 있습니다!')
        logger.info('미번역 항목이 없습니다. 번역 작업이 완료된 상태입니다.')

    return True


def command_validate(args, config, logger):
    """번역 검증"""
    logger.section('번역 검증', Icons.SEARCH)

    # 입력 파일 결정
    if args.input:
        input_path = Path(args.input)
    else:
        # config에서 기본 입력 파일 가져오기
        base_dir = config.base_dir
        input_filename = config.get('files.translation_input', '번역업데이트.tsv')
        input_path = base_dir / input_filename

    if not input_path.exists():
        logger.error(f'입력 파일을 찾을 수 없습니다: {input_path}')
        return False

    logger.info(f'입력 파일: {input_path}')

    # TSV 파일 읽기
    import csv

    entries = []
    try:
        with open(input_path, 'r', encoding='utf-8-sig') as f:
            reader = csv.DictReader(f, delimiter='\t')

            # 제외할 컬럼
            exclude_columns = {'msgctxt', 'SourceLocation', 'msgid'}
            lang_codes = [col for col in reader.fieldnames if col not in exclude_columns]

            # 원본 언어 (ko가 source language)
            source_lang = config.get('languages.source', 'ko')

            for row in reader:
                msgctxt = row.get('msgctxt', '')

                # msgid 컬럼이 있으면 사용, 없으면 source language(ko) 사용
                msgid = row.get('msgid', '') or row.get(source_lang, '')

                for lang in lang_codes:
                    # source language는 원본이므로 검증 스킵
                    if lang == source_lang:
                        continue

                    msgstr = row.get(lang, '')
                    if msgstr:  # 번역문이 있는 경우만 검증
                        entries.append({
                            'msgctxt': msgctxt,
                            'msgid': msgid,
                            'msgstr': msgstr,
                            'lang': lang
                        })

    except Exception as e:
        logger.error(f'파일 읽기 실패: {e}')
        return False

    if not entries:
        logger.warning('검증할 번역 항목이 없습니다.')
        return False

    logger.info(f'총 {len(entries)}개 번역 항목 검증 중...')

    # 검증 실행
    validator = TranslationValidator(config.data)
    issues, stats = validator.validate_batch(entries)

    # 결과 출력
    validator.print_validation_report(issues, stats, logger)

    # 검증 실패 시 오류 코드 반환
    if stats['errors'] > 0:
        if config.get('validation.stop_on_validation_error', False):
            logger.error('\n검증 실패로 인해 작업을 중단합니다.')
            return False

    return True


def command_update(args, config, logger):
    """PO 파일 업데이트"""
    logger.section('PO 파일 업데이트', Icons.GEAR)

    # 입력 파일 결정
    if args.input:
        input_path = Path(args.input)
    else:
        base_dir = config.base_dir
        input_filename = config.get('files.translation_input', '번역업데이트.tsv')
        input_path = base_dir / input_filename

    if not input_path.exists():
        logger.error(f'입력 파일을 찾을 수 없습니다: {input_path}')
        return False

    logger.info(f'입력 파일: {input_path}')

    # 언리얼 현지화 폴더
    unreal_loc = config.get_path('paths.unreal_localization')
    if not unreal_loc.exists():
        logger.error(f'언리얼 현지화 폴더를 찾을 수 없습니다: {unreal_loc}')
        return False

    logger.info(f'언리얼 현지화 폴더: {unreal_loc}')

    # 설정
    backup = config.get('backup.auto_backup_before_update', True)
    dry_run = args.dry_run if hasattr(args, 'dry_run') else False

    if dry_run:
        logger.warning('⚠️  DRY-RUN 모드: 실제 파일 수정 없이 시뮬레이션만 수행합니다.')

    # 업데이트 실행
    po_handler = POHandler(config.data, logger)
    results = po_handler.update_from_tsv(input_path, unreal_loc, backup, dry_run)

    if not results:
        logger.error('업데이트 실패')
        return False

    # 전체 통계
    total_updated = sum(r.updated for r in results.values())
    total_failed = sum(r.failed for r in results.values())
    total_skipped = sum(r.skipped for r in results.values())

    logger.separator()
    logger.section('📊 전체 업데이트 결과')
    logger.stats(
        **{
            '업데이트됨': total_updated,
            '스킵됨': total_skipped,
            '실패': total_failed,
            '처리 언어': len(results)
        }
    )

    if total_failed > 0:
        logger.warning(f'\n⚠️  {total_failed}건의 업데이트 실패가 발생했습니다.')
        return False

    logger.success(f'\n✅ PO 파일 업데이트 완료!')
    return True


def command_merge(args, config, logger):
    """CSV 병합"""
    logger.section('PO 파일 → CSV 병합', Icons.FILE)

    # 언리얼 현지화 폴더
    unreal_loc = config.get_path('paths.unreal_localization')
    if not unreal_loc.exists():
        logger.error(f'언리얼 현지화 폴더를 찾을 수 없습니다: {unreal_loc}')
        return False

    logger.info(f'언리얼 현지화 폴더: {unreal_loc}')

    # 출력 파일 경로
    output_dir = unreal_loc  # LocalExport 폴더에 저장
    timestamp = get_timestamp()
    pattern = config.get('files.merged_pattern', 'merged_po_entries_{timestamp}.csv')
    output_filename = pattern.format(timestamp=timestamp)
    output_path = output_dir / output_filename

    # 병합 실행
    po_handler = POHandler(config.data, logger)
    count = po_handler.merge_to_csv(unreal_loc, output_path)

    if count > 0:
        logger.success(f'\n✅ CSV 병합 완료: {count}개 항목')
        logger.info(f'📄 출력 파일: {output_path}')
        return True
    else:
        logger.error('병합 실패')
        return False


def command_cleanup(args, config, logger):
    """파일 정리"""
    logger.section('파일 정리', Icons.CLEAN)

    file_manager = FileManager(config.data, logger)

    # 출력 폴더 정리
    output_dir = config.get_path('paths.output_dir')
    if output_dir.exists():
        archived, _ = file_manager.cleanup_old_files(output_dir)

    # 언리얼 현지화 폴더의 CSV 파일 정리
    unreal_loc = config.get_path('paths.unreal_localization')
    if unreal_loc.exists():
        archived2, _ = file_manager.cleanup_old_files(unreal_loc)

    # 백업 파일 정리
    if unreal_loc.exists():
        deleted_backups = file_manager.delete_old_backups(unreal_loc)

    logger.success('\n✅ 파일 정리 완료')
    return True


def main():
    """메인 함수"""
    parser = argparse.ArgumentParser(
        description='DS_L10N - 던전 스토커즈 현지화 통합 툴',
        formatter_class=argparse.RawDescriptionHelpFormatter
    )

    parser.add_argument('--config', type=str, help='설정 파일 경로 (기본: config.yaml)')

    subparsers = parser.add_subparsers(dest='command', help='명령어')

    # extract 명령어
    parser_extract = subparsers.add_parser('extract', help='미번역 항목 추출')
    parser_extract.add_argument('--gui', action='store_true', help='GUI 모드로 실행')

    # validate 명령어
    parser_validate = subparsers.add_parser('validate', help='번역 검증')
    parser_validate.add_argument('input', nargs='?', help='입력 TSV 파일 (기본: 번역업데이트.tsv)')

    # update 명령어
    parser_update = subparsers.add_parser('update', help='PO 파일 업데이트')
    parser_update.add_argument('input', nargs='?', help='입력 TSV 파일 (기본: 번역업데이트.tsv)')
    parser_update.add_argument('--dry-run', action='store_true', help='시뮬레이션 모드 (실제 수정 안함)')

    # merge 명령어
    parser_merge = subparsers.add_parser('merge', help='PO 파일을 CSV로 병합')

    # cleanup 명령어
    parser_cleanup = subparsers.add_parser('cleanup', help='오래된 파일 정리')

    args = parser.parse_args()

    # 명령어가 없으면 도움말 출력
    if not args.command:
        parser.print_help()
        return 0

    try:
        # 설정 로드
        config_path = Path(args.config) if args.config else None
        config = load_config(config_path)

        # 로거 초기화
        logs_dir = config.get_path('paths.logs_dir')
        logs_dir.mkdir(parents=True, exist_ok=True)

        timestamp = get_timestamp()
        log_pattern = config.get('files.log_pattern', 'workflow_{timestamp}.log')
        log_filename = log_pattern.format(timestamp=timestamp)
        log_file = logs_dir / log_filename

        logger = init_logger(config.data, log_file)

        logger.section(f'DS_L10N - {args.command.upper()}', Icons.ROCKET)
        logger.info(f'시작 시간: {datetime.now().strftime("%Y-%m-%d %H:%M:%S")}')
        logger.info(f'설정 파일: {config.config_path}')
        logger.info(f'로그 파일: {log_file}')
        logger.separator()

        # 필요한 디렉토리 생성
        file_manager = FileManager(config.data, logger)
        file_manager.ensure_directories()

        # 명령어 실행
        commands = {
            'extract': command_extract,
            'validate': command_validate,
            'update': command_update,
            'merge': command_merge,
            'cleanup': command_cleanup,
        }

        command_func = commands.get(args.command)
        if command_func:
            success = command_func(args, config, logger)

            logger.separator()
            logger.info(f'종료 시간: {datetime.now().strftime("%Y-%m-%d %H:%M:%S")}')

            if success:
                logger.success(f'\n✅ {args.command} 작업 완료!')
                return 0
            else:
                logger.error(f'\n❌ {args.command} 작업 실패')
                return 1
        else:
            logger.error(f'알 수 없는 명령어: {args.command}')
            return 1

    except KeyboardInterrupt:
        print('\n\n사용자에 의해 중단되었습니다.')
        return 130

    except Exception as e:
        print(f'\n오류 발생: {e}')
        import traceback
        traceback.print_exc()
        return 1


if __name__ == '__main__':
    sys.exit(main())
