# -*- coding: utf-8 -*-
"""이메일 발송 + 장애 경보. '매일 아침 메일 보장' 담당."""
import sys, os, json, smtplib
from datetime import datetime, date
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.application import MIMEApplication
from email.header import Header
from email.utils import formataddr

sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from db.models import get_config, get_conn, log_stage


def _smtp_send(cfg, to_list, subject, html_body, attach_path=None):
    r = cfg["report"]
    msg = MIMEMultipart()
    msg["From"] = formataddr((str(Header(r["sender_name"], "utf-8")), r["smtp_user"]))
    msg["To"] = ", ".join(to_list)
    msg["Subject"] = Header(subject, "utf-8")
    msg.attach(MIMEText(html_body, "html", "utf-8"))
    if attach_path and os.path.exists(attach_path):
        with open(attach_path, "rb") as f:
            part = MIMEApplication(f.read(), _subtype="pdf")
        part.add_header("Content-Disposition", "attachment",
                        filename=os.path.basename(attach_path))
        msg.attach(part)
    with smtplib.SMTP(r["smtp_host"], r["smtp_port"], timeout=30) as s:
        s.starttls()
        s.login(r["smtp_user"], r["smtp_password"])
        s.sendmail(r["smtp_user"], to_list, msg.as_string())


def send_admin_alert(subject, body):
    """관리자 경보 (크롤러 구조변경 등)"""
    try:
        cfg = get_config()
        _smtp_send(cfg, [cfg["report"]["admin_email"]], subject,
                   f"<pre>{body}</pre>")
    except Exception as e:
        print(f"[alert] 관리자 경보 발송 실패: {e}")


def build_highlight_html(cur, report_date):
    cur.execute("SELECT item_ids FROM report_logs WHERE report_date=%s", (report_date,))
    row = cur.fetchone()
    if not row:
        return "<p>본문 요약 생성 실패. 첨부 PDF를 확인하세요.</p>"
    ids = json.loads(row["item_ids"])[:3]
    if not ids:
        return "<p>대상 물건 없음.</p>"
    fmt = ",".join(["%s"] * len(ids))
    cur.execute(
        f"""SELECT i.address, i.min_bid_price, s.rank_today, r2.roi_pct, ra.risk_level
            FROM auction_items i
            JOIN item_scores s ON s.item_id=i.id
            LEFT JOIN roi_analysis r2 ON r2.item_id=i.id AND r2.scenario='base'
                 AND r2.calc_date=s.score_date
            LEFT JOIN risk_analysis ra ON ra.item_id=i.id
            WHERE i.id IN ({fmt}) AND s.score_date=(SELECT MAX(score_date) FROM item_scores)
            ORDER BY s.rank_today LIMIT 3""", ids)
    rows = cur.fetchall()
    lis = "".join(
        f"<li><b>{r['address']}</b> — 최저가 {r['min_bid_price']:,}원 / "
        f"기준수익률 {r['roi_pct'] or '-'}% / 리스크 {r['risk_level'] or 'N/A'}</li>"
        for r in rows)
    return f"<p>오늘의 TOP 3</p><ul>{lis}</ul><p>전체 10건 상세는 첨부 PDF 참조.</p>"


def run():
    cfg = get_config()
    started = datetime.now()
    today = date.today()
    conn = get_conn()
    try:
        with conn.cursor() as cur:
            cur.execute("SELECT * FROM report_logs WHERE report_date=%s", (today,))
            rep = cur.fetchone()
            recipients = cfg["report"]["recipients"]

            if rep and rep["pdf_path"] and os.path.exists(rep["pdf_path"]):
                subject = f"[경매분석] {today} 경기도 TOP 10 일일 보고서"
                cur.execute("SELECT status FROM pipeline_logs WHERE run_date=%s "
                            "AND stage='report' ORDER BY id DESC LIMIT 1", (today,))
                pr = cur.fetchone()
                if pr and pr["status"] == "partial":
                    subject = f"[경매분석][데이터 지연] {today} 일일 보고서"
                html = build_highlight_html(cur, today)
                _smtp_send(cfg, recipients, subject, html, rep["pdf_path"])
                cur.execute("UPDATE report_logs SET sent_at=NOW(), "
                            "send_status='success' WHERE report_date=%s", (today,))
                log_stage("send", "success", 1, started_at=started)
                print(f"[send] 발송 완료 → {recipients}")
            else:
                # 보고서 생성 실패 → 실패 알림이라도 반드시 발송 (침묵 실패 금지)
                _smtp_send(cfg, recipients,
                           f"[경매분석][생성실패] {today} 보고서 생성 실패",
                           "<p>금일 보고서 생성에 실패했습니다. "
                           "pipeline_logs 확인이 필요합니다.</p>")
                cur.execute(
                    """INSERT INTO report_logs (report_date, send_status, error_msg, sent_at)
                       VALUES (%s,'fallback','pdf missing',NOW())
                       ON DUPLICATE KEY UPDATE send_status='fallback', sent_at=NOW()""",
                    (today,))
                log_stage("send", "partial", 0, "fallback notice sent", started)
                print("[send] 보고서 없음 → 실패 알림 발송")
    except Exception as e:
        log_stage("send", "failed", 0, str(e), started)
        raise
    finally:
        conn.close()


def healthcheck():
    """08:15 실행. 당일 send 성공 로그 없으면 관리자 경보."""
    conn = get_conn()
    try:
        with conn.cursor() as cur:
            cur.execute(
                "SELECT COUNT(*) c FROM pipeline_logs WHERE run_date=%s "
                "AND stage='send' AND status IN ('success','partial')", (date.today(),))
            if cur.fetchone()["c"] == 0:
                send_admin_alert(
                    "🚨 경매분석 시스템 발송 실패",
                    f"{date.today()} 보고서 발송 기록이 없습니다. 서버/파이프라인 점검 필요.")
                print("[healthcheck] 발송 기록 없음 → 경보 발송")
            else:
                print("[healthcheck] 정상")
    finally:
        conn.close()


if __name__ == "__main__":
    run()
