/** デッドキャットファクトリー — 共通型定義 */

/** 方角。コンベアの搬送方向に使う (0=東, 1=南, 2=西, 3=北)。 */
export const enum Dir {
  East = 0,
  South = 1,
  West = 2,
  North = 3,
}

export const DIR_VEC: ReadonlyArray<readonly [number, number]> = [
  [1, 0],
  [0, 1],
  [-1, 0],
  [0, -1],
];

export type TileKind =
  | 'floor'      // 素の床
  | 'wall'       // 壁 (通行不可)
  | 'intake'     // 資材搬入口
  | 'output'     // 出荷口
  | 'conveyor'   // コンベア
  | 'splitter'   // 分岐機 (スプリッター)
  | 'merger'     // 合流機 (マージャー)
  | 'stocker'    // 一時保管ストッカー (バッファ)
  | 'pallet'     // パレット置き場
  | 'basket'     // カゴ (小型容器・手運び)
  | 'container'  // コンテナ (大型容器・フォークリフト専用)
  | 'handler_post' // 荷役ステーション
  | 'forkdepot'  // フォークリフト詰所
  | 'dock'       // トラックバース
  | 'lab'        // 開発室
  | 'pole'       // 配電盤 (送電)
  | 'generator'  // ディーゼル発電機
  | 'solar'      // 太陽光パネル
  | 'bench'      // 作業台 (汎用・安全)
  | 'lathe'      // 旋盤
  | 'press'      // プレス機
  | 'robot'      // アームロボット
  | 'packer'     // 梱包機
  | 'rest'       // 仮眠クッション (随時の休憩)
  | 'breakroom'  // 休憩室 (定時休憩で集まる部屋)
  | 'office'     // 事務机 (事務室)
  | 'litter'     // トイレ
  | 'scratch'    // 爪とぎタワー
  | 'feeder'     // 自動給餌器
  | 'box'        // 段ボール箱
  | 'boiler';    // ボイラー (立入禁止・暖かい)

/** 置き場の受入モード。特定の加工段階のアイテムだけを受け入れるフィルタ。 */
export type YardMode = 'all' | 'raw' | 'wip' | 'done';

export interface Item {
  id: number;
  /** 素材グレード (0=鉄材 … 3=特殊合金材)。完成に必要な工程数と単価を決める。 */
  grade: number;
  /** 何回加工されたか */
  stage: number;
  /** 加工精度の累計。高グレードほど多く必要になる。 */
  precision: number;
  /** 梱包機を通ったか。通った完成品は単価が上がる。 */
  packed: boolean;
  /** 抜け毛混入などで不良品になったか */
  defective: boolean;
  /** 描画補間用: 前タイルからの移動進捗 0..1 */
  slide: number;
}

export interface Tile {
  kind: TileKind;
  dir: Dir;
  /** キャットウォーク (空中通路) が敷かれているか。猫の動線をモノの動線から分離する。 */
  catwalk: boolean;
  /** コンベア上の積荷 (1タイル1個) */
  cargo: Item | null;
  /** 作業台の入力バッファ / ストッカーの在庫 */
  queue: Item[];
  /** 入力バッファが満杯のまま経過したティック数 (オーバーフロー判定用) */
  fullFor: number;
  /** 作業台の加工進捗 (0..1) */
  progress: number;
  /** 作業台の完成品待避スロット */
  outSlot: Item | null;
  /** 故障中の残りティック。>0 の間は停止。 */
  brokenFor: number;
  /** 作業台に割り当てられた猫のID */
  assigned: number | null;
  /** 搬入口のスポーンクールダウン */
  cooldown: number;
  /** 分岐機の払い出し先ラウンドロビン カーソル */
  rr: number;
  /** ストッカー・パレット置き場・カゴの段数 (1〜3)。段を重ねるほど積めるが崩落しやすい。 */
  tiers: number;
  /** 置き場の受入モード (all: 全て, raw: 材料のみ, wip: 仕掛品のみ, done: 完成品のみ) */
  yardMode: YardMode;
  /** トラックバースに着車しているトラックの積荷。null なら空車待ち。 */
  truck: Item[] | null;
  /** トラックの入替に要する残りティック */
  truckTimer: number;
  /** 爪とぎ・給餌器などの累積使用回数 (日報用) */
  uses: number;
}

