"""
허니웰 바코드 리더기 COM3 포트 리딩 프로그램
바코드 스캔 시 터미널에 실시간 출력
"""

import serial
import sys
import io
from datetime import datetime

# Windows cp949 인코딩 문제 해결
if sys.platform == 'win32':
    sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')

def read_barcode_from_com3(port='COM3', baudrate=9600, timeout=1):
    """
    COM3 포트에서 바코드 데이터를 읽어 터미널에 출력

    Args:
        port: COM 포트 번호 (기본값: COM3)
        baudrate: 통신 속도 (기본값: 9600, 허니웰 기본값)
        timeout: 읽기 타임아웃 (초)
    """

    print(f'[시작] 바코드 리더기 연결 중...')
    print(f'포트: {port}')
    print(f'속도: {baudrate} bps')
    print('-' * 60)

    try:
        # 시리얼 포트 열기
        ser = serial.Serial(
            port=port,
            baudrate=baudrate,
            bytesize=serial.EIGHTBITS,
            parity=serial.PARITY_NONE,
            stopbits=serial.STOPBITS_ONE,
            timeout=timeout
        )

        print(f'[성공] {port} 포트 연결 완료!')
        print('[대기] 바코드를 스캔해주세요... (종료: Ctrl+C)')
        print('=' * 60)
        print()

        scan_count = 0

        while True:
            # 시리얼 포트에서 데이터 읽기
            if ser.in_waiting > 0:
                # 바코드 데이터 읽기 (개행문자까지)
                barcode_data = ser.readline()

                # 바이트를 문자열로 디코딩
                try:
                    barcode_str = barcode_data.decode('utf-8').strip()
                except UnicodeDecodeError:
                    # UTF-8 실패 시 ASCII로 시도
                    barcode_str = barcode_data.decode('ascii', errors='ignore').strip()

                if barcode_str:
                    scan_count += 1
                    timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S')

                    print(f'[스캔 #{scan_count}] {timestamp}')
                    print(f'바코드: {barcode_str}')
                    print(f'길이: {len(barcode_str)}자')
                    print(f'원본(HEX): {barcode_data.hex()}')
                    print('-' * 60)

    except serial.SerialException as e:
        print(f'[오류] 포트 연결 실패: {e}')
        print()
        print('가능한 해결 방법:')
        print('  1. COM3 포트가 다른 프로그램에서 사용 중인지 확인')
        print('  2. 바코드 리더기가 제대로 연결되어 있는지 확인')
        print('  3. 장치 관리자에서 포트 번호 확인 (COM3이 맞는지)')
        print('  4. USB 케이블을 다시 연결해보기')
        return 1

    except KeyboardInterrupt:
        print()
        print('=' * 60)
        print(f'[종료] 총 {scan_count}개의 바코드를 스캔했습니다.')
        print('[완료] 프로그램을 종료합니다.')
        ser.close()
        return 0

    except Exception as e:
        print(f'[오류] 예상치 못한 오류 발생: {e}')
        return 1

    finally:
        if 'ser' in locals() and ser.is_open:
            ser.close()
            print('[정리] 포트 연결 종료')


def list_available_ports():
    """사용 가능한 COM 포트 목록 출력"""
    import serial.tools.list_ports

    ports = serial.tools.list_ports.comports()

    if not ports:
        print('[알림] 사용 가능한 COM 포트가 없습니다.')
        return

    print('[사용 가능한 COM 포트]')
    print('-' * 60)
    for port in ports:
        print(f'포트: {port.device}')
        print(f'  설명: {port.description}')
        print(f'  제조사: {port.manufacturer}')
        print()


if __name__ == '__main__':
    import argparse

    parser = argparse.ArgumentParser(
        description='허니웰 바코드 리더기 COM 포트 리딩 프로그램'
    )
    parser.add_argument(
        '--port',
        default='COM3',
        help='COM 포트 번호 (기본값: COM3)'
    )
    parser.add_argument(
        '--baudrate',
        type=int,
        default=9600,
        help='통신 속도 (기본값: 9600)'
    )
    parser.add_argument(
        '--list-ports',
        action='store_true',
        help='사용 가능한 COM 포트 목록 출력'
    )

    args = parser.parse_args()

    if args.list_ports:
        list_available_ports()
    else:
        exit_code = read_barcode_from_com3(
            port=args.port,
            baudrate=args.baudrate
        )
        sys.exit(exit_code)
