"""
QR 영수증 라벨 인쇄 모듈
Brother QL-810W 프린터용 29mm 가로형 라벨
"""

from PIL import Image, ImageDraw, ImageFont
from brother_ql.raster import BrotherQLRaster
from brother_ql.conversion import convert
from brother_ql.backends.helpers import send
import qrcode
import os
from datetime import datetime
import logging

# 프린터 설정 (barcode_print.py와 동일)
PRINTER_IP = "192.168.0.168"
PRINTER_PORT = 9100
PRINTER_MODEL = "QL-810W"
LABEL_TYPE = "29"

# 로깅 설정
logging.basicConfig(level=logging.INFO, format='[QR_LABEL] %(levelname)s: %(message)s')


def get_font_path():
    """
    폰트 파일 경로 자동 감지 (폴백 지원)

    Returns:
        str: 폰트 파일 경로 또는 None (기본 폰트 사용)
    """
    candidates = [
        os.path.join(os.path.dirname(__file__), "..", "samples", "fonts", "malgunbd.ttf"),
        "C:\\Windows\\Fonts\\malgunbd.ttf",  # Windows 기본 경로
        "C:\\Windows\\Fonts\\malgun.ttf",   # 볼드 아닌 버전
        "/usr/share/fonts/truetype/malgun.ttf",  # Linux
        "malgun.ttf",  # 시스템 폰트
    ]

    for path in candidates:
        if os.path.exists(path):
            logging.info(f"폰트 파일 사용: {path}")
            return path

    logging.warning("폰트 파일을 찾을 수 없습니다. 기본 폰트 사용.")
    return None


def create_qr_receipt_label(qr_url, transaction_id, total_amount, claimable_points,
                            transaction_time):
    """
    QR 영수증 라벨 이미지 생성

    Args:
        qr_url (str): QR 코드 URL (token_raw 포함)
        transaction_id (str): 거래 번호
        total_amount (float): 총 판매 금액
        claimable_points (int): 적립 가능 포인트
        transaction_time (datetime): 거래 시간

    Returns:
        PIL.Image: 생성된 라벨 이미지 (800x306px, mode='1')

    레이아웃 (가로형):
    ┌────────────────────────────────────────────────────────────┐
    │                                                            │
    │  [청춘약국]                            [QR CODE]           │
    │  2025-10-24 14:30                      120x120px           │
    │  거래: 20251024000042                                      │
    │                                                            │
    │  결제금액: 50,000원                                        │
    │  적립예정: 1,500P                                          │
    │                                                            │
    │  QR 촬영하고 포인트 받으세요!                               │
    │                                                            │
    └────────────────────────────────────────────────────────────┘
    """
    try:
        # 1. 캔버스 생성 (가로형)
        width = 800
        height = 306
        img = Image.new('1', (width, height), 1)  # 흰색 배경
        draw = ImageDraw.Draw(img)

        # 2. 폰트 로드
        font_path = get_font_path()

        try:
            if font_path:
                font_title = ImageFont.truetype(font_path, 48)      # 약국명
                font_info = ImageFont.truetype(font_path, 32)       # 거래 정보
                font_amount = ImageFont.truetype(font_path, 40)     # 금액 (크게)
                font_points = ImageFont.truetype(font_path, 36)     # 포인트 (강조)
                font_small = ImageFont.truetype(font_path, 28)      # 안내 문구
                font_tiny = ImageFont.truetype(font_path, 18)       # 개인정보 동의 (작게)
            else:
                raise IOError("폰트 없음")
        except (IOError, OSError):
            logging.warning("TrueType 폰트 로드 실패. 기본 폰트 사용.")
            font_title = ImageFont.load_default()
            font_info = ImageFont.load_default()
            font_amount = ImageFont.load_default()
            font_points = ImageFont.load_default()
            font_small = ImageFont.load_default()
            font_tiny = ImageFont.load_default()

        # 3. QR 코드 생성 (우측 상단) - 크기 및 해상도 개선
        qr = qrcode.QRCode(
            version=1,
            error_correction=qrcode.constants.ERROR_CORRECT_H,  # 최고 레벨 (30% 복원)
            box_size=8,  # 기존 4 -> 8로 증가 (더 선명)
            border=2,    # 테두리 2칸 (인식률 향상)
        )
        qr.add_data(qr_url)
        qr.make(fit=True)
        qr_img = qr.make_image(fill_color="black", back_color="white")

        # QR 코드 크기 및 위치 (기존 120 -> 200으로 증가)
        qr_size = 200  # 크기 대폭 증가
        qr_img = qr_img.resize((qr_size, qr_size), Image.LANCZOS)
        qr_x = width - qr_size - 15  # 우측 여백 15px
        qr_y = 10  # 상단 여백 10px

        # QR 코드 붙이기
        if qr_img.mode != '1':
            qr_img = qr_img.convert('1')
        img.paste(qr_img, (qr_x, qr_y))

        # 4. 좌측 텍스트 영역 (y 위치 추적)
        x_margin = 20
        y = 20

        # 약국명 (굵게)
        pharmacy_text = "청춘약국"
        for offset in [(0, 0), (1, 0), (2, 0), (0, 1), (1, 1), (2, 1)]:
            draw.text((x_margin + offset[0], y + offset[1]), pharmacy_text,
                     font=font_title, fill=0)
        y += 55

        # 거래 시간
        time_text = transaction_time.strftime('%Y-%m-%d %H:%M')
        draw.text((x_margin, y), time_text, font=font_info, fill=0)
        y += 40

        # 거래 번호
        tx_text = f"거래: {transaction_id}"
        draw.text((x_margin, y), tx_text, font=font_info, fill=0)
        y += 50

        # 결제 금액 (강조)
        amount_text = f"결제금액: {int(total_amount):,}원"
        for offset in [(0, 0), (1, 0), (0, 1), (1, 1)]:
            draw.text((x_margin + offset[0], y + offset[1]), amount_text,
                     font=font_amount, fill=0)
        y += 46  # 50 → 46으로 축소

        # 적립 포인트 (굵게)
        points_text = f"적립예정: {claimable_points:,}P"
        for offset in [(0, 0), (1, 0), (0, 1), (1, 1)]:
            draw.text((x_margin + offset[0], y + offset[1]), points_text,
                     font=font_points, fill=0)
        y += 42  # 45 → 42로 축소

        # 안내 문구
        guide_text = "QR 촬영하고 포인트 받으세요!"
        draw.text((x_margin, y), guide_text, font=font_small, fill=0)
        y += 26  # 30 → 26으로 축소

        # 개인정보 동의 안내 (작은 글씨)
        privacy_text = "(QR 스캔 시 개인정보 수집·이용에 동의한 것으로 간주됩니다)"
        draw.text((x_margin, y), privacy_text, font=font_tiny, fill=0)

        # 5. 테두리 (가위선 스타일)
        for i in range(2):
            draw.rectangle([5 + i, 5 + i, width - 5 - i, height - 5 - i], outline=0)

        logging.info(f"QR 라벨 이미지 생성 완료: {transaction_id}")
        return img

    except Exception as e:
        logging.error(f"QR 라벨 이미지 생성 실패: {e}")
        raise


