/**
 * シルギア 地方公共団体コードAPI v1 の型定義
 * https://api.shirugear.com/lgcode/
 *
 * 互換の方針: v1 の中では項目を「足す」ことはあっても、名前や意味は変えません。
 * 知らない項目が増えていても無視してください。
 */

/**
 * 団体の種類。
 * prefecture=都道府県 / designated_city=政令指定都市 / ward=政令指定都市の区（行政区）/
 * special_ward=特別区（東京23区）/ city=市（政令指定都市を除く）/ town=町 / village=村
 */
export type LgKind = "prefecture" | "designated_city" | "ward" | "special_ward" | "city" | "town" | "village";

/**
 * 変更の理由。
 * absorption=編入合併 / new_merger=新設合併 / city_status=市制施行 / town_status=町制施行 /
 * rename=名称変更 / designated_city=政令指定都市への移行 / ward_established=区の設置 /
 * ward_split=分区 / ward_division=区の分割 / ward_reorganization=区の再編 /
 * district_change=郡・支庁の区域の変更 / okinawa_reversion=沖縄の本土復帰 / other=その他
 */
export type LgReason =
  | "absorption"
  | "new_merger"
  | "city_status"
  | "town_status"
  | "rename"
  | "designated_city"
  | "ward_established"
  | "ward_split"
  | "ward_division"
  | "ward_reorganization"
  | "district_change"
  | "okinawa_reversion"
  | "other";

/** コードと名前（名前はその時点のもの） */
export interface LgRef {
  /** 5桁 */
  code: string;
  name: string;
}

/** 今のコード */
export interface LgCurrentRef extends LgRef {
  kind: LgKind;
}

/** 名前の移り変わり（1970年4月1日以降） */
export interface LgNamePeriod {
  name: string;
  /** 全角カタカナ */
  name_kana: string;
  /** その名前になった日。記録の始まり（1970年4月1日）より前からなら null */
  from: string | null;
  /** その名前でなくなった日（この日から次の名前） */
  until: string | null;
}

/** コードができたとき（1970年4月1日より前からあるコードでは null） */
export interface LgEstablished {
  /** "YYYY-MM-DD" */
  date: string;
  reason: LgReason;
  /** 「新設合併」など（説明文。言い回しが変わることがある） */
  reason_label: string;
  /** e-Stat（標準地域コード）の説明文 */
  description: string;
  /** 元になったコード（その日の直前の名前） */
  from: LgRef[];
}

/** コードが廃止されたとき */
export interface LgAbolished {
  /** 廃止された日（この日から移った先のコード）"YYYY-MM-DD" */
  date: string;
  reason: LgReason;
  reason_label: string;
  description: string;
  /** 移った先のコード（その日の名前）。分割された場合などは複数 */
  to: LgRef[];
}

/** 同じコードを以前に使っていた、別の（廃止された）団体 */
export interface LgPreviousUse {
  name: string;
  name_kana: string;
  kind: LgKind;
  kind_label: string;
  district: string | null;
  parent: LgRef | null;
  valid_from: string | null;
  valid_until: string;
  established: LgEstablished | null;
  abolished: LgAbolished;
  current_codes: LgCurrentRef[];
  former_names: LgNamePeriod[];
}

/** GET /lgcode/v1/{5桁 または 検査数字付き6桁}.json */
export interface LgCodeResponse {
  /** 5桁 */
  code: string;
  /** 検査数字付きの6桁 */
  code6: string;
  /** 検査数字（6桁目） */
  check_digit: string;
  /** 名前。政令指定都市の区は「札幌市中央区」のように市の名前から。町村に郡の名前は付かない */
  name: string;
  /** 全角カタカナ（政令指定都市の区は市の読みから） */
  name_kana: string;
  kind: LgKind;
  kind_label: string;
  /** 都道府県コード（2桁） */
  prefcode: string;
  prefecture: string;
  prefecture_kana: string;
  /** 町村の属する郡（例: "南佐久郡"）。町村以外と北方領土の村は null */
  district: string | null;
  /** 政令指定都市の区なら、その市 */
  parent: LgRef | null;
  /** 今も使われているコードか */
  current: boolean;
  /** このコードが使われ始めた日。1970年4月1日より前からなら null */
  valid_from: string | null;
  /** 廃止された日。今も使われていれば null */
  valid_until: string | null;
  established: LgEstablished | null;
  /** 廃止されたコードのときだけ。今のコードでは null */
  abolished: LgAbolished | null;
  /**
   * 今のコード。今も使われていれば自分自身。廃止されたコードは、何段も合併していても最後までたどった今のコード
   * （分かれて移った場合は複数。政令指定都市に移ったものは市のコード）
   */
  current_codes: LgCurrentRef[];
  /** 以前の名前（古い順。今の名前は含まない） */
  former_names: LgNamePeriod[];
  /** 同じコードを以前に使っていた別の団体（ほとんどのコードでは []） */
  previous_uses: LgPreviousUse[];
  /** 郵便番号API の市区町村の町域一覧の URL（例: "/zip/v1/city/13101.json"）。無ければ null */
  zip_city: string | null;
  /** 補足（北方領土の村など）。無ければ null */
  note: string | null;
  /** 総務省の一覧の版 "YYYY-MM-DD"（その日現在） */
  data_version: string;
}

