"""
NHN Cloud 알림톡 발송 서비스
마일리지 적립 완료 등 알림톡 발송 + SQLite 로깅
"""

import os
import json
import logging
from datetime import datetime, timezone, timedelta

import requests

logger = logging.getLogger(__name__)

# NHN Cloud 알림톡 설정
APPKEY = os.getenv('NHN_ALIMTALK_APPKEY', 'u0TLUaXXY9bfQFkY')
SECRET_KEY = os.getenv('NHN_ALIMTALK_SECRET', 'naraGEUJfpkRu1fgirKewJtwADqWQ5gY')
SENDER_KEY = os.getenv('NHN_ALIMTALK_SENDER', '341352077bce225195ccc2697fb449f723e70982')

API_BASE = f'https://api-alimtalk.cloud.toast.com/alimtalk/v2.3/appkeys/{APPKEY}'

# KST 타임존
KST = timezone(timedelta(hours=9))


def _log_to_db(template_code, recipient_no, success, result_message,
               template_params=None, user_id=None, trigger_source='unknown',
               transaction_id=None):
    """발송 결과를 SQLite에 저장"""
    try:
        from db.dbsetup import db_manager
        conn = db_manager.get_sqlite_connection()
        cursor = conn.cursor()
        cursor.execute("""
            INSERT INTO alimtalk_logs
                (template_code, recipient_no, user_id, trigger_source,
                 template_params, success, result_message, transaction_id)
            VALUES (?, ?, ?, ?, ?, ?, ?, ?)
        """, (
            template_code,
            recipient_no,
            user_id,
            trigger_source,
            json.dumps(template_params, ensure_ascii=False) if template_params else None,
            success,
            result_message,
            transaction_id
        ))
        conn.commit()
    except Exception as e:
        logger.warning(f"알림톡 로그 DB 저장 실패: {e}")


def _send_alimtalk(template_code, recipient_no, template_params):
    """
    알림톡 발송 공통 함수

    Args:
        template_code: 템플릿 코드
        recipient_no: 수신 번호 (01012345678)
        template_params: 템플릿 변수 딕셔너리

    Returns:
        tuple: (성공 여부, 메시지)
    """
    url = f'{API_BASE}/messages'
    headers = {
        'Content-Type': 'application/json;charset=UTF-8',
        'X-Secret-Key': SECRET_KEY
    }
    data = {
        'senderKey': SENDER_KEY,
        'templateCode': template_code,
        'recipientList': [
            {
                'recipientNo': recipient_no,
                'templateParameter': template_params
            }
        ]
    }

    try:
        resp = requests.post(url, headers=headers, json=data, timeout=10)
        result = resp.json()

        if resp.status_code == 200 and result.get('header', {}).get('isSuccessful'):
            logger.info(f"알림톡 발송 성공: {template_code} → {recipient_no}")
            return (True, "발송 성공")
        else:
            # 상세 에러 추출: sendResults[0].resultMessage 우선, 없으면 header.resultMessage
            header_msg = result.get('header', {}).get('resultMessage', '')
            send_results = result.get('message', {}).get('sendResults', [])
            detail_msg = send_results[0].get('resultMessage', '') if send_results else ''
            
            # 상세 에러가 있으면 그걸 사용, 없으면 header 에러
            error_msg = detail_msg if detail_msg and detail_msg != 'SUCCESS' else header_msg
            if not error_msg:
                error_msg = str(result)
            
            logger.warning(f"알림톡 발송 실패: {template_code} → {recipient_no}: {error_msg}")
            return (False, error_msg)

    except requests.exceptions.Timeout:
        logger.warning(f"알림톡 발송 타임아웃: {template_code} → {recipient_no}")
        return (False, "타임아웃")
    except Exception as e:
        logger.warning(f"알림톡 발송 오류: {template_code} → {recipient_no}: {e}")
        return (False, str(e))


def build_item_summary(items):
    """구매 품목 요약 문자열 생성 (예: '타이레놀 외 3건')
    
    Note: 카카오 알림톡 템플릿 변수는 14자 제한
          (에러: "Blacklist can't use more than 14 characters in template value.")
          특수문자(%, 괄호 등)는 문제없이 발송 가능!
    """
    if not items:
        return "약국 구매"
    first = items[0]['name']
    first = first.strip()
    
    if len(items) == 1:
        # 단일 품목: 14자 제한 (그냥 자름)
        return first[:14]
    
    # 복수 품목: "외 N건" 붙으므로 전체 14자 맞춤
    suffix = f" 외 {len(items) - 1}건"
    max_first = 14 - len(suffix)
    return f"{first[:max_first]}{suffix}"


def send_mileage_claim_alimtalk(phone, name, points, balance, items=None,
                                 user_id=None, trigger_source='kiosk',
                                 transaction_id=None):
    """
    마일리지 적립 완료 알림톡 발송

    Args:
        phone: 수신 전화번호 (01012345678)
        name: 고객명
        points: 적립 포인트
        balance: 적립 후 총 잔액
        items: 구매 품목 리스트 [{'name': ..., 'qty': ..., 'total': ...}, ...]
        user_id: 사용자 ID (로그용)
        trigger_source: 발송 주체 ('kiosk', 'admin', 'manual')
        transaction_id: 거래 ID (로그용)

    Returns:
        tuple: (성공 여부, 메시지)
    """
    now_kst = datetime.now(KST).strftime('%m/%d %H:%M')
    item_summary = build_item_summary(items)

    # MILEAGE_CLAIM_V3 (발송 근거 + 구매품목 포함) 우선 시도
    template_code = 'MILEAGE_CLAIM_V3'
    params = {
        '고객명': name,
        '구매품목': item_summary,
        '적립포인트': f'{points:,}',
        '총잔액': f'{balance:,}',
        '적립일시': now_kst,
        '전화번호': phone
    }

    success, msg = _send_alimtalk(template_code, phone, params)

    # 결과 로그 (V3만 사용, V2 폴백 제거 - V2 반려 상태)
    _log_to_db(template_code, phone, success, msg,
               template_params=params, user_id=user_id,
               trigger_source=trigger_source, transaction_id=transaction_id)

    return (success, msg)


def get_nhn_send_history(start_date, end_date, page=1, page_size=15):
    """
    NHN Cloud API에서 실제 발송 내역 조회

    Args:
        start_date: 시작일 (YYYY-MM-DD HH:mm)
        end_date: 종료일 (YYYY-MM-DD HH:mm)

    Returns:
        list: 발송 메시지 목록
    """
    url = (f'{API_BASE}/messages'
           f'?startRequestDate={start_date}'
           f'&endRequestDate={end_date}'
           f'&pageNum={page}&pageSize={page_size}')
    headers = {
        'Content-Type': 'application/json;charset=UTF-8',
        'X-Secret-Key': SECRET_KEY
    }

    try:
        resp = requests.get(url, headers=headers, timeout=10)
        data = resp.json()
        if data.get('messageSearchResultResponse'):
            return data['messageSearchResultResponse'].get('messages', [])
        return []
    except Exception as e:
        logger.warning(f"NHN 발송내역 조회 실패: {e}")
        return []
