# pos_printer.py - ESC/POS 영수증 프린터 유틸리티
# 0bin-label-app/src/pos_settings_dialog.py 기반

import socket
import logging
from datetime import datetime

# 프린터 설정 (config에서 불러올 수도 있음)
POS_PRINTER_IP = "192.168.0.174"
POS_PRINTER_PORT = 9100
POS_PRINTER_NAME = "올댓포스 오른쪽"

# ESC/POS 명령어
ESC = b'\x1b'
GS = b'\x1d'

# 기본 명령
INIT = ESC + b'@'           # 프린터 초기화
CUT = ESC + b'd\x03'        # 피드 + 커트 (원본 방식)
FEED = b'\n\n\n'            # 줄바꿈

# 정렬
ALIGN_LEFT = ESC + b'a\x00'
ALIGN_CENTER = ESC + b'a\x01'
ALIGN_RIGHT = ESC + b'a\x02'

# 폰트 스타일
BOLD_ON = ESC + b'E\x01'
BOLD_OFF = ESC + b'E\x00'
DOUBLE_HEIGHT = ESC + b'!\x10'
DOUBLE_WIDTH = ESC + b'!\x20'
DOUBLE_SIZE = ESC + b'!\x30'  # 가로세로 2배
NORMAL_SIZE = ESC + b'!\x00'

# 로깅
logging.basicConfig(level=logging.INFO)


def print_raw(data: bytes, ip: str = None, port: int = None) -> bool:
    """
    ESC/POS 바이트 데이터를 프린터로 전송
    
    Args:
        data: ESC/POS 명령어 + 텍스트 바이트
        ip: 프린터 IP (기본값: POS_PRINTER_IP)
        port: 프린터 포트 (기본값: POS_PRINTER_PORT)
    
    Returns:
        bool: 성공 여부
    """
    ip = ip or POS_PRINTER_IP
    port = port or POS_PRINTER_PORT
    
    try:
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.settimeout(5)
        sock.connect((ip, port))
        sock.sendall(data)
        sock.close()
        logging.info(f"[POS Printer] 전송 성공: {ip}:{port}")
        return True
    except socket.timeout:
        logging.error(f"[POS Printer] 연결 시간 초과: {ip}:{port}")
        return False
    except ConnectionRefusedError:
        logging.error(f"[POS Printer] 연결 거부됨: {ip}:{port}")
        return False
    except Exception as e:
        logging.error(f"[POS Printer] 전송 실패: {e}")
        return False


def print_text(text: str, cut: bool = True) -> bool:
    """
    텍스트를 영수증 프린터로 출력
    
    Args:
        text: 출력할 텍스트 (한글 지원)
        cut: 출력 후 용지 커트 여부
    
    Returns:
        bool: 성공 여부
    """
    try:
        # EUC-KR 인코딩 (한글 지원)
        text_bytes = text.encode('euc-kr', errors='replace')
        
        # 명령어 조합
        command = INIT + text_bytes + b'\n\n\n'
        if cut:
            command += CUT
        
        return print_raw(command)
    except Exception as e:
        logging.error(f"[POS Printer] 텍스트 인쇄 실패: {e}")
        return False


def print_cusetc(customer_name: str, cusetc: str, phone: str = None) -> bool:
    """
    특이(참고)사항 영수증 출력 (단순 텍스트 방식)
    
    Args:
        customer_name: 고객 이름
        cusetc: 특이사항 내용
        phone: 전화번호 (선택)
    
    Returns:
        bool: 성공 여부
    """
    now = datetime.now().strftime('%Y-%m-%d %H:%M')
    
    # 전화번호 포맷팅
    phone_display = ""
    if phone:
        phone_clean = phone.replace("-", "").replace(" ", "")
        if len(phone_clean) == 11:
            phone_display = f"{phone_clean[:3]}-{phone_clean[3:7]}-{phone_clean[7:]}"
        else:
            phone_display = phone
    
    # 80mm 프린터 = 48자 기준
    LINE = "=" * 48
    THIN = "-" * 48
    
    message = f"""
{LINE}
            [ 특이사항 ]
{LINE}
고객: {customer_name}
"""
    if phone_display:
        message += f"연락처: {phone_display}\n"
    
    message += f"""출력: {now}
{THIN}
{cusetc}
{LINE}
                 청춘약국
"""
    
    return print_text(message, cut=True)


def test_print() -> bool:
    """테스트 인쇄"""
    now = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    
    test_message = f"""
================================
    POS 프린터 테스트
================================

IP: {POS_PRINTER_IP}
Port: {POS_PRINTER_PORT}
Time: {now}

청춘약국 마일리지 시스템
ESC/POS 정상 작동!
================================
"""
    return print_text(test_message, cut=True)


if __name__ == "__main__":
    # 테스트
    print("POS 프린터 테스트 인쇄...")
    result = test_print()
    print(f"결과: {'성공' if result else '실패'}")