export const enum CatState {
  Idle = 'idle',
  GoToBench = 'goto_bench',
  Working = 'working',
  GoToRest = 'goto_rest',
  Resting = 'resting',
  GoToLitter = 'goto_litter',
  UsingLitter = 'using_litter',
  GoToBreak = 'goto_break',
  OnBreak = 'on_break',
  Clerical = 'clerical',
  Driving = 'driving',
  Loading = 'loading',
  GoToPickup = 'goto_pickup',
  Picking = 'picking',
  GoToDropoff = 'goto_dropoff',
  Dropping = 'dropping',
  Research = 'research',
  GoToFeeder = 'goto_feeder',
  Eating = 'eating',
  Sleeping = 'sleeping',
  GoToScratch = 'goto_scratch',
  Scratching = 'scratching',
  Panic = 'panic',
  Rage = 'rage',
  Fighting = 'fighting',
  Boxed = 'boxed',
  OffDuty = 'off_duty',
}

export interface LogisticsRoute {
  /** 搬出元タイルindex (搬入口・機械・カゴ・ストッカーなど) */
  from: number;
  /** 搬入先タイルindex (機械・カゴ・ストッカー・出荷口など) */
  to: number;
}

/** 荷役機材の種類 */
export type HandlerEquipment = 'none' | 'handcart' | 'handfork';

export interface Cat {
  id: number;
  name: string;
  color: string;
  /** 9つの命 (残機) */
  lives: number;
  /** 体力 0..100 — 低下すると居眠り */
  hp: number;
  /** 機嫌 0..100 — 作業環境や空腹で変動 */
  mood: number;
  /** 空腹 0..100 (高いほど空腹) */
  hunger: number;
  /** 尿意 0..100 (高いほど限界) */
  bladder: number;
  /** 退屈 0..100 — 高まると破壊衝動 */
  boredom: number;
  /** 集中力 0..100 — 作業速度と手順遵守率 */
  focus: number;
  /** 記憶力 0..100 — 安全手順を覚えていられるか */
  memory: number;

  x: number;
  y: number;
  state: CatState;
  /** 現在の状態の残り時間 (ティック) */
  stateTimer: number;
  /** 追従中の経路 (タイルindexの配列, 末尾が目的地) */
  path: number[];
  /** 荷役作業員・手すきの猫が手で持っている荷物 (最大HANDLER_CARRY_CAP個) */
  carrying: Item[];
  /** ルート搬送時の指定荷降ろし先タイルindex */
  targetDropoff: number | null;
  /** 割り当てられた持ち場 (作業台または事務机) のタイルindex */
  stationIndex: number | null;
  /** 定時休憩で確保した休憩室のタイルindex */
  breakTile: number | null;
  /** ヘルメット着用中か */
  helmet: boolean;
  /** 八つ当たり対象 (猫ID or タイルindex) */
  rageTargetCat: number | null;
  rageTargetTile: number | null;
  /** 休職中の残り日数 */
  offDutyDays: number;
  /** 休職の理由となった労災の程度 (無傷なら 'none') */
  injury: HarmLevel;
  /** 直近に経路探索に失敗した回数 (動線分断の検知に使う) */
  pathFails: number;
  /** 本日の処理個数 */
  producedToday: number;
  /** 描画用のふらつき位相 */
  wobble: number;
  /** 向いている方角 (描画用) */
  facing: Dir;
  /** 荷役機材 (素手/台車/ハンドフォーク) */
  equipment: HandlerEquipment;
}

export type HazardKind =
  | 'sleep_on_line'   // 稼働ラインの上で就寝
  | 'cross_line'      // 稼働中コンベアの横断
  | 'no_helmet'       // ヘルメット未着用
  | 'boiler_nap'      // 立入禁止のボイラー室で就寝
  | 'scratch_machine' // 工作機械で爪とぎ
  | 'overflow'        // 作業台のオーバーフロー (パニック)
  | 'cable_bite'      // 退屈による配線の噛みちぎり
  | 'cat_punch'       // ネコパンチ・喧嘩
  | 'fur_contamination' // 製品への抜け毛混入
  | 'blocked_route'   // 休憩所・トイレへの動線分断
  | 'no_break'        // 定時休憩が取れない
  | 'paperwork'       // 書類の滞留
  | 'lathe_entangle'  // 旋盤への巻き込まれ
  | 'press_crush'     // プレス機への挟まれ
  | 'robot_strike'    // アームロボットとの接触
  | 'packer_trap'     // 梱包機への閉じ込め
  | 'forklift_run'    // フォークリフトとの接触
  | 'stack_collapse'  // 積み荷の崩落
  | 'truck_load'      // 積み込み作業中の災害
  | 'heavy_lifting'   // 荷役作業中の腰痛・転倒
  | 'blackout';       // 停電

