#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
EDM 與節慶促銷路由模組
包含：限時搶購儀表板、節慶活動儀表板
"""

import hashlib
import math
import os
import pickle
from datetime import datetime, timezone, timedelta
from pathlib import Path
from flask import Blueprint, request, render_template, url_for
from auth import login_required
from sqlalchemy import func, desc

from config import BASE_DIR, public_url, DATABASE_TYPE, SYSTEM_VERSION
from database.manager import DatabaseManager
from database.models import Product
from database.edm_models import PromoProduct
from services.logger_manager import SystemLogger
from utils.momo_url_utils import build_momo_product_url, normalize_momo_product_url

# 時區設定
TAIPEI_TZ = timezone(timedelta(hours=8))

# Logger
sys_log = SystemLogger("EDMRoutes").get_logger()

# Blueprint 定義
edm_bp = Blueprint('edm', __name__)

_PROMO_DASHBOARD_CACHE = {}
_PROMO_DASHBOARD_CACHE_MAX = 32
_PROMO_PAGE_SIZE_DEFAULT = 24
_PROMO_PAGE_SIZE_MAX = 200
_PROMO_SHARED_CACHE_FILE = Path(BASE_DIR) / 'data' / 'promo_dashboard_cache.pkl'


# ==========================================
# 輔助函數
# ==========================================

def slugify(text):
    """將文字轉換為 URL 友善格式"""
    if not text:
        return ""
    return str(text).replace(' ', '_').replace(':', '').replace('!', '').replace('?', '').replace('/', '').replace('&', '').replace('(', '').replace(')', '').replace('+', '_').replace('.', '_').replace('%', '').replace("'", "")


def get_color_for_string(s):
    """為字串生成一個穩定且美觀的 HSL 顏色"""
    if not s:
        return "hsl(0, 0%, 85%)"  # 預設灰色
    hash_val = int(hashlib.md5(s.encode('utf-8'), usedforsecurity=False).hexdigest(), 16)
    hue = hash_val % 360
    return f"hsl({hue}, 60%, 88%)"


def load_scheduler_stats():
    """讀取排程統計資料"""
    import os
    import json
    stats_path = os.path.join(BASE_DIR, 'data', 'scheduler_stats.json')
    if os.path.exists(stats_path):
        try:
            with open(stats_path, 'r', encoding='utf-8') as f:
                return json.load(f)
        except (IOError, json.JSONDecodeError):
            return {}
    return {}


def _get_promo_dashboard_fingerprint(session, page_type):
    """取得促銷資料指紋，用於判斷快取是否仍可復用。"""
    max_id, max_crawled_at, row_count = session.query(
        func.max(PromoProduct.id),
        func.max(PromoProduct.crawled_at),
        func.count(PromoProduct.id)
    ).filter(PromoProduct.page_type == page_type).one()
    return (
        max_id or 0,
        max_crawled_at.isoformat() if max_crawled_at else '',
        row_count or 0
    )


def _get_promo_dashboard_cache_key(session, page_type, sort_by, order, requested_slot):
    """建立 dashboard data 快取鍵；日期/小時避免自動時段跨時段後仍命中舊首屏。"""
    now_taipei = datetime.now(TAIPEI_TZ)
    auto_slot_bucket = now_taipei.strftime('%Y-%m-%d-%H') if not requested_slot else ''
    return (
        page_type,
        sort_by,
        order,
        requested_slot or '',
        auto_slot_bucket,
        _get_promo_dashboard_fingerprint(session, page_type)
    )


def _remember_promo_dashboard_data(cache_key, data):
    """保留少量活動 dashboard data，避免常用時段每次重算。"""
    if len(_PROMO_DASHBOARD_CACHE) >= _PROMO_DASHBOARD_CACHE_MAX:
        _PROMO_DASHBOARD_CACHE.pop(next(iter(_PROMO_DASHBOARD_CACHE)))
    _PROMO_DASHBOARD_CACHE[cache_key] = data


def _load_shared_promo_dashboard_cache(cache_key):
    """讀取跨 worker 促銷 dashboard 快取，讓冷 worker 不必重算首屏資料。"""
    try:
        if not os.path.exists(_PROMO_SHARED_CACHE_FILE):
            return None
        with open(_PROMO_SHARED_CACHE_FILE, 'rb') as f:
            payload = pickle.load(f)
        if payload.get('version') != SYSTEM_VERSION:
            return None
        entries = payload.get('entries')
        if not isinstance(entries, dict):
            return None
        return entries.get(cache_key)
    except Exception as exc:
        _discard_shared_promo_dashboard_cache("load_corrupt", exc)
        return None


def _discard_shared_promo_dashboard_cache(reason, exc=None):
    """刪除損毀的跨 worker 快取，避免每個 worker 重複噴 traceback。"""
    try:
        os.remove(_PROMO_SHARED_CACHE_FILE)
        sys_log.info("promo dashboard shared cache discarded | reason=%s | error=%s", reason, exc)
    except FileNotFoundError:
        return
    except OSError:
        sys_log.debug("promo dashboard shared cache discard failed", exc_info=True)


def _write_shared_promo_dashboard_cache(cache_key, data):
    """原子寫入促銷 dashboard 共享快取；失敗不阻斷頁面回應。"""
    cache_file = str(_PROMO_SHARED_CACHE_FILE)
    tmp_file = f"{cache_file}.{os.getpid()}.tmp"
    entries = {}
    try:
        if os.path.exists(_PROMO_SHARED_CACHE_FILE):
            try:
                with open(_PROMO_SHARED_CACHE_FILE, 'rb') as f:
                    payload = pickle.load(f)
                if payload.get('version') == SYSTEM_VERSION and isinstance(payload.get('entries'), dict):
                    entries = payload['entries']
            except Exception as exc:
                _discard_shared_promo_dashboard_cache("write_corrupt", exc)
                entries = {}
        entries[cache_key] = data
        while len(entries) > _PROMO_DASHBOARD_CACHE_MAX:
            entries.pop(next(iter(entries)))

        os.makedirs(os.path.dirname(cache_file), exist_ok=True)
        with open(tmp_file, 'wb') as f:
            pickle.dump({'version': SYSTEM_VERSION, 'entries': entries}, f, protocol=pickle.HIGHEST_PROTOCOL)
        os.replace(tmp_file, cache_file)
    except Exception:
        try:
            if os.path.exists(tmp_file):
                os.remove(tmp_file)
        except OSError:
            pass
        sys_log.debug("promo dashboard shared cache write failed", exc_info=True)


def _get_promo_page_window_args():
    """讀取促銷商品清單分頁參數，限制首屏 HTML 重量。"""
    page = request.args.get('page', 1, type=int) or 1
    per_page = request.args.get('per_page', _PROMO_PAGE_SIZE_DEFAULT, type=int) or _PROMO_PAGE_SIZE_DEFAULT
    return max(1, page), max(20, min(per_page, _PROMO_PAGE_SIZE_MAX))


def _paginate_active_slot(data, page, per_page):
    """只裁切目前顯示時段；其他統計仍保留完整資料。"""
    active_tab = data.get('active_tab')
    grouped_items = dict(data.get('sorted_grouped_items') or {})
    active_items = list(grouped_items.get(active_tab, []))
    total_items = len(active_items)
    total_pages = max(1, math.ceil(total_items / per_page)) if total_items else 1
    page = min(max(1, page), total_pages)
    start_idx = (page - 1) * per_page
    end_idx = min(start_idx + per_page, total_items)
    grouped_items[active_tab] = active_items[start_idx:end_idx]
    return grouped_items, {
        'page': page,
        'per_page': per_page,
        'total_pages': total_pages,
        'total_items': total_items,
        'start_item': start_idx + 1 if total_items else 0,
        'end_item': end_idx,
        'has_prev': page > 1,
        'has_next': page < total_pages,
    }


def _build_promo_dashboard_data(session, page_type, page_name, sort_by, order, requested_slot=None):
    """
    通用的促銷儀表板數據建構函數
    用於 edm 和 festival 兩種頁面類型
    """
    cache_key = _get_promo_dashboard_cache_key(session, page_type, sort_by, order, requested_slot)
    cached_data = _PROMO_DASHBOARD_CACHE.get(cache_key)
    if cached_data is not None:
        return cached_data
    cached_data = _load_shared_promo_dashboard_cache(cache_key)
    if cached_data is not None:
        _remember_promo_dashboard_data(cache_key, cached_data)
        return cached_data

    # 1. 基礎統計
    last_update = session.query(PromoProduct.crawled_at).filter(
        PromoProduct.page_type == page_type
    ).order_by(desc(PromoProduct.crawled_at)).first()
    last_update_str = last_update[0].strftime('%Y-%m-%d %H:%M') if last_update else "尚無資料"

    latest_entry = session.query(PromoProduct).filter(
        PromoProduct.page_type == page_type
    ).order_by(desc(PromoProduct.crawled_at)).first()
    activity_time = getattr(latest_entry, 'activity_time_text', page_name) if latest_entry else page_name

    # 2. 查詢最新批次
    latest_batch = session.query(PromoProduct.batch_id).filter(
        PromoProduct.page_type == page_type
    ).order_by(desc(PromoProduct.crawled_at)).first()
    current_batch_id = latest_batch[0] if latest_batch else None

    # 3. 查詢「全商品的最新狀態快照」
    subq = session.query(
        func.max(PromoProduct.id).label('max_id')
    ).filter(PromoProduct.page_type == page_type).group_by(
        PromoProduct.i_code, PromoProduct.time_slot
    ).subquery()

    latest_records = session.query(PromoProduct).join(
        subq, PromoProduct.id == subq.c.max_id
    ).all()

    # 4. 過濾顯示列表
    items_in_batch = []
    today_start = datetime.now(TAIPEI_TZ).replace(
        hour=0, minute=0, second=0, microsecond=0
    )  # 保持時區資訊 (台北 +8)

    for item in latest_records:
        # 確保 crawled_at 有時區資訊，若無則假設為台北時區
        item_crawled_at = item.crawled_at
        if item_crawled_at.tzinfo is None:
            item_crawled_at = item_crawled_at.replace(tzinfo=TAIPEI_TZ)

        if item.status_change == 'SLOT_END' and item_crawled_at < today_start:
            continue
        if item.status_change == 'DELISTED' and item_crawled_at < today_start:
            continue
        items_in_batch.append(item)

    # 5. 按時段分組
    grouped_items = {}
    for item in items_in_batch:
        if item.time_slot not in grouped_items:
            grouped_items[item.time_slot] = []
        grouped_items[item.time_slot].append(item)

    sorted_grouped_items = dict(sorted(grouped_items.items()))

    # 6. 決定預設顯示的頁籤
    def get_current_time_slot():
        hour = datetime.now(TAIPEI_TZ).hour
        available_slots = sorted([
            int(s.split(':')[0]) for s in sorted_grouped_items.keys() if s and ':' in s
        ]) if sorted_grouped_items else [0, 7, 11, 14, 18, 22]
        current_slot_hour = 0
        for s in available_slots:
            if hour >= s:
                current_slot_hour = s
        return f"{current_slot_hour:02d}:00"

    active_tab = get_current_time_slot()
    if requested_slot in sorted_grouped_items:
        active_tab = requested_slot
    if active_tab not in sorted_grouped_items and sorted_grouped_items:
        active_tab = next(iter(sorted_grouped_items))

    # 7. 僅為首屏目前時段補齊列級資訊；其他時段以連結切換後再載入。
    visible_items = sorted_grouped_items.get(active_tab, [])
    visible_icodes = [item.i_code for item in visible_items]
    product_categories = {}
    days_on_shelf_map = {}
    total_sold_map = {}
    history_map = {}

    if visible_icodes:
        # 從主商品表查詢分類
        main_products = session.query(Product.i_code, Product.category).filter(
            Product.i_code.in_(visible_icodes)
        ).all()
        product_categories = {p.i_code: p.category for p in main_products}

        # 計算上架天數 (兼容 SQLite 和 PostgreSQL)
        if DATABASE_TYPE == 'postgresql':
            # PostgreSQL: 使用 DATE() 函數
            days_on_shelf_q = session.query(
                PromoProduct.i_code,
                func.count(func.distinct(func.date(PromoProduct.crawled_at)))
            ).filter(
                PromoProduct.i_code.in_(visible_icodes),
                PromoProduct.page_type == page_type
            ).group_by(PromoProduct.i_code).all()
        else:
            # SQLite: 使用 strftime
            days_on_shelf_q = session.query(
                PromoProduct.i_code,
                func.count(func.distinct(func.strftime('%Y-%m-%d', PromoProduct.crawled_at)))
            ).filter(
                PromoProduct.i_code.in_(visible_icodes),
                PromoProduct.page_type == page_type
            ).group_by(PromoProduct.i_code).all()
        days_on_shelf_map = {r[0]: r[1] for r in days_on_shelf_q}

        # 只有 edm 頁面需要計算總銷量和庫存歷程
        if page_type == 'edm':
            # 計算總銷量
            first_qty_subq = session.query(
                PromoProduct.i_code,
                func.min(PromoProduct.id).label('min_id')
            ).filter(
                PromoProduct.i_code.in_(visible_icodes),
                PromoProduct.remain_qty.isnot(None),
                PromoProduct.page_type == 'edm'
            ).group_by(PromoProduct.i_code).subquery()

            first_qty_records = session.query(
                PromoProduct.i_code, PromoProduct.remain_qty
            ).join(first_qty_subq, PromoProduct.id == first_qty_subq.c.min_id).all()
            first_qty_map = {r[0]: r[1] for r in first_qty_records}

            for item in visible_items:
                if item.i_code in first_qty_map and item.remain_qty is not None:
                    initial_qty = first_qty_map[item.i_code]
                    current_qty = item.remain_qty
                    if initial_qty > current_qty:
                        total_sold_map[item.i_code] = initial_qty - current_qty

            # 準備銷售歷程資料
            all_history_records = session.query(
                PromoProduct.i_code,
                PromoProduct.time_slot,
                PromoProduct.remain_qty,
                PromoProduct.crawled_at
            ).filter(
                PromoProduct.i_code.in_(visible_icodes),
                PromoProduct.crawled_at >= today_start
            ).order_by(PromoProduct.crawled_at).all()

            for rec in all_history_records:
                key = (rec.i_code, rec.time_slot)
                if key not in history_map:
                    history_map[key] = []
                if rec.remain_qty is not None:
                    if not history_map[key] or (history_map[key] and history_map[key][-1]['qty'] != rec.remain_qty):
                        history_map[key].append({'time': rec.crawled_at.strftime('%H:%M'), 'qty': rec.remain_qty})

    # 8. 附加分類資訊到首屏可見 item
    for item in visible_items:
        item.safe_product_url = normalize_momo_product_url(item.url, item.i_code) or build_momo_product_url(item.i_code)
        item.main_category = product_categories.get(item.i_code)
        if item.main_category:
            item.category_color = get_color_for_string(item.main_category)
        item.days_on_shelf = days_on_shelf_map.get(item.i_code, 1)
        item.total_sold = total_sold_map.get(item.i_code, 0)
        item.qty_history = history_map.get((item.i_code, item.time_slot), [])

    # 9. 排序邏輯：首屏只需要排序目前時段
    reverse = (order == 'desc')
    for time_slot in [active_tab]:
        if time_slot not in sorted_grouped_items:
            continue
        if sort_by == 'name':
            sorted_grouped_items[time_slot].sort(key=lambda x: x.name or '', reverse=reverse)
        elif sort_by == 'remain_qty':
            sorted_grouped_items[time_slot].sort(
                key=lambda x: x.remain_qty if x.remain_qty is not None else -1,
                reverse=reverse
            )
        elif sort_by == 'price':
            sorted_grouped_items[time_slot].sort(
                key=lambda x: x.price if x.price is not None else -1,
                reverse=reverse
            )
        else:  # 預設排序
            sorted_grouped_items[time_slot].sort(key=lambda x: (
                1 if x.main_category else 0,
                2 if x.status_change in ['NEW', 'PRICE_UP', 'PRICE_DOWN'] else (1 if x.status_change == 'DELISTED' else 0),
                x.price if x.price is not None else -1
            ), reverse=True)

    # 10. 時段統計
    slot_stats = {}
    today_change_records = session.query(PromoProduct).filter(
        PromoProduct.crawled_at >= today_start,
        PromoProduct.page_type == page_type
    ).all()

    slots_from_changes = {rec.time_slot for rec in today_change_records}
    slots_from_display = set(sorted_grouped_items.keys())
    all_relevant_slots = sorted(list(slots_from_changes.union(slots_from_display)))

    for slot in all_relevant_slots:
        slot_stats[slot] = {
            'new': 0, 'up': 0, 'down': 0,
            'delisted_last_run': 0, 'on_shelf': 0, 'delisted_total': 0
        }

    for rec in today_change_records:
        if rec.time_slot in slot_stats:
            if rec.status_change == 'NEW':
                slot_stats[rec.time_slot]['new'] += 1
            elif rec.status_change == 'PRICE_UP':
                slot_stats[rec.time_slot]['up'] += 1
            elif rec.status_change == 'PRICE_DOWN':
                slot_stats[rec.time_slot]['down'] += 1
            elif rec.status_change in ['DELISTED', 'SLOT_END']:
                slot_stats[rec.time_slot]['delisted_last_run'] += 1

    for slot, items in sorted_grouped_items.items():
        if slot in slot_stats:
            on_shelf_count = sum(1 for item in items if item.status_change not in ['DELISTED', 'SLOT_END'])
            delisted_total_count = len(items) - on_shelf_count
            slot_stats[slot]['on_shelf'] = on_shelf_count
            slot_stats[slot]['delisted_total'] = delisted_total_count

    data = {
        'sorted_grouped_items': sorted_grouped_items,
        'slot_stats': slot_stats,
        'items_in_batch': items_in_batch,
        'last_update_str': last_update_str,
        'activity_time': activity_time,
        'active_tab': active_tab,
        'current_batch_id': current_batch_id
    }
    _remember_promo_dashboard_data(cache_key, data)
    _write_shared_promo_dashboard_cache(cache_key, data)
    return data


def warm_promo_dashboard_cache(reason='manual'):
    """預熱常用活動看板 shared cache，避免部署後第一個使用者承擔冷 worker。"""
    db = DatabaseManager()
    session = db.get_session()
    page_configs = [
        ('edm', '限時搶購'),
        ('festival', '1.1狂歡購物節'),
        ('mothers_day', '母親節超值限時購'),
        ('valentine_520', '520情人節限定購物'),
        ('labor_day', '勞動節購物優惠'),
    ]
    started = datetime.now(TAIPEI_TZ)
    warmed = 0
    try:
        for page_type, page_name in page_configs:
            data = _build_promo_dashboard_data(session, page_type, page_name, 'default', 'desc', None)
            if data:
                warmed += 1
        elapsed_ms = (datetime.now(TAIPEI_TZ) - started).total_seconds() * 1000
        sys_log.info(
            f"[EDM] [Cache] ✅ 活動看板預熱完成 | reason={reason} | pages={warmed} | 耗時={elapsed_ms:.0f}ms"
        )
        return warmed
    finally:
        session.close()


# ==========================================
# EDM 儀表板路由
# ==========================================

@edm_bp.route('/edm')
@login_required
def edm_dashboard():
    """MOMO 限時搶購 (EDM) 專屬儀表板"""
    db = DatabaseManager()
    session = db.get_session()

    sort_by = request.args.get('sort_by', 'default')
    order = request.args.get('order', 'desc')
    requested_slot = request.args.get('slot')
    page, per_page = _get_promo_page_window_args()

    try:
        data = _build_promo_dashboard_data(session, 'edm', '限時搶購', sort_by, order, requested_slot)
        grouped_items, page_window = _paginate_active_slot(data, page, per_page)

        # 建立儀表板頁籤
        promo_pages = [
            {'url': url_for('edm.edm_dashboard'), 'name': '限時搶購', 'id': 'edm'},
            {'url': url_for('edm.festival_dashboard'), 'name': '1.1狂歡購物節', 'id': 'festival'},
            {'url': url_for('edm.mothers_day_dashboard'), 'name': '母親節', 'id': 'mothers_day'},
            {'url': url_for('edm.valentine_520_dashboard'), 'name': '520情人節', 'id': 'valentine_520'},
            {'url': url_for('edm.labor_day_dashboard'), 'name': '勞動節', 'id': 'labor_day'}
        ]

        scheduler_stats = load_scheduler_stats()
        now_taipei = datetime.now(TAIPEI_TZ)

        template_name = 'edm_dashboard_v2.html'

        return render_template(template_name,
                               promo_pages=promo_pages,
                               current_promo_page='edm',
                               page_title='MOMO 限時搶購',
                               grouped_items=grouped_items,
                               slot_stats=data['slot_stats'],
                               page_window=page_window,
                               total_edm_products=len(data['items_in_batch']),
                               last_update=data['last_update_str'],
                               activity_time=data['activity_time'],
                               active_tab=data['active_tab'],
                               current_batch_id=data['current_batch_id'],
                               public_url=public_url,
                               scheduler_stats=scheduler_stats,
                               current_sort=sort_by,
                               current_order=order,
                               slugify=slugify,
                               datetime_now=now_taipei.strftime('%Y-%m-%d %H:%M:%S'),
                               active_page='edm')
    except Exception as e:
        sys_log.error(f"EDM Dashboard 渲染錯誤: {e}")
        return f"系統錯誤: {e}"
    finally:
        session.close()


@edm_bp.route('/festival')
@login_required
def festival_dashboard():
    """1.1 狂歡購物節專屬儀表板"""
    db = DatabaseManager()
    session = db.get_session()

    PAGE_TYPE = "festival"
    PAGE_NAME = "1.1狂歡購物節"

    sort_by = request.args.get('sort_by', 'default')
    order = request.args.get('order', 'desc')
    requested_slot = request.args.get('slot')
    page, per_page = _get_promo_page_window_args()

    try:
        data = _build_promo_dashboard_data(session, PAGE_TYPE, PAGE_NAME, sort_by, order, requested_slot)
        grouped_items, page_window = _paginate_active_slot(data, page, per_page)

        # 建立儀表板頁籤
        promo_pages = [
            {'url': url_for('edm.edm_dashboard'), 'name': '限時搶購', 'id': 'edm'},
            {'url': url_for('edm.festival_dashboard'), 'name': '1.1狂歡購物節', 'id': 'festival'},
            {'url': url_for('edm.mothers_day_dashboard'), 'name': '母親節', 'id': 'mothers_day'},
            {'url': url_for('edm.valentine_520_dashboard'), 'name': '520情人節', 'id': 'valentine_520'},
            {'url': url_for('edm.labor_day_dashboard'), 'name': '勞動節', 'id': 'labor_day'}
        ]

        scheduler_stats = load_scheduler_stats()

        template_name = 'edm_dashboard_v2.html'

        return render_template(template_name,
                               promo_pages=promo_pages,
                               current_promo_page='festival',
                               page_title=PAGE_NAME,
                               grouped_items=grouped_items,
                               slot_stats=data['slot_stats'],
                               page_window=page_window,
                               total_edm_products=len(data['items_in_batch']),
                               last_update=data['last_update_str'],
                               activity_time=data['activity_time'],
                               active_tab=data['active_tab'],
                               public_url=public_url,
                               scheduler_stats=scheduler_stats,
                               current_sort=sort_by,
                               current_order=order,
                               slugify=slugify,
                               active_page='edm')
    except Exception as e:
        sys_log.error(f"{PAGE_NAME} Dashboard 渲染錯誤: {e}")
        return f"系統錯誤: {e}"
    finally:
        session.close()


@edm_bp.route('/mothers_day')
@login_required
def mothers_day_dashboard():
    """母親節促銷活動專屬儀表板"""
    db = DatabaseManager()
    session = db.get_session()

    PAGE_TYPE = "mothers_day"
    PAGE_NAME = "母親節超值限時購"

    sort_by = request.args.get('sort_by', 'default')
    order = request.args.get('order', 'desc')
    requested_slot = request.args.get('slot')
    page, per_page = _get_promo_page_window_args()

    try:
        data = _build_promo_dashboard_data(session, PAGE_TYPE, PAGE_NAME, sort_by, order, requested_slot)
        grouped_items, page_window = _paginate_active_slot(data, page, per_page)

        # 建立儀表板頁籤
        promo_pages = [
            {'url': url_for('edm.edm_dashboard'), 'name': '限時搶購', 'id': 'edm'},
            {'url': url_for('edm.festival_dashboard'), 'name': '1.1狂歡購物節', 'id': 'festival'},
            {'url': url_for('edm.mothers_day_dashboard'), 'name': '母親節', 'id': 'mothers_day'},
            {'url': url_for('edm.valentine_520_dashboard'), 'name': '520情人節', 'id': 'valentine_520'},
            {'url': url_for('edm.labor_day_dashboard'), 'name': '勞動節', 'id': 'labor_day'}
        ]

        scheduler_stats = load_scheduler_stats()

        template_name = 'edm_dashboard_v2.html'

        return render_template(template_name,
                               promo_pages=promo_pages,
                               current_promo_page='mothers_day',
                               page_title=PAGE_NAME,
                               grouped_items=grouped_items,
                               slot_stats=data['slot_stats'],
                               page_window=page_window,
                               total_edm_products=len(data['items_in_batch']),
                               last_update=data['last_update_str'],
                               activity_time=data['activity_time'],
                               active_tab=data['active_tab'],
                               public_url=public_url,
                               scheduler_stats=scheduler_stats,
                               current_sort=sort_by,
                               current_order=order,
                               slugify=slugify,
                               active_page='edm')
    except Exception as e:
        sys_log.error(f"{PAGE_NAME} Dashboard 渲染錯誤: {e}")
        return f"系統錯誤: {e}"
    finally:
        session.close()


@edm_bp.route('/valentine_520')
@login_required
def valentine_520_dashboard():
    """520情人節促銷活動專屬儀表板"""
    db = DatabaseManager()
    session = db.get_session()

    PAGE_TYPE = "valentine_520"
    PAGE_NAME = "520情人節限定購物"

    sort_by = request.args.get('sort_by', 'default')
    order = request.args.get('order', 'desc')
    requested_slot = request.args.get('slot')
    page, per_page = _get_promo_page_window_args()

    try:
        data = _build_promo_dashboard_data(session, PAGE_TYPE, PAGE_NAME, sort_by, order, requested_slot)
        grouped_items, page_window = _paginate_active_slot(data, page, per_page)

        # 建立儀表板頁籤
        promo_pages = [
            {'url': url_for('edm.edm_dashboard'), 'name': '限時搶購', 'id': 'edm'},
            {'url': url_for('edm.festival_dashboard'), 'name': '1.1狂歡購物節', 'id': 'festival'},
            {'url': url_for('edm.mothers_day_dashboard'), 'name': '母親節', 'id': 'mothers_day'},
            {'url': url_for('edm.valentine_520_dashboard'), 'name': '520情人節', 'id': 'valentine_520'},
            {'url': url_for('edm.labor_day_dashboard'), 'name': '勞動節', 'id': 'labor_day'}
        ]

        scheduler_stats = load_scheduler_stats()

        template_name = 'edm_dashboard_v2.html'

        return render_template(template_name,
                               promo_pages=promo_pages,
                               current_promo_page='valentine_520',
                               page_title=PAGE_NAME,
                               grouped_items=grouped_items,
                               slot_stats=data['slot_stats'],
                               page_window=page_window,
                               total_edm_products=len(data['items_in_batch']),
                               last_update=data['last_update_str'],
                               activity_time=data['activity_time'],
                               active_tab=data['active_tab'],
                               public_url=public_url,
                               scheduler_stats=scheduler_stats,
                               current_sort=sort_by,
                               current_order=order,
                               slugify=slugify,
                               active_page='edm')
    except Exception as e:
        sys_log.error(f"{PAGE_NAME} Dashboard 渲染錯誤: {e}")
        return f"系統錯誤: {e}"
    finally:
        session.close()


@edm_bp.route('/labor_day')
@login_required
def labor_day_dashboard():
    """勞動節促銷活動專屬儀表板"""
    db = DatabaseManager()
    session = db.get_session()

    PAGE_TYPE = "labor_day"
    PAGE_NAME = "勞動節購物優惠"

    sort_by = request.args.get('sort_by', 'default')
    order = request.args.get('order', 'desc')
    requested_slot = request.args.get('slot')
    page, per_page = _get_promo_page_window_args()

    try:
        data = _build_promo_dashboard_data(session, PAGE_TYPE, PAGE_NAME, sort_by, order, requested_slot)
        grouped_items, page_window = _paginate_active_slot(data, page, per_page)

        # 建立儀表板頁籤
        promo_pages = [
            {'url': url_for('edm.edm_dashboard'), 'name': '限時搶購', 'id': 'edm'},
            {'url': url_for('edm.festival_dashboard'), 'name': '1.1狂歡購物節', 'id': 'festival'},
            {'url': url_for('edm.mothers_day_dashboard'), 'name': '母親節', 'id': 'mothers_day'},
            {'url': url_for('edm.valentine_520_dashboard'), 'name': '520情人節', 'id': 'valentine_520'},
            {'url': url_for('edm.labor_day_dashboard'), 'name': '勞動節', 'id': 'labor_day'}
        ]

        scheduler_stats = load_scheduler_stats()

        template_name = 'edm_dashboard_v2.html'

        return render_template(template_name,
                               promo_pages=promo_pages,
                               current_promo_page='labor_day',
                               page_title=PAGE_NAME,
                               grouped_items=grouped_items,
                               slot_stats=data['slot_stats'],
                               page_window=page_window,
                               total_edm_products=len(data['items_in_batch']),
                               last_update=data['last_update_str'],
                               activity_time=data['activity_time'],
                               active_tab=data['active_tab'],
                               public_url=public_url,
                               scheduler_stats=scheduler_stats,
                               current_sort=sort_by,
                               current_order=order,
                               slugify=slugify,
                               active_page='edm')
    except Exception as e:
        sys_log.error(f"{PAGE_NAME} Dashboard 渲染錯誤: {e}")
        return f"系統錯誤: {e}"
    finally:
        session.close()
