'use client';

import { toast } from 'sonner';
import { useAuthStore } from '@/stores/auth-store';
import { fillActionUrl, openHostUrl } from '@/lib/action-url';
import {
  HOST_ACTION_MESSAGE_SOURCE,
  HOST_ACTION_MESSAGE_TYPE,
  type HostActionMessage,
  type HostPotentialTreatmentPayload,
} from '@pac/types';

/**
 * 宿主动作派发(潜在治疗 / 回访)—— 模式由 actionUrls[key] 的值形态决定:
 *
 *   未配置          → 动作不可用,按钮不渲染(PAC 默认无此动作)
 *   URL 模板        → 占位替换后打开宿主页(推荐姿势,同 CREATE_APPOINTMENT)
 *   哨兵 'postMessage' → 向宿主父窗发动作事件,宿主监听后弹自己的组件
 *                       (兜底通道,限"宿主动作是弹窗/组件、没有独立 URL"的场景;
 *                        需同时配 HOST_ORIGIN 作 targetOrigin,否则视为配置错误 → 不可用)
 *
 * postMessage 信封(与对接方约定的契约一致,宿主据 type+source 过滤):
 *   { source: 'pac', type: 'action', action, payload: { patientId } }
 * targetOrigin 走 actionUrls.HOST_ORIGIN(不允许 '*')。不做 iframe 判断:
 * 非嵌入时 targetOrigin 与当前窗口不符,浏览器自动丢弃(无副作用)。
 */
export type HostAction = 'OPEN_POTENTIAL_TREATMENT' | 'OPEN_RETURN_VISIT';

/** 哨兵值:配在 actionUrls[key] 上表示该动作走 postMessage 而非 URL 跳转(比较不区分大小写)。 */
export const POST_MESSAGE_SENTINEL = 'postMessage';

/** 值是否哨兵 —— 大小写不敏感:裸词不可能是合法 URL 模板,宽容拼写不会误伤 URL 配置。 */
export function isPostMessageSentinel(value: string | null | undefined): boolean {
  return value?.trim().toLowerCase() === POST_MESSAGE_SENTINEL.toLowerCase();
}

/** 宿主 origin(postMessage targetOrigin)—— 来自会话下发的 actionUrls.HOST_ORIGIN。 */
export function hostOrigin(): string | undefined {
  return useAuthStore.getState().user?.actionUrls?.HOST_ORIGIN || undefined;
}

function rawValue(key: HostAction): string | undefined {
  return useAuthStore.getState().user?.actionUrls?.[key]?.trim() || undefined;
}

/**
 * 宿主动作可用性(按钮渲染依据)。
 * 返回 undefined = 不可用(未配置,或配了哨兵却没配 HOST_ORIGIN)。
 */
export function hostActionMode(key: HostAction): 'url' | 'postMessage' | undefined {
  const raw = rawValue(key);
  if (!raw) return undefined;
  if (isPostMessageSentinel(raw)) return hostOrigin() ? 'postMessage' : undefined;
  return 'url';
}

/**
 * 按配置模式派发宿主动作。不可用时提示并返 false(正常按钮已按 hostActionMode 隐藏,
 * 此处兜底会话中途配置变化的竞态)。
 */
export function openHostAction(
  key: HostAction,
  ctx: Record<string, string | null | undefined>,
  /**
   * 附加载荷(仅 postMessage 模式带上)—— 目前只有「打开潜在治疗」用:
   * 待治疗描述 / 关联治疗项目 / 病例阶段。契约见 @pac/types/host-action-message。
   * ⚠️ 刻意**不进 URL 模式**:这三个字段是长文本 + 数组,塞 query string 会撞长度上限、
   * 还会把病情描述写进浏览器历史和宿主的 access log。要 URL 模式也带,得宿主改成 POST。
   */
  extraPayload?: HostPotentialTreatmentPayload,
): boolean {
  const raw = rawValue(key);
  const mode = hostActionMode(key);
  if (!raw || !mode) {
    toast('宿主动作未配置', { description: `请在宿主管理页配置 actionUrls.${key}` });
    return false;
  }
  if (mode === 'url') {
    openHostUrl(fillActionUrl(raw, ctx));
    return true;
  }
  // 信封:source + type + action + payload(契约约定;无 version / doctorId / meta)
  const message: HostActionMessage = {
    source: HOST_ACTION_MESSAGE_SOURCE,
    type: HOST_ACTION_MESSAGE_TYPE,
    action: key,
    payload: { patientId: ctx.patientId ?? '', ...(extraPayload ?? {}) },
  };
  window.parent.postMessage(message, hostOrigin()!);
  return true;
}
