"""
カレンダー JPEG ジェネレーター
================================
出力: YYYY_MM.jpg  (1月1ファイル)
サイズ: 400×300px (4:3)、白背景、罫線なし

色仕様:
  日曜・祝日 → 赤  #FF0000
  土曜       → 金  #FFD700
  平日       → 黒  #000000
  背景       → 白  #FFFFFF

列順: 日・月・火・水・木・金・土

必要ライブラリ (pip でインストール):
  pip install reportlab pdf2image Pillow
  ※ pdf2image は poppler-utils も必要
    - Ubuntu/Debian: sudo apt install poppler-utils
    - macOS:         brew install poppler
    - Windows:       https://github.com/oschwartz10612/poppler-windows
"""

import calendar
import os
from io import BytesIO

from reportlab.pdfgen import canvas as rl_canvas
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
from reportlab.lib.colors import HexColor
from pdf2image import convert_from_bytes

# ===========================================================
# ★ フォントパスを環境に合わせて変更してください
#   Windows 例: "C:/Windows/Fonts/msgothic.ttc"
#   macOS   例: "/System/Library/Fonts/ヒラギノ角ゴシック W3.ttc"
#   Linux   例: "/usr/share/fonts/opentype/ipafont-gothic/ipag.ttf"
# ===========================================================
FONT_PATH = "/usr/share/fonts/opentype/ipafont-gothic/ipag.ttf"

# ===========================================================
# 出力設定
# ===========================================================
OUTPUT_DIR  = "./output"   # 保存先フォルダ
JPEG_DPI    = 150          # DPI (大きいほど高画質・ファイルサイズ増)
JPEG_QUALITY = 95          # JPEG品質 (1〜95)
PAGE_W_PT   = 400          # ページ幅  (pt ≒ px)
PAGE_H_PT   = 300          # ページ高さ (pt ≒ px)
MARGIN_PT   = 14           # 余白

# ===========================================================
# 色
# ===========================================================
COLOR_BG   = HexColor("#FFFFFF")
COLOR_TEXT = HexColor("#000000")
COLOR_RED  = HexColor("#FF0000")
COLOR_GOLD = HexColor("#FFD700")

# ===========================================================
# 祝日 (2026年)  ── 必要に応じて追加・修正してください
# ===========================================================
JP_HOLIDAYS = {
    (2026,  1,  1), (2026,  1, 12),
    (2026,  2, 11), (2026,  2, 23),
    (2026,  3, 20),
    (2026,  4, 29),
    (2026,  5,  3), (2026,  5,  4), (2026,  5,  5), (2026,  5,  6),
    (2026,  7, 20),
    (2026,  8, 11),
    (2026,  9, 21), (2026,  9, 23),
    (2026, 10, 12),
    (2026, 11,  3), (2026, 11, 23),
}

MONTH_NAMES_JP = {
    1:"1月",  2:"2月",  3:"3月",  4:"4月",
    5:"5月",  6:"6月",  7:"7月",  8:"8月",
    9:"9月", 10:"10月", 11:"11月", 12:"12月",
}

DOW_NAMES = ["日", "月", "火", "水", "木", "金", "土"]


# -----------------------------------------------------------
# 内部ユーティリティ
# -----------------------------------------------------------

def _day_color(year, month, day, col_idx):
    """col_idx: 0=日曜 … 6=土曜"""
    if (year, month, day) in JP_HOLIDAYS or col_idx == 0:
        return COLOR_RED
    if col_idx == 6:
        return COLOR_GOLD
    return COLOR_TEXT


def _sun_first_weeks(year, month):
    """日曜始まりの週リストを返す (空き=0)"""
    return calendar.Calendar(firstweekday=6).monthdayscalendar(year, month)


