#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
OSS Inventory 自动导入 — 函数计算（FC）入口

当 OSS 触发器检测到新的 manifest.json 写入时，自动解析清单并将
OSS 文件元数据批量写入 Tablestore。

触发器配置：
  - 触发器类型: OSS
  - 触发事件:   ObjectCreated:PutObject
  - 前缀过滤:   <report-bucket>/<source-bucket>/<inventory-rule-name>/
  - 后缀过滤:   manifest.json

必填环境变量：
  OSS_ACCESS_KEY_ID      OSS Access Key ID
  OSS_ACCESS_KEY_SECRET  OSS Access Key Secret
  OSS_REGION             OSS 地域，如 cn-hangzhou
  OTS_ACCESS_KEY_ID      OTS Access Key ID（可与 OSS 相同）
  OTS_ACCESS_KEY_SECRET  OTS Access Key Secret
  OTS_ENDPOINT           OTS 实例访问地址
  OTS_INSTANCE_NAME      OTS 实例名称

可选环境变量：
  OTS_TABLE_NAME         OTS 数据表名（默认: oss_inventory）
"""

import json
import logging
import os

from oss_inventory_import import import_from_manifest

# ============================================================
# 日志
# ============================================================
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s %(levelname)s: %(message)s',
    datefmt='%Y-%m-%d %H:%M:%S'
)
logger = logging.getLogger('fc_handler')

# ============================================================
# 必填环境变量
# ============================================================
REQUIRED_ENV_VARS = [
    'OSS_ACCESS_KEY_ID',
    'OSS_ACCESS_KEY_SECRET',
    'OSS_REGION',
    'OTS_ACCESS_KEY_ID',
    'OTS_ACCESS_KEY_SECRET',
    'OTS_ENDPOINT',
    'OTS_INSTANCE_NAME',
]


def load_config_from_env():
    """从环境变量加载配置，缺少必填项时抛出 RuntimeError"""
    missing = [v for v in REQUIRED_ENV_VARS if not os.environ.get(v)]
    if missing:
        raise RuntimeError(f"缺少必填环境变量: {', '.join(missing)}")

    return {
        'oss_access_key_id':     os.environ['OSS_ACCESS_KEY_ID'],
        'oss_access_key_secret': os.environ['OSS_ACCESS_KEY_SECRET'],
        'oss_region':            os.environ['OSS_REGION'],
        'ots_access_key_id':     os.environ['OTS_ACCESS_KEY_ID'],
        'ots_access_key_secret': os.environ['OTS_ACCESS_KEY_SECRET'],
        'ots_endpoint':          os.environ['OTS_ENDPOINT'],
        'ots_instance_name':     os.environ['OTS_INSTANCE_NAME'],
        'ots_table_name':        os.environ.get('OTS_TABLE_NAME', 'oss_inventory'),
    }


# ============================================================
# FC 入口
# ============================================================
def handler(event, context):
    """
    函数计算入口。
    OSS 触发器 event 为 JSON bytes，核心字段：
      events[0].eventName  事件类型，如 ObjectCreated:PutObject
      events[0].oss.bucket.name  触发的 Bucket 名称
      events[0].oss.object.key   触发的对象路径（即 manifest.json 的 key）
    """
    request_id = getattr(context, 'request_id', 'local')
    logger.info(f"[START] request_id={request_id}")

    # 解析 OSS 触发器事件
    if isinstance(event, (bytes, bytearray)):
        event = event.decode('utf-8')
    data = json.loads(event)

    oss_event = data['events'][0]
    event_name = oss_event['eventName']
    bucket = oss_event['oss']['bucket']['name']
    key = oss_event['oss']['object']['key']

    logger.info(f"事件: {event_name} | oss://{bucket}/{key}")

    if not event_name.startswith('ObjectCreated:'):
        logger.info(f"跳过非写入事件: {event_name}")
        return 'skipped'

    # 加载配置
    try:
        cfg = load_config_from_env()
    except RuntimeError as e:
        logger.error(f"配置错误: {e}")
        raise

    logger.info(f"OTS endpoint: {cfg['ots_endpoint']} | table: {cfg['ots_table_name']}")

    # 导入
    try:
        total = import_from_manifest(bucket, key, cfg)
    except Exception as e:
        logger.error(f"导入失败: {e}")
        raise

    logger.info(f"[DONE] 共写入 {total} 行")
    return f"success: {total} rows written"
