"""
OTC 용법 라벨 출력 모듈
Brother QL-810W 프린터용 가로형 와이드 라벨 생성 및 출력

기반: person-lookup-web-local/print_label.py
"""

from PIL import Image, ImageDraw, ImageFont
import logging
import re
from pathlib import Path

# 프린터 설정 (QL-810W)
PRINTER_IP = "192.168.0.168"  # QR 라벨과 동일한 Brother QL-810W
PRINTER_MODEL = "QL-810W"
LABEL_TYPE = "29"  # 29mm 연속 출력 용지

# 폰트 경로 (Windows/Linux 크로스 플랫폼)
FONT_PATHS = [
    "C:/Windows/Fonts/malgunbd.ttf",  # Windows
    "/srv/person-lookup-web-local/pop_maker/fonts/malgunbd.ttf",  # Linux
    "/usr/share/fonts/truetype/nanum/NanumGothicBold.ttf",  # Linux 대체
]

def get_font_path():
    """사용 가능한 폰트 경로 반환"""
    for path in FONT_PATHS:
        if Path(path).exists():
            return path
    return None


def create_otc_label_image(drug_name, effect="", dosage_instruction="", usage_tip=""):
    """
    OTC 용법 라벨 이미지 생성 (800 x 306px)

    레이아웃:
    - 효능: 중앙 상단에 크게 강조 (72pt)
    - 약품명: 오른쪽 중간 (36pt)
    - 용법: 왼쪽 하단 체크박스 (40pt)
    - 약국명: 오른쪽 하단 테두리 박스 (32pt)

    Args:
        drug_name (str): 약품명
        effect (str): 효능
        dosage_instruction (str): 복용 방법
        usage_tip (str): 사용 팁

    Returns:
        PIL.Image: 가로형 와이드 라벨 이미지 (800 x 306px, mode='1')
    """
    try:
        # 1. 캔버스 생성 (가로로 긴 형태)
        width = 800
        height = 306  # Brother QL 29mm 용지 폭

        img = Image.new('1', (width, height), 1)  # 흰색 배경
        draw = ImageDraw.Draw(img)

        # 2. 폰트 로드
        font_path = get_font_path()
        try:
            font_effect = ImageFont.truetype(font_path, 72)       # 효능 (매우 크게!)
            font_drugname = ImageFont.truetype(font_path, 36)     # 약품명 (중간)
            font_dosage = ImageFont.truetype(font_path, 40)       # 용법 (크게)
            font_pharmacy = ImageFont.truetype(font_path, 32)     # 약국명 (크게)
            font_small = ImageFont.truetype(font_path, 26)        # 사용팁
        except (IOError, TypeError):
            font_effect = ImageFont.load_default()
            font_drugname = ImageFont.load_default()
            font_dosage = ImageFont.load_default()
            font_pharmacy = ImageFont.load_default()
            font_small = ImageFont.load_default()
            logging.warning("폰트 로드 실패. 기본 폰트 사용.")

        # 3. 레이아웃
        x_margin = 25

        # 효능 - 중앙 상단에 크게 (매우 강조!)
        if effect:
            effect_bbox = draw.textbbox((0, 0), effect, font=font_effect)
            effect_width = effect_bbox[2] - effect_bbox[0]
            effect_x = (width - effect_width) // 2
            # 굵게 표시 (offset)
            for offset in [(0, 0), (1, 0), (2, 0), (0, 1), (1, 1), (2, 1)]:
                draw.text((effect_x + offset[0], 20 + offset[1]), effect, font=font_effect, fill=0)

        # 약품명 - 오른쪽 중간 여백에 배치
        drugname_bbox = draw.textbbox((0, 0), drug_name, font=font_drugname)
        drugname_width = drugname_bbox[2] - drugname_bbox[0]
        drugname_x = width - drugname_width - 30  # 오른쪽에서 30px 여백
        drugname_y = 195
        draw.text((drugname_x, drugname_y), drug_name, font=font_drugname, fill=0)

        # 용법 - 왼쪽 하단에 크게 표시
        y = 120  # 효능 아래부터 시작

        # 사용팁이 없으면 복용방법을 더 크게
        if not usage_tip:
            try:
                font_dosage_adjusted = ImageFont.truetype(font_path, 50)
            except:
                font_dosage_adjusted = font_dosage
        else:
            font_dosage_adjusted = font_dosage

        if dosage_instruction:
            # 대괄호로 묶인 부분을 별도 줄로 분리
            dosage_text = re.sub(r'\s*(\[.*?\])\s*', r'\n\1\n', dosage_instruction)

            # 여러 줄 처리
            max_chars_per_line = 32
            dosage_lines = []

            text_parts = dosage_text.split('\n')
            for part in text_parts:
                part = part.strip()
                if not part:
                    continue

                if part.startswith('[') and part.endswith(']'):
                    dosage_lines.append(part)
                elif len(part) > max_chars_per_line:
                    words = part.split()
                    current_line = ""
                    for word in words:
                        if len(current_line + word) <= max_chars_per_line:
                            current_line += word + " "
                        else:
                            if current_line:
                                dosage_lines.append(current_line.strip())
                            current_line = word + " "
                    if current_line:
                        dosage_lines.append(current_line.strip())
                else:
                    dosage_lines.append(part)

            # 첫 줄에 체크박스 추가
            if dosage_lines:
                first_line = f"□ {dosage_lines[0]}"
                draw.text((x_margin, y), first_line, font=font_dosage_adjusted, fill=0)

                line_spacing = 60 if not usage_tip else 50
                y += line_spacing

                for line in dosage_lines[1:]:
                    indent = 0 if (line.startswith('[') and line.endswith(']')) else 30
                    draw.text((x_margin + indent, y), line, font=font_dosage_adjusted, fill=0)
                    y += line_spacing + 2

        # 사용팁 (체크박스 + 텍스트)
        if usage_tip and y < height - 60:
            tip_text = f"□ {usage_tip}"
            if len(tip_text) > 55:
                tip_text = tip_text[:52] + "..."
            draw.text((x_margin, y), tip_text, font=font_small, fill=0)

        # 약국명 - 오른쪽 하단에 크게 (테두리 박스)
        sign_text = "청춘약국"
        sign_bbox = draw.textbbox((0, 0), sign_text, font=font_pharmacy)
        sign_width = sign_bbox[2] - sign_bbox[0]
        sign_height = sign_bbox[3] - sign_bbox[1]

        sign_padding_lr = 10
        sign_padding_top = 5
        sign_padding_bottom = 10

        sign_x = width - sign_width - x_margin - 10 - sign_padding_lr
        sign_y = height - 55

        # 테두리 박스 그리기
        box_x1 = sign_x - sign_padding_lr
        box_y1 = sign_y - sign_padding_top
        box_x2 = sign_x + sign_width + sign_padding_lr
        box_y2 = sign_y + sign_height + sign_padding_bottom
        draw.rectangle([box_x1, box_y1, box_x2, box_y2], outline=0, width=2)

        # 약국명 텍스트 (굵게)
        for offset in [(0, 0), (1, 0), (0, 1), (1, 1)]:
            draw.text((sign_x + offset[0], sign_y + offset[1]), sign_text, font=font_pharmacy, fill=0)

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

        logging.info(f"OTC 라벨 이미지 생성 성공: {drug_name}")
        return img

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