def print_qr_label(qr_url, transaction_id, total_amount, claimable_points,
                   transaction_time, preview_mode=False):
    """
    QR 라벨 출력 또는 미리보기

    Args:
        qr_url (str): QR 코드 URL
        transaction_id (str): 거래 번호
        total_amount (float): 판매 금액
        claimable_points (int): 적립 포인트
        transaction_time (datetime): 거래 시간
        preview_mode (bool): True = 미리보기, False = 인쇄

    Returns:
        preview_mode=True: (성공 여부, 이미지 파일 경로)
        preview_mode=False: 성공 여부 (bool)
    """
    try:
        logging.info(f"QR 라벨 {'미리보기' if preview_mode else '출력'} 시작: {transaction_id}")

        # 1. 라벨 이미지 생성
        label_image = create_qr_receipt_label(
            qr_url, transaction_id, total_amount,
            claimable_points, transaction_time
        )

        # 2. 미리보기 모드
        if preview_mode:
            # temp 디렉터리 생성
            temp_dir = os.path.join(os.path.dirname(__file__), "..", "samples", "temp")
            os.makedirs(temp_dir, exist_ok=True)

            # 파일명 생성
            timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
            filename = f"qr_receipt_{transaction_id}_{timestamp}.png"
            file_path = os.path.join(temp_dir, filename)

            # PNG로 저장
            label_image.save(file_path, "PNG")
            logging.info(f"미리보기 이미지 저장: {file_path}")

            return True, file_path

        # 3. 실제 인쇄 모드
        else:
            # 이미지 90도 회전 (Brother QL은 세로 기준)
            label_image_rotated = label_image.rotate(90, expand=True)

            # Brother QL Raster 변환
            qlr = BrotherQLRaster(PRINTER_MODEL)
            instructions = convert(
                qlr=qlr,
                images=[label_image_rotated],
                label=LABEL_TYPE,
                rotate="0",
                threshold=70.0,
                dither=False,
                compress=False,
                red=False,
                dpi_600=False,
                hq=True,
                cut=True
            )

            # 프린터로 전송
            printer_identifier = f"tcp://{PRINTER_IP}:{PRINTER_PORT}"
            send(instructions, printer_identifier=printer_identifier)

            logging.info(f"QR 라벨 출력 완료: {transaction_id}")
            return True

    except Exception as e:
        logging.error(f"QR 라벨 {'미리보기' if preview_mode else '출력'} 실패: {e}")
        if preview_mode:
            return False, None
        else:
            return False


# 테스트 코드
if __name__ == "__main__":
    # 테스트 데이터
    test_qr_url = "https://pharmacy.example.com/claim?t=20251024000042:abc123:2025-10-24T14:30:00"
    test_tx_id = "20251024000042"
    test_amount = 50000.0
    test_points = 1500
    test_time = datetime.now()

    print("=" * 80)
    print("QR 라벨 생성 테스트")
    print("=" * 80)
    print(f"거래 ID: {test_tx_id}")
    print(f"금액: {test_amount:,}원")
    print(f"적립: {test_points}P")
    print(f"QR URL: {test_qr_url[:60]}...")
    print("=" * 80)

    # 미리보기 테스트
    print("\n미리보기 모드 테스트...")
    success, image_path = print_qr_label(
        test_qr_url, test_tx_id, test_amount, test_points, test_time,
        preview_mode=True
    )

    if success:
        print(f"[OK] 테스트 성공!")
        print(f"이미지 저장: {image_path}")
        print(f"\n다음 명령으로 확인:")
        print(f"  start {image_path}")
    else:
        print("[ERROR] 테스트 실패")
