import os
import json
import logging
from logging.handlers import TimedRotatingFileHandler
import paho.mqtt.client as mqtt
import pymysql

# ==============================================================================
# [하드코딩 설정] 제공해주신 belt_db 구조를 소스에 직접 반영
# ==============================================================================
DB_SETTINGS = {
    'host': '127.0.0.1',
    'port': 3307,
    'user': 'jinsungmes',
    'password': 'qetu1357@#',
    'database': 'belt1',       # 명시해주신 독립 데이터베이스 스키마 지정
    'charset': 'utf8mb4',
    'autocommit': True          # 실시간 즉시 반영
}

TARGET_TABLE = "thickness"     # belt1 데이터베이스 내부의 thickness 테이블

# MQTT 브로커 설정
MQTT_HOST = "localhost"
MQTT_PORT = 1883
TARGET_TOPIC = "factory/+/thickness"  # 이지뷰 터치 패널 구독 토픽


# ==============================================================================
# 로깅(Logging) 시스템 설정 (매일 자정 롤링, 30일 보관)
# ==============================================================================
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
LOG_DIR = os.path.join(BASE_DIR, "logs")
os.makedirs(LOG_DIR, exist_ok=True)

LOG_FILE = os.path.join(LOG_DIR, "mqtt_pipeline.log")
log_formatter = logging.Formatter('%(asctime)s [%(levelname)s] %(message)s', datefmt='%Y-%m-%d %H:%M:%S')

file_handler = TimedRotatingFileHandler(LOG_FILE, when="midnight", interval=1, backupCount=30, encoding="utf-8")
file_handler.setFormatter(log_formatter)

console_handler = logging.StreamHandler()
console_handler.setFormatter(log_formatter)

logger = logging.getLogger("MQTT_Logger")
logger.setLevel(logging.INFO)
logger.addHandler(file_handler)
logger.addHandler(console_handler)


# ==============================================================================
# MQTT 수신 및 MySQL 고정 테이블 적재 콜백 핸들러
# ==============================================================================
def on_message(client, userdata, message):
    connection = None
    try:
        # 토픽 분리 (로그 확인용 호스트네임 추출)
        topic_parts = message.topic.split('/')
        hostname = topic_parts[1] if len(topic_parts) > 1 else "unknown"

        # 이지뷰 터치 전송 JSON 바디 디코딩
        payload_str = message.payload.decode("utf-8")
        data = json.loads(payload_str)
        
        # JSON 데이터 추출
        num = data.get('num')
        master_num = data.get('master_num')
        meter = data.get('meter')
        bon = data.get('bon')
        rope_left = data.get('Rope_left')
        rope_center = data.get('Rope_Center')
        rope_right = data.get('Rope_Right')
        worker_id = data.get('worker_id')

        # MySQL 데이터 연결 및 인서트 실행 (belt1.thickness 저장)
        connection = pymysql.connect(**DB_SETTINGS)
        with connection.cursor() as cursor:
            sql = f"""
                INSERT INTO `{TARGET_TABLE}` (
                    num, master_num, meter, bon, 
                    Rope_left, Rope_Center, Rope_Right, worker_id
                ) VALUES (%s, %s, %s, %s, %s, %s, %s, %s)
            """
            cursor.execute(sql, (
                num, master_num, meter, bon, 
                rope_left, rope_center, rope_right, worker_id
            ))
        
        logger.info(f"[적재완료] 수신호스트: [{hostname}] -> 대상위치: [belt1.{TARGET_TABLE}] | 제품번호: {num}")
        
    except json.JSONDecodeError:
        logger.error(f"JSON 파싱 실패 (포맷 불일치): {message.payload}")
    except pymysql.MySQLError as e:
        logger.error(f"MySQL 에러 (데이터베이스 'belt1' 내부의 'thickness' 테이블 유무 확인 필요): {e}")
    except Exception as e:
        logger.error(f"시스템 예외 발생: {e}")
    finally:
        if connection and connection.open:
            connection.close()


# ==============================================================================
# MQTT 클라이언트 초기화 및 가동
# ==============================================================================
client = mqtt.Client()
client.on_message = on_message

try:
    client.connect(MQTT_HOST, MQTT_PORT, 60)
    logger.info(f"MQTT 브로커 연결 성공 ({MQTT_HOST}:{MQTT_PORT})")
except Exception as e:
    logger.error(f"MQTT 브로커 접속 불가: {e}")
    exit(1)

# 구독 활성화
client.subscribe(TARGET_TOPIC)
logger.info(f"구독 토픽 활성화: {TARGET_TOPIC} -> MySQL 3307 [belt1.thickness] 직접 지정 모드 가동")

client.loop_forever()