/**
 * 事案の深刻度。物損で止まるか、人身災害（労災）に至るかまでを1本の階段で表す。
 * nearmiss → minor(物損) → injury(軽傷) → serious(重傷) → fatal(死亡)
 */
export type IncidentSeverity = 'nearmiss' | 'minor' | 'injury' | 'serious' | 'fatal';

/** 人身災害の段階。ハザードごとに「ここまで至りうる」上限を持つ。 */
export type HarmLevel = 'none' | 'injury' | 'serious' | 'fatal';

/** 労災としてカウントされる深刻度 */
export type InjurySeverity = 'injury' | 'serious' | 'fatal';

/** 労災としてカウントされる深刻度か */
export function isOccupationalInjury(sev: IncidentSeverity): sev is InjurySeverity {
  return sev === 'injury' || sev === 'serious' || sev === 'fatal';
}

/**
 * 事務作業の対象になる書類。インシデントが起きるたびに1件積まれ、
 * 事務机で処理されると対応するハザードのリスクスコアが下がる。
 */
export interface PaperDoc {
  kind: HazardKind;
  severity: IncidentSeverity;
  /** 起票された日 */
  day: number;
}

export interface Incident {
  day: number;
  tick: number;
  kind: HazardKind;
  severity: IncidentSeverity;
  catId: number | null;
  tileIndex: number | null;
  text: string;
  /** 金銭的損害 (治療費・補償を含む) */
  cost: number;
}

/** フォークリフト。パレットやコンテナを積んでトラックバースまで運ぶ。 */
export interface Forklift {
  id: number;
  /** 詰所のタイルindex */
  depot: number;
  /** 運転している猫のID。null なら詰所で停車。 */
  driver: number | null;
  x: number;
  y: number;
  facing: Dir;
  state: 'parked' | 'to_pallet' | 'to_container' | 'to_dock' | 'returning';
  path: number[];
  /** 積んでいるパレット/コンテナの中身 */
  load: Item[];
  /** 目的地のタイルindex */
  target: number | null;
  /** 荷役中の残りティック */
  busy: number;
}

export const enum Phase {
  Plan = 'plan',
  Do = 'do',
  Check = 'check',
  Action = 'action',
  GameOver = 'gameover',
}

export interface DailyReport {
  day: number;
  /** シフト終了時点の工場ランク (達成済みマイルストーン数) */
  rank: number;
  /** この日に達成したマイルストーンのID */
  milestoneAchieved: string | null;
  shipped: number;
  defects: number;
  revenue: number;
  wages: number;
  utilities: number;
  damages: number;
  /** 未処理書類の是正費用 */
  fines: number;
  net: number;
  /** その日に処理した書類の数 */
  paperworkDone: number;
  /** 翌日へ持ち越した未処理書類 */
  paperworkLeft: number;
  /** 定時休憩の長さ (ティック) */
  breakTicks: number;
  /** 本日の労災件数 */
  injuries: { injury: number; serious: number; fatal: number };
  /** 労災の治療費・補償の合計 */
  compensation: number;
  /** 終業時点の無災害連続日数 */
  safeDays: number;
  /** 本日出発したトラックの台数 */
  truckDepartures: number;
  /** フォークリフトが運んだパレットの枚数 */
  palletsHauled: number;
  /** 荷役作業員が運んだカゴ荷役の回数/個数 */
  basketsHandled: number;
  /** フォークリフトが運んだコンテナ数 */
  containersHauled: number;
  /** その日に得た研究ポイント */
  research: number;
  /** 電力の需要と供給 */
  power: { demand: number; supply: number };
  /** 自家発電の燃料費 */
  fuel: number;
  /** 素材の調達費 */
  materialCost: number;
  incidents: Incident[];
  /** ハザード種別ごとの発生数 */
  hazardCounts: Record<HazardKind, number>;
  catSummaries: Array<{
    id: number;
    name: string;
    produced: number;
    mood: number;
    hp: number;
    lives: number;
    offDuty: boolean;
    /** 休業の原因になった労災の程度 */
    injury: HarmLevel;
    /** 事務机に付いていたか */
    clerical: boolean;
  }>;
}
