import { defineStore } from 'pinia';
import type { CardInstance, ChatMessage, TaskState } from '../api/types';
import { connectChatStream, type ParsedSseEvent } from '../api/sse';
import { fetchCard, submitCardAction } from '../api/client';

function randomUUID(): string {
  try { return randomUUID(); } catch { /* HTTP */ }
  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
    const r = (Math.random() * 16) | 0;
    return (c === 'x' ? r : (r & 0x3) | 0x8).toString(16);
  });
}

export type ContextPanelMode = 'idle' | 'thinking' | 'loading' | 'task' | 'error' | 'completed';
export type ConnectionStatus = 'online' | 'disconnected';

export interface CardPreview {
  id: string;
  cardKey: string;
  title: string;
  subtitle: string;
  timestamp: string;
  _seq?: number;
}

const CARD_TITLE_MAP: Record<string, string> = {
  'department-selection': '科室推荐',
  'doctor-selection': '医生选择',
  'time-slot-selection': '就诊时间',
  'confirm-appointment': '确认预约',
  'payment-qrcode': '支付',
  'appointment-success': '挂号成功',
};

export const useTerminalStore = defineStore('terminal', {
  state: () => ({
    deviceId: 'EMOON-WEB-DEMO-001',
    deviceType: 'self_service_kiosk',
    conversationId: '' as string,
    currentTraceId: '' as string,
    messages: [] as ChatMessage[],
    _timelineSeq: 0,
    streaming: false,
    task: null as TaskState | null,
    activeCard: null as CardInstance | null,
    cardHistory: [] as CardInstance[],
    viewingCardId: null as string | null,
    cardPreviews: [] as CardPreview[],
    errorMessage: '' as string,
    connectionStatus: 'online' as ConnectionStatus,
    inputText: '',
    pendingActionKey: '',
    demoMode: import.meta.env.VITE_DEMO_MODE === 'true',
    sending: false,
    cardActionSubmitting: false,
    selection: {} as Record<string, string>,
  }),
  getters: {
    contextPanelMode(state): ContextPanelMode {
      if (state.errorMessage) return 'error';
      if (state.sending && !state.activeCard && !state.viewingCardId) return 'thinking';
      if (this.displayedCard?.cardKey === 'appointment-success') return 'completed';
      if (this.displayedCard) return 'task';
      if (state.sending || state.streaming) return 'thinking';
      return 'idle';
    },
    displayedCard(state): CardInstance | null {
      if (state.viewingCardId) {
        return state.cardHistory.find((c) => c.cardInstanceId === state.viewingCardId) ?? state.activeCard;
      }
      return state.activeCard;
    },
    isDemo(): boolean {
      return this.demoMode;
    },
  },
  actions: {
    addMessage(message: ChatMessage) {
      message._seq = ++this._timelineSeq;
      this.messages.push(message);
    },
    appendAssistantDelta(text: string) {
      const last = this.messages[this.messages.length - 1];
      if (last?.role === 'assistant' && last.streaming) {
        last.content += text;
        return;
      }
      this.messages.push({
        id: randomUUID(),
        role: 'assistant',
        content: text,
        streaming: true,
        timestamp: new Date().toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit' }),
        _seq: ++this._timelineSeq,
      });
    },
    completeAssistantMessage() {
      const last = this.messages[this.messages.length - 1];
      if (last?.role === 'assistant') last.streaming = false;
    },
    setTask(task: TaskState) {
      this.task = task;
    },
    setActiveCard(card: CardInstance) {
      this.activeCard = card;
      this.viewingCardId = null;
      this.cardHistory.push(card);
      this.errorMessage = '';
      // Push mini card preview for chat feed
      const cardKey = card.cardKey;
      const title = CARD_TITLE_MAP[cardKey] || cardKey;
      const data = card.cardData || {};
      let subtitle = '';
      if (cardKey === 'department-selection') {
        const depts = data.departments as Array<{ name: string }> | undefined;
        subtitle = depts?.[0]?.name ? `${depts[0].name}${depts.length > 1 ? '等' + depts.length + '个科室' : ''}` : '';
      } else if (cardKey === 'doctor-selection') {
        const docs = data.doctors as Array<{ name: string; title: string; doctorName?: string }> | undefined;
        const top = docs?.[0];
        if (top) {
          const dept = (this.selection.departmentName as string) || '';
          subtitle = `${top.name || top.doctorName || ''} ${top.title || ''}`.trim();
          if (dept) subtitle += ` · ${dept}`;
        }
      } else if (cardKey === 'time-slot-selection') {
        const slots = data.slots as Array<{ timePeriod: string }> | undefined;
        const amount = data.amountYuan ?? data.amount ?? '';
        subtitle = slots?.[0]?.timePeriod || '';
        if (subtitle && amount) subtitle += ` · ¥${amount}`;
      } else if (cardKey === 'confirm-appointment') {
        const dept = (this.selection.departmentName as string) || (data.departmentName as string) || '';
        const doc = (this.selection.doctorName as string) || (data.doctorName as string) || '';
        const date = (data.visitDate as string) || '';
        const time = (this.selection.timePeriod as string) || (data.visitTime as string) || '';
        const amt = data.amountYuan ?? data.amount ?? '25.00';
        subtitle = [dept, doc, date + (date && time ? ' ' : '') + time, `¥${amt}`].filter(Boolean).join(' · ');
      } else if (cardKey === 'payment-qrcode') {
        const amount = data.amountYuan || '0.00';
        subtitle = `Mock支付 ¥${amount}`;
      } else if (cardKey === 'appointment-success') {
        const aptNo = (data.appointmentNo as string) || (data.appointmentNoStr as string) || '';
        const visitDate = (data.visitDate as string) || (data.visitTime as string) || '';
        const visitTime = (data.timePeriod as string) || (this.selection.timePeriod as string) || '';
        const docName = (data.doctorName as string) || (this.selection.doctorName as string) || '';
        const docTitle = (data.doctorTitle as string) || (this.selection.doctorTitle as string) || '';
        const parts = [aptNo, visitDate + visitTime, docName + (docTitle ? ' ' + docTitle : '')].filter(Boolean);
        subtitle = parts.join(' · ') || '预约已确认';
      }
      this.cardPreviews.push({ id: card.cardInstanceId, cardKey, title, subtitle, timestamp: new Date().toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit' }), _seq: ++this._timelineSeq });
    },
    setError(message: string, traceId = '') {
      this.errorMessage = message;
      this.currentTraceId = traceId;
    },
    viewCard(cardInstanceId: string | null) {
      this.viewingCardId = cardInstanceId;
    },
    resetToIdle() {
      this.task = null;
      this.activeCard = null;
      this.viewingCardId = null;
      this.cardHistory = [];
      this.cardPreviews = [];
      this.errorMessage = '';
      this.pendingActionKey = '';
      this.selection = {};
    },

    saveSelection(payload: Record<string, unknown>) {
      for (const [key, value] of Object.entries(payload)) {
        if (typeof value === 'string') {
          this.selection[key] = value;
        }
      }
    },

    handleSseEvent(event: ParsedSseEvent) {
      switch (event.type) {
        case 'task_updated': {
          const data = event.data as unknown as TaskState;
          this.setTask(data);
          break;
        }
        case 'message_delta': {
          const text = event.data.text as string;
          if (text) this.appendAssistantDelta(text);
          this.streaming = true;
          break;
        }
        case 'message_completed': {
          this.completeAssistantMessage();
          this.streaming = false;
          if (event.data.conversationId) {
            this.conversationId = event.data.conversationId as string;
          }
          break;
        }
        case 'card_created': {
          const cardInstanceId = event.data.cardInstanceId as string;
          if (cardInstanceId) {
            fetchCard(cardInstanceId)
              .then((card) => this.setActiveCard(card))
              .catch((err) => this.setError(err.message));
          }
          break;
        }
        case 'error': {
          this.setError(
            (event.data.message as string) ?? '未知错误',
            (event.data.traceId as string) ?? '',
          );
          this.streaming = false;
          break;
        }
        case 'completed': {
          this.streaming = false;
          break;
        }
      }
    },

    async sendMessage(text: string): Promise<void> {
      if (this.sending) return; // 防重入：正在发送中不允许重复调用
      this.addMessage({ id: randomUUID(), role: 'user', content: text, timestamp: new Date().toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit' }) });
      this.errorMessage = '';
      this.sending = true;
      this.streaming = true;

      return new Promise((resolve, reject) => {
        connectChatStream({
          deviceId: this.deviceId,
          deviceType: this.deviceType,
          text,
          conversationId: this.conversationId || undefined,
          onEvent: (event) => this.handleSseEvent(event),
          onError: (error) => {
            this.setError(error.message);
            this.streaming = false;
            this.sending = false;
            reject(error);
          },
          onComplete: () => {
            this.streaming = false;
            this.sending = false;
            resolve();
          },
        });
      });
    },

    addSelectionBubble(payload: Record<string, unknown>) {
      const cardKey = this.activeCard?.cardKey ?? '';
      let text = '';
      if (cardKey === 'department-selection') text = (payload.departmentName as string) || '';
      else if (cardKey === 'doctor-selection') text = `${payload.doctorTitle || ''} ${payload.doctorName || ''}`.trim();
      else if (cardKey === 'time-slot-selection') text = (payload.timePeriod as string) || '';
      else if (cardKey === 'confirm-appointment') text = '确认挂号';
      else if (cardKey === 'payment-qrcode') return;
      else text = JSON.stringify(payload);
      if (text) {
        this.addMessage({
          id: randomUUID(),
          role: 'user',
          content: text,
          timestamp: new Date().toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit' }),
        });
      }
    },

    addTransitionMessage(nextCard: CardInstance) {
      const currentKey = this.activeCard?.cardKey ?? '';
      const nextKey = nextCard.cardKey;
      let text = '';
      if (currentKey === 'department-selection' && nextKey === 'doctor-selection') {
        const deptName = (this.selection.departmentName as string) || '';
        const docs = nextCard.cardData.doctors as Array<{ name: string; title: string }> | undefined;
        if (docs?.[0]) {
          text = `好的，以下是${deptName}可预约的医生。根据您的症状，建议优先选择${docs[0].title} ${docs[0].name}`;
        } else {
          text = `好的，以下是${deptName}可预约的医生`;
        }
      } else if (currentKey === 'doctor-selection' && nextKey === 'time-slot-selection') {
        const dn = this.selection.doctorName || '';
        const dt = this.selection.doctorTitle || '';
        text = `好的，以下是${dt}${dn}的可预约时段`;
      } else if (currentKey === 'time-slot-selection' && nextKey === 'confirm-appointment') {
        text = '好的，请确认以下预约信息';
      } else if (currentKey === 'confirm-appointment' && nextKey === 'payment-qrcode') {
        text = '预约信息已确认，请扫码支付挂号费';
      } else if (currentKey === 'payment-qrcode' && nextKey === 'appointment-success') {
        text = '支付成功。您的挂号已确认，请按时到诊区签到候诊。系统将根据您的位置自动提醒签到。';
      }
      if (!text) return Promise.resolve();
      return new Promise<void>((resolve) => {
        const msgId = randomUUID();
        const isSuccess = currentKey === 'payment-qrcode' && nextKey === 'appointment-success';
        this.messages.push({
          id: msgId,
          role: 'assistant',
          content: '',
          streaming: true,
          timestamp: new Date().toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit' }),
          _seq: ++this._timelineSeq,
          _type: isSuccess ? 'success' : undefined,
        });
        let i = 0;
        const timer = setInterval(() => {
          const msg = this.messages.find((m) => m.id === msgId);
          if (!msg) { clearInterval(timer); resolve(); return; }
          msg.content += text[i++];
          if (i >= text.length) {
            clearInterval(timer);
            msg.streaming = false;
            resolve();
          }
        }, 40);
      });
    },

    async submitCard(payload: Record<string, unknown>): Promise<void> {
      if (!this.activeCard || this.cardActionSubmitting) return;

      const actionName = this.activeCard.actions[0]?.actionName;
      if (!actionName) return;

      this.pendingActionKey = `${this.activeCard.cardInstanceId}-${actionName}`;
      this.errorMessage = '';
      this.cardActionSubmitting = true;

      // 15 秒超时兜底，防止网络异常导致按钮永久禁用
      const timeoutId = setTimeout(() => {
        if (this.cardActionSubmitting) {
          this.setError('请求超时，请重试');
          this.cardActionSubmitting = false;
        }
      }, 15_000);

      try {
        const result = await submitCardAction(
          this.activeCard.cardInstanceId,
          actionName,
          payload,
        );

        clearTimeout(timeoutId);

        if (result.nextCard?.cardInstanceId) {
          const fullCard = await fetchCard(result.nextCard.cardInstanceId);
          await this.addTransitionMessage(fullCard);
          this.setActiveCard(fullCard);
        }
      } catch (err) {
        clearTimeout(timeoutId);
        this.setError((err as Error).message);
        throw err;
      } finally {
        this.cardActionSubmitting = false;
      }
    },
  },
});