/** 一覧の1件 */
export interface LgSummary {
  code: string;
  code6: string;
  name: string;
  name_kana: string;
  kind: LgKind;
  district: string | null;
  /** 政令指定都市の区なら市のコード */
  parent_code: string | null;
}

/** GET /lgcode/v1/pref.json の1件 */
export interface LgPrefItem {
  prefcode: string;
  /** 都道府県の5桁コード（"13000"） */
  code: string;
  code6: string;
  name: string;
  name_kana: string;
  /** その都道府県の今の市区町村の数（pref/{2桁}.json の count と同じ） */
  count: number;
  /** その都道府県の一覧の URL（"/lgcode/v1/pref/13.json"） */
  url: string;
}

/** GET /lgcode/v1/pref.json */
export interface LgPrefListResponse {
  count: number;
  /** 47都道府県。コードの順 */
  prefectures: LgPrefItem[];
  data_version: string;
}

/** GET /lgcode/v1/pref/{都道府県コード2桁}.json */
export interface LgPrefResponse {
  prefcode: string;
  /** 都道府県の5桁コード（"13000"） */
  code: string;
  code6: string;
  prefecture: string;
  prefecture_kana: string;
  count: number;
  /** 今の市区町村（政令指定都市とその区・特別区を含む）。コードの順 */
  municipalities: LgSummary[];
  data_version: string;
}

/** GET /lgcode/v1/all.json */
export interface LgAllResponse {
  count: number;
  /** 都道府県と今の市区町村のすべて。コードの順 */
  items: Array<LgSummary & { prefcode: string; prefecture: string }>;
  data_version: string;
}

/** changes の1件（同じ日・同じ理由でまとめて行われた1つの変更） */
export interface LgChange {
  date: string;
  reason: LgReason;
  reason_label: string;
  description: string;
  /** この変更でなくなったコードと、移った先のコード */
  abolished: Array<LgRef & { to: string[] }>;
  /** この変更でできたコード */
  established: LgRef[];
  /** コードは変わらずに関わった団体（編入した側の市・名前が変わった町など）。名前が変わったときは name_before */
  continued: Array<LgRef & { name_before?: string }>;
}

/** GET /lgcode/v1/changes.json */
export interface LgChangesResponse {
  /** 記録の始まり "1970-04-01" */
  from: string;
  count: number;
  /** 古い順 */
  changes: LgChange[];
  data_version: string;
}

/** GET /lgcode/v1/meta.json */
export interface LgMetaResponse {
  data_version: string;
  /** データを作った日時（ISO 8601・UTC） */
  built_at: string;
  source: string;
  sources: Array<{ name: string; url: string; page?: string; as_of?: string; fetched_at?: string }>;
  history: { from: string; latest_change: string | null };
  counts: {
    /** 今の団体の数（都道府県・政令指定都市の区・北方領土の村を含む） */
    current: number;
    prefectures: number;
    designated_cities: number;
    /** 政令指定都市を除く市 */
    cities: number;
    special_wards: number;
    wards: number;
    towns: number;
    /** 北方領土の6村を除く */
    villages: number;
    northern_territory_villages: number;
    /** 市町村の数（政令指定都市を含む市＋町＋村。特別区・区・北方領土の村を除く） */
    municipalities: number;
    /** 廃止されたコードの数 */
    abolished_codes: number;
    /** changes の件数 */
    changes: number;
  };
}

/** エラーのときの本文 */
export interface ErrorResponse {
  error: {
    status: 400 | 404 | 405;
    code: "invalid_lgcode" | "invalid_check_digit" | "lgcode_not_found" | "not_found" | "method_not_allowed";
    message: string;
  };
}
