import { END_ID, END_NODE, START_ID } from '@/libs/logic-flow/constant';
import type { FlowNodeProperties } from './index';

interface CreateNodeOptions extends FlowNodeProperties {
  point?: Partial<{
    x: number;
    y: number;
  }>;
  rect?: Partial<{
    radius: number;
    width: number;
    height: number;
  }>;
}

export const DEFAULT_NODE_WIDTH = 160;
export const DEFAULT_NODE_HEIGHT = 40;

export const ID_Start = START_ID;
export const ID_End = END_ID;
export const ID_Back = 'back';
export const ID_Register = 'register';
export const ID_Analysis_Pulse = 'pulseAnalysis';
export const ID_Analysis_TongueAndFace = 'tongueAndFaceAnalysis';
export const ID_Analysis_Health = 'healthAnalysis';

export const ID_Report_Pulse = 'pulseAnalysisReport';
export const ID_Report_TongueAndFace = 'tongueAndFaceAnalysisReport';
export const ID_Report_Alcohol = 'alcoholAnalysisReport';
export const ID_Report_Health = 'healthAnalysisReport';
export const ID_Scheme_Health = 'healthAnalysisScheme';

const factory = (type: 'StartNode' | 'EndNode' | 'FlowNode', id: string, text: string, options?: CreateNodeOptions) => {
  const { point, rect, ...properties } = options ?? {};
  return {
    type,
    id,
    text,
    x: point?.x ?? 100,
    y: point?.y ?? 100,
    properties: {
      radius: 8,
      width: rect?.width ?? DEFAULT_NODE_WIDTH,
      height: rect?.height ?? DEFAULT_NODE_HEIGHT,
      ...properties,
    },
  };
};

const textRef = {
  [ID_Start]: '开始检测',
  [ID_End]: '完成检测',
  [ID_Back]: '返回首页',
  [ID_Register]: '建档',
  [ID_Analysis_Pulse]: '脉象分析',
  [ID_Analysis_TongueAndFace]: '舌面象分析',
  [ID_Analysis_Health]: '问诊',
  [ID_Report_Pulse]: '脉象分析报告',
  [ID_Report_TongueAndFace]: '舌面象分析报告',
  [ID_Report_Health]: '报告+方案',
  [ID_Scheme_Health]: '调理方案',
  [ID_Report_Alcohol]: '黄酒建议',
};

export function formatText(value: string | { text?: string | { value?: string } }) {
  let text = '未命名节点';
  if (typeof value === 'string') text = textRef[<keyof typeof textRef>value] ?? text;
  else if (typeof value.text === 'string') text = value.text ?? text;
  else if (typeof value.text === 'object') text = value.text?.value ?? text;
  return text;
}

export function start(options?: CreateNodeOptions) {
  return factory('FlowNode', ID_Start, textRef[ID_Start], {
    icon: 'start',
    iconBackground: '#cf1322',
    iconColor: '#fff',
    configurable: true,
    quickNodes: [ID_Register, ID_Analysis_Pulse, ID_Analysis_TongueAndFace].map((id) => ({ id, text: formatText(id) })),
    ...options,
  });
}

export function end(options?: CreateNodeOptions) {
  return factory('FlowNode', ID_End, textRef[ID_End], {
    icon: 'finish',
    iconBackground: '#0958d9',
    iconColor: '#fff',
    forbidDirectSource: [ID_Start],
    ...options,
  });
}

export function back(options?: CreateNodeOptions) {
  return factory(END_NODE, ID_Back, textRef[ID_Back], {
    radius: 20,
    ...options,
  });
}

export function register(options?: CreateNodeOptions) {
  return factory('FlowNode', ID_Register, textRef[ID_Register], {
    icon: 'config',
    iconBackground: '#c41d7f',
    iconColor: '#fff',
    onlySource: [START_ID],
    configurable: true,
    quickNodes: [ID_Analysis_Pulse, ID_Analysis_TongueAndFace].map((id) => ({ id, text: formatText(id) })),
    ...options,
  });
}

export function pulseAnalysis(options?: CreateNodeOptions) {
  return factory('FlowNode', ID_Analysis_Pulse, textRef[ID_Analysis_Pulse], {
    icon: 'pulse',
    iconBackground: '#d46b08',
    iconColor: '#fff',
    forbidSource: [ID_Report_Pulse],
    quickNodes: [ID_Analysis_TongueAndFace].map((id) => ({ id, text: formatText(id) })),
    ...options,
  });
}
export function tongueAndFaceAnalysis(options?: CreateNodeOptions) {
  return factory('FlowNode', ID_Analysis_TongueAndFace, textRef[ID_Analysis_TongueAndFace], {
    icon: 'tongue',
    iconBackground: '#d46b08',
    iconColor: '#fff',
    forbidSource: [ID_Report_TongueAndFace, ID_Analysis_Health, ID_Report_Alcohol, ID_Report_Health, ID_Scheme_Health],
    quickNodes: [ID_Analysis_Health, ID_Report_TongueAndFace].map((id) => ({ id, text: formatText(id) })),
    ...options,
  });
}

export function healthAnalysis(options?: CreateNodeOptions) {
  return factory('FlowNode', ID_Analysis_Health, textRef[ID_Analysis_Health], {
    icon: 'questionnaire',
    iconBackground: '#d46b08',
    iconColor: '#fff',
    forbidSource: [ID_Report_Alcohol, ID_Report_Health, ID_Scheme_Health],
    quickNodes: [ID_Report_Health, ID_Scheme_Health].map((id) => ({ id, text: formatText(id) })),
    ...options,
  });
}

export function pulseAnalysisReport(options?: CreateNodeOptions) {
  return factory('FlowNode', ID_Report_Pulse, textRef[ID_Report_Pulse], {
    icon: 'report',
    iconBackground: '#08979c',
    iconColor: '#fff',
    forbidDirectTarget: [ID_Back],
    ...options,
  });
}

export function tongueAndFaceAnalysisReport(options?: CreateNodeOptions) {
  return factory('FlowNode', ID_Report_TongueAndFace, textRef[ID_Report_TongueAndFace], {
    icon: 'report',
    iconBackground: '#08979c',
    iconColor: '#fff',
    configurable: true,
    forbidDirectTarget: [ID_Back],
    ...options,
  });
}

export function healthAnalysisReport(options?: CreateNodeOptions) {
  return factory('FlowNode', ID_Report_Health, textRef[ID_Report_Health], {
    icon: 'report',
    iconBackground: '#08979c',
    iconColor: '#fff',
    configurable: true,
    onlyTarget: [ID_End],
    ...options,
  });
}

export function healthAnalysisScheme(options?: CreateNodeOptions) {
  return factory('FlowNode', ID_Scheme_Health, textRef[ID_Scheme_Health], {
    icon: 'report',
    iconBackground: '#08979c',
    iconColor: '#fff',
    configurable: true,
    onlyTarget: [ID_End],
    ...options,
  });
}

export function alcoholAnalysisReport(options?: CreateNodeOptions) {
  return factory('FlowNode', ID_Report_Alcohol, textRef[ID_Report_Alcohol], {
    icon: 'report',
    iconBackground: '#08979c',
    iconColor: '#fff',
    ...options,
  });
}

export function edge(sourceNodeId: string, targetNodeId: string, properties?: Record<string, any>) {
  return {
    type: 'custom-polyline-edge',
    sourceNodeId,
    targetNodeId,
    properties: properties ?? {},
  };
}
