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

import hashlib
from datetime import datetime, timezone, timedelta
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
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__)


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

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 _build_promo_dashboard_data(session, page_type, page_name, sort_by, order):
    """
    通用的促銷儀表板數據建構函數
    用於 edm 和 festival 兩種頁面類型
    """
    # 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 active_tab not in sorted_grouped_items and sorted_grouped_items:
        active_tab = next(iter(sorted_grouped_items))

    # 7. 計算在架天數與總銷量
    all_icodes_in_batch = [item.i_code for item in items_in_batch]
    product_categories = {}
    days_on_shelf_map = {}
    total_sold_map = {}
    history_map = {}

    if all_icodes_in_batch:
        # 從主商品表查詢分類
        main_products = session.query(Product.i_code, Product.category).filter(
            Product.i_code.in_(all_icodes_in_batch)
        ).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_(all_icodes_in_batch),
                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_(all_icodes_in_batch),
                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_(all_icodes_in_batch),
                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 items_in_batch:
                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_(all_icodes_in_batch),
                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 items_in_batch:
        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 sorted_grouped_items:
        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

    return {
        '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
    }


# ==========================================
# 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')

    try:
        data = _build_promo_dashboard_data(session, 'edm', '限時搶購', sort_by, order)

        # 建立儀表板頁籤
        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.html' if request.args.get('ui') == 'legacy' else 'edm_dashboard_v2.html'

        return render_template(template_name,
                               promo_pages=promo_pages,
                               current_promo_page='edm',
                               page_title='MOMO 限時搶購',
                               grouped_items=data['sorted_grouped_items'],
                               slot_stats=data['slot_stats'],
                               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')

    try:
        data = _build_promo_dashboard_data(session, PAGE_TYPE, PAGE_NAME, sort_by, order)

        # 建立儀表板頁籤
        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.html' if request.args.get('ui') == 'legacy' else 'edm_dashboard_v2.html'

        return render_template(template_name,
                               promo_pages=promo_pages,
                               current_promo_page='festival',
                               page_title=PAGE_NAME,
                               grouped_items=data['sorted_grouped_items'],
                               slot_stats=data['slot_stats'],
                               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')

    try:
        data = _build_promo_dashboard_data(session, PAGE_TYPE, PAGE_NAME, sort_by, order)

        # 建立儀表板頁籤
        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.html' if request.args.get('ui') == 'legacy' else 'edm_dashboard_v2.html'

        return render_template(template_name,
                               promo_pages=promo_pages,
                               current_promo_page='mothers_day',
                               page_title=PAGE_NAME,
                               grouped_items=data['sorted_grouped_items'],
                               slot_stats=data['slot_stats'],
                               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')

    try:
        data = _build_promo_dashboard_data(session, PAGE_TYPE, PAGE_NAME, sort_by, order)

        # 建立儀表板頁籤
        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.html' if request.args.get('ui') == 'legacy' else 'edm_dashboard_v2.html'

        return render_template(template_name,
                               promo_pages=promo_pages,
                               current_promo_page='valentine_520',
                               page_title=PAGE_NAME,
                               grouped_items=data['sorted_grouped_items'],
                               slot_stats=data['slot_stats'],
                               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')

    try:
        data = _build_promo_dashboard_data(session, PAGE_TYPE, PAGE_NAME, sort_by, order)

        # 建立儀表板頁籤
        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.html' if request.args.get('ui') == 'legacy' else 'edm_dashboard_v2.html'

        return render_template(template_name,
                               promo_pages=promo_pages,
                               current_promo_page='labor_day',
                               page_title=PAGE_NAME,
                               grouped_items=data['sorted_grouped_items'],
                               slot_stats=data['slot_stats'],
                               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()