def _draw_month(c, year, month, x0, y0, w, h):
    """ReportLab canvas に1か月分を描画する"""
    header_h = h * 0.15
    dow_h    = h * 0.11
    body_h   = h - header_h - dow_h
    col_w    = w / 7.0

    weeks  = _sun_first_weeks(year, month)
    row_h  = body_h / len(weeks)

    # ---- タイトル ----
    c.setFont("CalFont", header_h * 0.52)
    c.setFillColor(COLOR_TEXT)
    c.drawCentredString(
        x0 + w / 2,
        y0 + h - header_h * 0.68,
        f"{year}年　{MONTH_NAMES_JP[month]}"
    )

    # ---- 曜日行 ----
    dow_top = y0 + h - header_h
    c.setFont("CalFont", dow_h * 0.52)
    for col, name in enumerate(DOW_NAMES):
        cx = x0 + col_w * col + col_w / 2
        cy = dow_top - dow_h * 0.75
        c.setFillColor(COLOR_RED if col == 0 else COLOR_GOLD if col == 6 else COLOR_TEXT)
        c.drawCentredString(cx, cy, name)

    # ---- 日付グリッド ----
    grid_top = dow_top - dow_h
    c.setFont("CalFont", row_h * 0.50)
    for row_idx, week in enumerate(weeks):
        for col_idx, day in enumerate(week):
            if day == 0:
                continue
            cx = x0 + col_w * col_idx + col_w / 2
            cy = grid_top - row_h * row_idx - row_h * 0.65
            c.setFillColor(_day_color(year, month, day, col_idx))
            c.drawCentredString(cx, cy, str(day))


def _render_pdf_bytes(year, month):
    """1か月分の PDF をメモリ上に生成して bytes で返す"""
    buf = BytesIO()
    c = rl_canvas.Canvas(buf, pagesize=(PAGE_W_PT, PAGE_H_PT))
    c.setFillColor(COLOR_BG)
    c.rect(0, 0, PAGE_W_PT, PAGE_H_PT, fill=1, stroke=0)
    _draw_month(c, year, month,
                MARGIN_PT, MARGIN_PT,
                PAGE_W_PT - MARGIN_PT * 2,
                PAGE_H_PT - MARGIN_PT * 2)
    c.save()
    return buf.getvalue()


# -----------------------------------------------------------
# 公開 API
# -----------------------------------------------------------

def generate_calendar_jpeg(months, output_dir=OUTPUT_DIR,
                            dpi=JPEG_DPI, quality=JPEG_QUALITY):
    """
    指定した月のカレンダー JPEG を生成する。

    Parameters
    ----------
    months : list of (int, int)
        [(year, month), ...]  例: [(2026, 5), (2026, 6)]
    output_dir : str
        保存先ディレクトリ (存在しなければ自動作成)
    dpi : int
        出力解像度
    quality : int
        JPEG 品質 (1〜95)

    Returns
    -------
    list of str
        生成したファイルパスの一覧
    """
    # フォント登録 (重複登録はスキップ)
    if "CalFont" not in pdfmetrics.getRegisteredFontNames():
        pdfmetrics.registerFont(TTFont("CalFont", FONT_PATH))

    os.makedirs(output_dir, exist_ok=True)
    saved = []

    for year, month in months:
        pdf_bytes = _render_pdf_bytes(year, month)
        images = convert_from_bytes(pdf_bytes, dpi=dpi)
        img = images[0].convert("RGB")

        filename = f"{year}_{month:02d}.jpg"
        filepath = os.path.join(output_dir, filename)
        img.save(filepath, "JPEG", quality=quality)
        print(f"  保存: {filepath}  ({img.width}×{img.height}px)")
        saved.append(filepath)

    print(f"✅ {len(saved)}枚 生成完了")
    return saved


# -----------------------------------------------------------
# エントリポイント
# -----------------------------------------------------------

if __name__ == "__main__":
    # ↓ 出力したい月をここに追加するだけ
    months_to_generate = [
        (2026, 5),
        (2026, 6),
        # (2026, 7),
        # (2026, 8),
    ]

    generate_calendar_jpeg(months_to_generate)