def print_otc_label(drug_name, effect="", dosage_instruction="", usage_tip=""):
    """
    OTC 용법 라벨을 Brother QL-810W 프린터로 출력

    Args:
        drug_name (str): 약품명
        effect (str): 효능
        dosage_instruction (str): 복용 방법
        usage_tip (str): 사용 팁

    Returns:
        bool: 성공 여부
    """
    try:
        from brother_ql.raster import BrotherQLRaster
        from brother_ql.conversion import convert
        from brother_ql.backends.helpers import send

        # 1. 라벨 이미지 생성
        label_img = create_otc_label_image(drug_name, effect, dosage_instruction, usage_tip)

        # 2. 이미지 90도 회전 (Brother QL이 세로 방향 기준이므로)
        label_img_rotated = label_img.rotate(90, expand=True)

        logging.info(f"이미지 회전 완료: {label_img_rotated.size}")

        # 3. Brother QL 프린터로 전송
        qlr = BrotherQLRaster(PRINTER_MODEL)
        instructions = convert(
            qlr=qlr,
            images=[label_img_rotated],
            label='29',
            rotate='0',
            threshold=70.0,
            dither=False,
            compress=False,
            red=False,
            dpi_600=False,
            hq=True,
            cut=True
        )
        send(instructions, printer_identifier=f"tcp://{PRINTER_IP}:9100")

        logging.info(f"[SUCCESS] OTC 용법 라벨 인쇄 성공: {drug_name}")
        return True

    except ImportError:
        logging.error("brother_ql 라이브러리가 설치되지 않았습니다.")
        return False
    except Exception as e:
        logging.error(f"[ERROR] OTC 용법 라벨 인쇄 실패: {e}")
        return False


def generate_preview_image(drug_name, effect="", dosage_instruction="", usage_tip=""):
    """
    미리보기용 PNG 이미지 생성 (Base64 인코딩)

    Args:
        drug_name (str): 약품명
        effect (str): 효능
        dosage_instruction (str): 복용 방법
        usage_tip (str): 사용 팁

    Returns:
        str: Base64 인코딩된 PNG 이미지 (data:image/png;base64,... 형태)
    """
    import base64
    from io import BytesIO

    try:
        # 라벨 이미지 생성
        label_img = create_otc_label_image(drug_name, effect, dosage_instruction, usage_tip)

        # RGB로 변환 (1-bit → RGB)
        label_img_rgb = label_img.convert('RGB')

        # PNG로 인코딩
        buffer = BytesIO()
        label_img_rgb.save(buffer, format='PNG')
        buffer.seek(0)

        # Base64 인코딩
        img_base64 = base64.b64encode(buffer.getvalue()).decode('utf-8')

        return f"data:image/png;base64,{img_base64}"

    except Exception as e:
        logging.error(f"미리보기 이미지 생성 실패: {e}")
        return None
