// INVYONE Stage-2 — Emergency Scenario Player
// 시연용 자동 시나리오 시퀀서: 경고 발생 → 모달(CCTV+담당자) → 핸드폰 알림 → 회사맵 → 담당자 이동 → ACK → 복귀
// 각 step은 { at: ms, action: fn } 형식. start() 호출 시 setTimeout chain으로 자동 진행.

(function (global) {
  // ============================================================
  // STATE
  // ============================================================
  const state = {
    running: false,
    paused: false,
    timers: [],         // 활성 setTimeout id 목록 (stop 시 일괄 clearTimeout)
    currentStep: 0,
    startTime: 0,
    pausedAt: 0,
    waitingAck: false,  // ACK 대기 중인지
    onAck: null,        // ACK 클릭 시 호출할 콜백
  };

  // ============================================================
  // SCENARIO DEFINITIONS
  // ============================================================
  // 1번 설비 = BW-A1 (원수 취수펌프 #1)
  // 시나리오: 토출압 과압 → 알람 → 자동 인터록 후보 → 담당자 호출 → 도착 → ACK
  const SCENARIO_BW_A1 = {
    id: 'bw-a1-overpressure',
    title: 'BW-A1 펌프 과압 / 누설 의심',
    targetComp: 'bw-a1',                          // P&ID에서 깜빡일 설비
    targetGauge: 'p-in-1',                         // 압력 알람 발생 게이지
    cam: { id: 'CAM-01', label: 'PUMP ROOM A / BW-A1' },
    officer: {
      name: '김영수',
      title: '안전관리책임자',
      phone: '010-7842-3019',
      role: 'EHS 1차 대응자',
      avatar: 'KY',                                // 이니셜 표기
      from: 'control-room',                        // 맵 시작 위치
      to: 'pump-room-a',                           // 맵 도착 위치
    },
    alarm: {
      code: 'P-IN-HH',
      severity: 'CRITICAL',
      title: 'P-IN 토출압 HH (≥7.0 bar) — 누설 의심',
      message: 'BW-A1 토출 압력이 정상 운전 범위(4.0~5.0 bar)를 초과했습니다.\n현장 점검이 즉시 필요합니다.',
    },
    steps: [
      { at: 0,     label: '시연 시작 + 시각 강조 (배너+핀+펌프)', action: ctx => beginScenario(ctx) },
      { at: 400,   label: '압력 1차 상승 (노란 영역)',            action: ctx => pressureRise1(ctx) },
      { at: 1100,  label: '압력 2차 상승 (빨간 영역, HH 임계)',    action: ctx => pressureRise2(ctx) },
      { at: 1500,  label: '★ CRITICAL 알람 발령',                action: ctx => raiseAlarm(ctx) },
      { at: 2000,  label: '모달 팝업',                            action: ctx => openModal(ctx) },
      { at: 2700,  label: '핸드폰 알림 발송',                     action: ctx => triggerPhoneAlert(ctx) },
      { at: 3700,  label: '회사 맵 슬라이드 인',                  action: ctx => openMap(ctx) },
      { at: 5200,  label: '담당자 이동 시작',                     action: ctx => startOfficerMove(ctx) },
      { at: 7700,  label: '핸드폰 확인 탭',                       action: ctx => phoneTapAck(ctx) },
      { at: 12200, label: '담당자 현장 도착',                     action: ctx => officerArrived(ctx) },
      { at: 13200, label: 'ACK 대기 (시연자 클릭)',                action: ctx => waitForOperatorAck(ctx) },
    ],
  };

  const SCENARIOS = { 'bw-a1-overpressure': SCENARIO_BW_A1 };

  // ============================================================
  // STEP ACTIONS (각 step에서 호출)
  // ============================================================
  function beginScenario(ctx) {
    const E = global.INVYONE_ENGINE;
    E.emitEvent(`🚨 경고시스템 시연 시작 — ${ctx.scenario.title}`, 'alarm');
    if (E.state.currentMode !== 'NORMAL') E.applyMode('NORMAL');
    // 시연 시작 즉시 강력한 시각 효과 — 펌프 강조 + 알람 핀 + 상단 배너 동시
    highlightTarget(ctx.scenario.targetComp, true);
    flashTargetComp(ctx.scenario.targetComp);
    dispatch('scenario:bannerOn', ctx);
    dispatch('scenario:pinShow', ctx);
  }

  function pressureRise1(ctx) {
    const E = global.INVYONE_ENGINE;
    const g = E.state.gauges[ctx.scenario.targetGauge];
    if (g) {
      g.forced = true;
      g.value = (g.max || 8) * 0.72; // 5.76 bar — 노란 주의 영역
      E.setGaugeVisual(ctx.scenario.targetGauge);
    }
    E.emitEvent(`P-IN 압력 상승 감지 (${g ? g.value.toFixed(1) : '?'} bar) — WARNING`, 'warn');
  }

  function pressureRise2(ctx) {
    const E = global.INVYONE_ENGINE;
    const g = E.state.gauges[ctx.scenario.targetGauge];
    if (g) {
      g.forced = true;
      g.value = (g.max || 8) * 0.95; // 7.6 bar — 빨강 임계 초과
      E.setGaugeVisual(ctx.scenario.targetGauge);
    }
    E.emitEvent(`P-IN 압력 임계 초과 (${g ? g.value.toFixed(1) : '?'} bar) — HH 진입`, 'alarm');
  }

  function raiseAlarm(ctx) {
    const E = global.INVYONE_ENGINE;
    E.emitEvent(`★ ${ctx.scenario.alarm.severity} — ${ctx.scenario.alarm.title}`, 'alarm');
  }

  function openModal(ctx)         { dispatch('scenario:openModal', ctx); }
  function triggerPhoneAlert(ctx) {
    dispatch('scenario:phoneAlert', ctx);
    pushAlarmToWorker(ctx);
  }
  function openMap(ctx)           { dispatch('scenario:openMap', ctx); }
  function startOfficerMove(ctx)  { dispatch('scenario:officerMove', ctx); }
  function phoneTapAck(ctx)       { dispatch('scenario:phoneTap', ctx); }
  function officerArrived(ctx)    {
    dispatch('scenario:officerArrived', ctx);
    global.INVYONE_ENGINE.emitEvent(`[현장도착] ${ctx.scenario.officer.name} ${ctx.scenario.officer.title} — 점검 시작`, 'info');
  }
  function waitForOperatorAck(ctx) {
    state.waitingAck = true;
    dispatch('scenario:waitAck', ctx);
    global.INVYONE_ENGINE.emitEvent('ACK 대기 중 — 시연자가 모달의 [확인] 버튼을 클릭하세요', 'warn');
  }

  // ============================================================
  // PLAYER CONTROL
  // ============================================================
  function play(scenarioId) {
    const scenario = SCENARIOS[scenarioId];
    if (!scenario) { console.warn('Unknown scenario:', scenarioId); return; }
    if (state.running) stop();

    state.running = true;
    state.paused = false;
    state.currentStep = 0;
    state.startTime = Date.now();
    state.waitingAck = false;

    const ctx = { scenario, state };
    scenario.steps.forEach((step, i) => {
      const t = setTimeout(() => {
        if (!state.running) return;
        state.currentStep = i;
        try { step.action(ctx); } catch (err) { console.error('Scenario step error:', err); }
      }, step.at);
      state.timers.push(t);
    });

    dispatch('scenario:started', ctx);
  }

  function stop() {
    state.timers.forEach(clearTimeout);
    state.timers = [];
    state.running = false;
    state.waitingAck = false;
    // 강제로 잡아둔 게이지 값 해제 (정상 자동 갱신 복귀)
    const E = global.INVYONE_ENGINE;
    if (E && E.state) {
      Object.values(SCENARIOS).forEach(s => {
        const g = E.state.gauges[s.targetGauge];
        if (g) g.forced = false;
      });
    }
  }

  // 시연자가 ACK 클릭 → 정상 복귀
  function ackAndResolve() {
    if (!state.running) return;
    const E = global.INVYONE_ENGINE;
    const active = SCENARIO_BW_A1;

    E.emitEvent('[조치완료] 운영자 ACK 수신 — 정상 복귀 절차 진행', 'info');
    const g = E.state.gauges[active.targetGauge];
    if (g) { g.forced = false; g.value = (g.max || 8) * 0.55; E.setGaugeVisual(active.targetGauge); }
    highlightTarget(active.targetComp, false);
    flashStop(active.targetComp);

    dispatch('scenario:resolved', { scenario: active, state });
    stop();
  }

  // ============================================================
  // 실제 작업자 폰 push (siflex.invyone.com/mobile 에 ws 로 연결된 사용자)
  // SCADA_ALARM_TARGET 미지정 시 no-op (로컬 데모 모드)
  // ============================================================
  function pushAlarmToWorker(ctx) {
    const target = (typeof window !== 'undefined' && window.SCADA_ALARM_TARGET) || '';
    if (!target) return;
    const a = ctx.scenario.alarm;
    const body = {
      target_user_id: target,
      alarm: {
        code: a.code,
        severity: a.severity,
        title: ctx.scenario.title,
        message: a.message,
        location: '펌프룸 A · BW-A1 (원수 취수펌프 #1)',
        comp: ctx.scenario.targetComp,
      },
    };
    fetch('/api/demo/alarm/trigger', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(body),
    })
      .then(r => r.json())
      .then(res => {
        const delivered = res && res.data && res.data.delivered_to;
        global.INVYONE_ENGINE.emitEvent(
          delivered > 0
            ? `📱 작업자 폰 알람 전송 완료 (${target}) — ${delivered}건 수신`
            : `📱 작업자 폰 미접속 (${target}) — 알람 큐 없음`,
          delivered > 0 ? 'info' : 'warn'
        );
      })
      .catch(err => {
        global.INVYONE_ENGINE.emitEvent(`📱 폰 알람 전송 실패: ${err.message || err}`, 'warn');
      });
  }

  // ============================================================
  // VISUAL HELPERS (P&ID 안에서)
  // ============================================================
  function highlightTarget(compId, on) {
    const el = document.querySelector(`[data-comp-id="${compId}"]`);
    if (el) el.classList.toggle('scenario-target', on);
  }
  function flashTargetComp(compId) {
    const el = document.querySelector(`[data-comp-id="${compId}"]`);
    if (el) el.classList.add('scenario-flash');
  }
  function flashStop(compId) {
    const el = document.querySelector(`[data-comp-id="${compId}"]`);
    if (el) el.classList.remove('scenario-flash');
  }

  // ============================================================
  // EVENT DISPATCH (scenario.js → ui.js 분리)
  // ============================================================
  function dispatch(name, detail) {
    document.dispatchEvent(new CustomEvent(name, { detail }));
  }

  // ============================================================
  // PUBLIC API
  // ============================================================
  global.INVYONE_SCENARIO = {
    play, stop, ackAndResolve,
    SCENARIOS,
    state,
  };
})(window);
