/**
 * 事案が起きたときにワールドへ反映する実害。
 * 物損で止まる場合と、人身災害（労災）に至った場合で扱いを分けている。
 */
import { HARM_RULES, machineDef } from '../core/config';
import { CatState, type Cat, type HazardKind, type IncidentSeverity } from '../core/types';
import { pushLog, type GameState } from './state';

/** 労災の程度に応じて、休業・補償・9つの命の消費を適用する。 */
export function applyInjury(
  s: GameState,
  cat: Cat,
  severity: 'injury' | 'serious' | 'fatal',
  tileIndex: number | null,
  breakTicks: number,
): void {
  const rule = HARM_RULES[severity];

  cat.injury = severity;
  cat.offDutyDays = s.rng.int(rule.offDuty[0], rule.offDuty[1]);
  cat.state = CatState.OffDuty;
  cat.path = [];
  cat.breakTile = null;
  s.trust = Math.max(0, s.trust - rule.trustLoss);

  if (severity === 'injury') {
    cat.hp = 25;
    cat.mood = Math.max(0, cat.mood - 20);
  } else if (severity === 'serious') {
    cat.hp = 15;
    cat.mood = Math.max(0, cat.mood - 35);
  } else {
    cat.hp = 40;
    cat.mood = 40;
  }

  // 労災が起きた設備は調査のため停止する
  if (tileIndex !== null && machineDef(s.tiles[tileIndex].kind)) {
    s.tiles[tileIndex].brokenFor = breakTicks * (severity === 'fatal' ? 2 : 1);
  }

  if (rule.costsLife) {
    cat.lives = Math.max(0, cat.lives - 1);
    if (cat.lives <= 0) {
      pushLog(
        s,
        `${cat.name} は9つの命を使い切りました。もう工場には戻れません`,
        'danger',
      );
      cat.offDutyDays = 9999;
    } else {
      pushLog(
        s,
        `${cat.name} は9つの命を1つ消費して復帰します（残り ${cat.lives}）。休業 ${cat.offDutyDays}日`,
        'danger',
      );
    }
  } else {
    pushLog(
      s,
      `${cat.name} は${rule.label}のため ${cat.offDutyDays}日間の休業となりました`,
      'danger',
    );
  }
}

/** 人身に至らなかった物損事故の実害。 */
export function applyPropertyDamage(
  s: GameState,
  kind: HazardKind,
  severity: IncidentSeverity,
  cat: Cat | null,
  tileIndex: number | null,
  breakTicks: number,
): void {
  if (severity !== 'minor') return;

  switch (kind) {
    case 'cable_bite':
    case 'scratch_machine': {
      if (tileIndex !== null && machineDef(s.tiles[tileIndex].kind)) {
        s.tiles[tileIndex].brokenFor = breakTicks;
      }
      if (cat) cat.boredom = 0;
      break;
    }

    case 'lathe_entangle':
    case 'press_crush':
    case 'robot_strike':
    case 'packer_trap': {
      // 人身に至らなくても機械は止まり、担当は肝を冷やす
      if (tileIndex !== null) s.tiles[tileIndex].brokenFor = breakTicks;
      if (cat) {
        cat.mood = Math.max(0, cat.mood - 18);
        cat.state = CatState.Panic;
        cat.stateTimer = 160;
      }
      break;
    }

    case 'sleep_on_line': {
      if (cat) {
        cat.hp = Math.max(5, cat.hp - 35);
        cat.mood = Math.max(0, cat.mood - 30);
        cat.state = CatState.Panic;
        cat.stateTimer = 180;
      }
      break;
    }

    case 'overflow': {
      if (cat) {
        // 威嚇して作業を放棄するが、クールダウンより短く復帰させて
        // 「パニック → さらに滞留 → またパニック」の無限ループを避ける
        cat.state = CatState.Panic;
        cat.stateTimer = 140;
        cat.mood = Math.max(0, cat.mood - 12);
      }
      break;
    }

    case 'cat_punch': {
      if (cat) {
        cat.state = CatState.Fighting;
        cat.stateTimer = 200;
        cat.mood = Math.max(0, cat.mood - 10);
      }
      break;
    }

    case 'cross_line':
    case 'fur_contamination': {
      if (tileIndex !== null && s.tiles[tileIndex].cargo) {
        s.tiles[tileIndex].cargo!.defective = true;
      }
      break;
    }

    case 'blocked_route': {
      if (cat) {
        cat.mood = Math.max(0, cat.mood - 25);
        cat.state = CatState.Rage;
        cat.stateTimer = 200;
      }
      break;
    }

    case 'no_helmet': {
      if (cat) cat.hp = Math.max(5, cat.hp - 20);
      break;
    }

    case 'no_break': {
      if (cat) {
        cat.mood = Math.max(0, cat.mood - 22);
        cat.state = CatState.Rage;
        cat.stateTimer = 160;
      }
      break;
    }

    case 'paperwork': {
      // 書類の不備は現場ではなく信頼度に効く
      s.trust = Math.max(0, s.trust - 3);
      break;
    }

    case 'boiler_nap': {
      if (tileIndex !== null) s.tiles[tileIndex].brokenFor = breakTicks;
      if (cat) cat.hp = Math.max(5, cat.hp - 25);
      break;
    }
  }
}
