# AI_CHANGELOG
# - 2026-03-20 | Prompt: H2 FDW→直连ETL统一改造 | FDW 外部表（fdw_etl.*）改为直连 ETL 库
#   查询 app.v_* RLS 视图。原因：postgres_fdw 不传递 GUC 参数，RLS 门店隔离失效。
#   使用 fdw_queries._fdw_context() 上下文管理器统一管理 ETL 连接。

# -*- coding: utf-8 -*-
"""
人员匹配服务 —— 根据申请信息在 ETL 库 RLS 视图中查找候选匹配。

职责：
- find_candidates()：根据 site_id + phone（+ employee_number）在助教表和员工表中查找匹配

直连 ETL 库查询 app.v_* RLS 视图，通过 _fdw_context 设置 site_id 实现门店隔离。
ETL 库连接失败时优雅降级返回空列表。
"""

from __future__ import annotations

import logging

from app.services.fdw_queries import _fdw_context
from app.trace.decorators import trace_service

logger = logging.getLogger(__name__)


@trace_service(description_zh="查找匹配候选人", description_en="Find matching candidates")
async def find_candidates(
    site_id: int | None,
    phone: str,
    employee_number: str | None = None,
) -> list[dict]:
    """
    在助教表和员工表中查找匹配候选。

    查询逻辑：
    1. 若 site_id 为 None，跳过匹配，返回空列表
    2. 设置 app.current_site_id 进行 RLS 隔离（直连 ETL 库）
    3. app.v_dim_assistant: WHERE mobile = phone
    4. app.v_dim_staff JOIN app.v_dim_staff_ex: WHERE mobile = phone OR job_num = employee_number
    5. 合并结果返回统一候选列表

    参数:
        site_id: 门店 ID（None 时跳过匹配）
        phone: 手机号
        employee_number: 员工编号（可选，用于 job_num 匹配）

    返回:
        [{"source_type": "assistant"|"staff", "id": int, "name": str,
          "mobile": str|None, "job_num": str|None}]
    """
    # site_id 为空时直接返回空列表（需求 5.6）
    if site_id is None:
        return []

    candidates: list[dict] = []

    # CHANGE 2026-03-20 | H2 FDW→直连ETL | 从业务库 fdw_etl.* 改为直连 ETL 库 app.v_*
    # intent: 修复 RLS 门店隔离失效（postgres_fdw 不传递 GUC 参数）
    # assumptions: _fdw_context 内部管理 ETL 连接生命周期，无需外部 conn
    try:
        with _fdw_context(None, site_id) as cur:
            # 1. 查询助教匹配
            candidates.extend(_query_assistants(cur, phone))

            # 2. 查询员工匹配
            candidates.extend(_query_staff(cur, phone, employee_number))
    except Exception:
        logger.warning(
            "ETL 人员匹配查询失败 (site_id=%s, phone=%s)，返回空列表",
            site_id,
            phone,
            exc_info=True,
        )
        return []

    return candidates


def _query_assistants(cur, phone: str) -> list[dict]:
    """查询 app.v_dim_assistant 中按 mobile 匹配的助教记录（直连 ETL 库）。"""
    try:
        # CHANGE 2026-03-20 | H2 | fdw_etl.v_dim_assistant → app.v_dim_assistant
        # 列名映射: scd2_is_current 是 integer 类型（1=当前），不是 boolean
        cur.execute(
            """
            SELECT assistant_id, real_name, mobile
              FROM app.v_dim_assistant
             WHERE mobile = %s
               AND scd2_is_current = 1
            """,
            (phone,),
        )
        rows = cur.fetchall()
    except Exception:
        logger.warning(
            "查询 app.v_dim_assistant 失败，跳过助教匹配",
            exc_info=True,
        )
        return []

    return [
        {
            "source_type": "assistant",
            "id": row[0],
            "name": row[1] or "",
            "mobile": row[2],
            "job_num": None,
        }
        for row in rows
    ]


def _query_staff(
    cur, phone: str, employee_number: str | None
) -> list[dict]:
    """
    查询 app.v_dim_staff JOIN app.v_dim_staff_ex（直连 ETL 库）
    按 mobile 或 job_num 匹配的员工记录。
    """
    try:
        # CHANGE 2026-03-20 | H2 | fdw_etl.v_dim_staff/v_dim_staff_ex → app.v_dim_staff/v_dim_staff_ex
        # 列名映射: scd2_is_current 是 integer 类型（1=当前），不是 boolean
        if employee_number:
            cur.execute(
                """
                SELECT s.staff_id, s.staff_name, s.mobile, ex.job_num
                  FROM app.v_dim_staff s
                  LEFT JOIN app.v_dim_staff_ex ex
                    ON s.staff_id = ex.staff_id
                   AND ex.scd2_is_current = 1
                 WHERE s.scd2_is_current = 1
                   AND (s.mobile = %s OR ex.job_num = %s)
                """,
                (phone, employee_number),
            )
        else:
            cur.execute(
                """
                SELECT s.staff_id, s.staff_name, s.mobile, ex.job_num
                  FROM app.v_dim_staff s
                  LEFT JOIN app.v_dim_staff_ex ex
                    ON s.staff_id = ex.staff_id
                   AND ex.scd2_is_current = 1
                 WHERE s.scd2_is_current = 1
                   AND s.mobile = %s
                """,
                (phone,),
            )
        rows = cur.fetchall()
    except Exception:
        logger.warning(
            "查询 app.v_dim_staff 失败，跳过员工匹配",
            exc_info=True,
        )
        return []

    return [
        {
            "source_type": "staff",
            "id": row[0],
            "name": row[1] or "",
            "mobile": row[2],
            "job_num": row[3],
        }
        for row in rows
    ]
