import json
import os
from datetime import datetime

import pandas as pd
import requests
from evidently.metric_preset import DataDriftPreset
from evidently.report import Report

# ==============================================================================
# 데이터 드리프트 감지 및 슬랙 알림 시스템 실습 코드
#
# 본 예제는 Evidently AI를 사용하여 데이터 드리프트를 감지하고,
# 드리프트가 확인되면 Slack을 통해 알림을 보내는 과정을 보여줍니다.
#
# 실행 방법:
# 1. `pip install -r requirements.txt` 로 라이브러리를 설치합니다.
# 2. 아래 `SLACK_WEBHOOK_URL`을 실제 Slack Webhook URL로 변경합니다.
# 3. `python data_drift_detection.py`를 실행합니다.
# ==============================================================================

# --- 설정 ---
# TODO: 본인의 Slack Incoming Webhook URL을 입력하세요.
# Slack Webhook URL 생성 가이드: https://api.slack.com/messaging/webhooks
SLACK_WEBHOOK_URL = os.environ.get(
    "SLACK_WEBHOOK_URL", "https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK_URL"
)


def send_slack_notification(message: str):
    """Slack으로 알림 메시지를 전송합니다."""
    try:
        payload = {"text": message}
        response = requests.post(
            SLACK_WEBHOOK_URL,
            data=json.dumps(payload),
            headers={"Content-Type": "application/json"},
        )
        if response.status_code != 200:
            raise ValueError(f"Slack 알림 실패: {response.status_code} {response.text}")
        print("✅ Slack 알림을 성공적으로 보냈습니다.")
    except Exception as e:
        print(f"❌ Slack 알림 전송 중 에러 발생: {e}")


def check_data_drift():
    """
    Evidently AI를 사용하여 데이터 드리프트를 감지하고,
    결과에 따라 Slack 알림을 트리거합니다.
    """
    print("데이터 드리프트 감지를 시작합니다...")

    # 1. 데이터 준비 (시뮬레이션)
    # 참조 데이터셋 (예: 모델 학습에 사용된 데이터)
    reference_data = pd.DataFrame(
        {
            "feature1": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
            "feature2": [10, 20, 30, 40, 50, 60, 70, 80, 90, 100],
            "target": [0, 0, 0, 0, 1, 1, 1, 1, 1, 1],
        }
    )

    # 현재 데이터셋 (예: 프로덕션에서 수집된 최신 데이터)
    # feature1에서 의도적으로 분포 변화(드리프트) 발생시킴
    current_data = pd.DataFrame(
        {
            "feature1": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14],  # 드리프트 발생
            "feature2": [12, 22, 31, 42, 53, 61, 72, 81, 93, 101],
            "target": [0, 0, 1, 0, 1, 1, 1, 0, 1, 1],
        }
    )
    print("참조 데이터와 현재 데이터를 준비했습니다.")

    # 2. Evidently AI 리포트 생성
    data_drift_report = Report(metrics=[DataDriftPreset()])
    data_drift_report.run(reference_data=reference_data, current_data=current_data)

    # 3. 드리프트 결과 분석
    report_dict = data_drift_report.as_dict()
    is_drift_detected = report_dict["metrics"][0]["result"]["dataset_drift"]
    number_of_drifted_features = report_dict["metrics"][0]["result"][
        "number_of_drifted_columns"
    ]

    print(f"📊 드리프트 감지 결과: {is_drift_detected}")

    # 4. Slack 알림 전송 (드리프트가 감지된 경우)
    if is_drift_detected:
        timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        message = (
            f"🚨 *데이터 드리프트 경고* 🚨\n\n"
            f"- *시간*: {timestamp}\n"
            f"- *상태*: 데이터 드리프트 감지됨\n"
            f"- *드리프트된 피처 수*: {number_of_drifted_features}개\n\n"
            "상세 분석을 위해 MLOps 대시보드를 확인해주세요."
        )
        send_slack_notification(message)
    else:
        print("✅ 데이터 드리프트가 감지되지 않았습니다. 시스템이 안정적입니다.")


if __name__ == "__main__":
    if "YOUR/SLACK/WEBHOOK_URL" in SLACK_WEBHOOK_URL:
        print(
            "⚠️ 경고: SLACK_WEBHOOK_URL이 설정되지 않았습니다. Slack 알림은 전송되지 않습니다."
        )
        print("스크립트 상단의 URL을 실제 Slack Webhook URL로 변경해주세요.")

    check_data_drift()
