// Master Data DTOs (docs/11-BACKEND-PHASE1.md §2; FR-MD-01..11).
// Mirrors the backend DTOs exactly — the API contract is the source of truth (docs/20 §1).
import { EntityStatus } from "@/types/common"

/**
 * Whether an item holds stock. Renamed from `ItemType` on 2026-07-16 (docs/11 §8): the
 * name `ItemType` now means a *dimension master* (Color/Size), which is a different
 * concept entirely — see {@link ItemType} below.
 */
export type StockNature = "Stocked" | "NonStocked" | "Service"
export type TrackingMode = "None" | "Batch" | "Serial"
export type Warranty = "NonWarranty" | "Warranty"

/** Warranty coverage lengths offered when an item is marked Warranty. */
export const WARRANTY_PERIOD_MONTHS_OPTIONS = [3, 6, 12, 18] as const
export type WarrantyPeriodMonths = (typeof WARRANTY_PERIOD_MONTHS_OPTIONS)[number]

/**
 * Unit of an item's content size — how much one stocked pack holds.
 *
 * Not a stocking unit: stock is always counted in packs (`baseUomId`). Only `Ml` and `G`
 * are ever returned as a *base* content unit; `L` and `Kg` are entry conveniences the
 * server normalises ×1000 on write.
 */
export type MeasureUnit = "Ml" | "L" | "G" | "Kg"

/** The four content fields, which are always all set or all null. */
export interface ItemContent {
  /** Content per pack as entered, e.g. 500 with `Ml`, or 1.5 with `L`. */
  contentQty: number | null
  contentUnit: MeasureUnit | null
  /** Server-derived normalisation of the pair above; never sent on write. */
  contentBaseQty: number | null
  contentBaseUnit: MeasureUnit | null
}

export interface ItemListItem extends ItemContent {
  itemId: number
  sku: string
  name: string
  categoryId: number
  subCategoryId: number | null
  brandId: number | null
  baseUomId: number
  defaultVendorId: number | null
  stockNature: StockNature
  trackingMode: TrackingMode
  warranty: Warranty
  /** Coverage length in months; set when `warranty` is `"Warranty"`, null otherwise. */
  warrantyPeriodMonths: WarrantyPeriodMonths | null
  taxClass: string | null
  /** Fixed sale price (Sales only); null ⇒ sell at stock/FIFO value. */
  salePrice: number | null
  status: EntityStatus
}

export interface ItemReorderSetting {
  warehouseId: number
  reorderPoint: number
  reorderQty: number
}

/**
 * Full Item resource (docs/11 §2.1 `GET /items/{itemId}`).
 *
 * Note there is no item-type field: the values chosen in the builder are encoded into the
 * client-generated `sku` and never stored server-side (docs/10 Part C.9). The SKU is the
 * only record of which colour/size an item is.
 */
export interface Item extends ItemContent {
  itemId: number
  sku: string
  name: string
  description: string | null
  categoryId: number
  /** Optional second level; must belong to `categoryId` or the server returns 422. */
  subCategoryId: number | null
  brandId: number | null
  baseUomId: number
  defaultVendorId: number | null
  stockNature: StockNature
  trackingMode: TrackingMode
  warranty: Warranty
  /** Coverage length in months; set when `warranty` is `"Warranty"`, null otherwise. */
  warrantyPeriodMonths: WarrantyPeriodMonths | null
  taxClass: string | null
  /** Fixed sale price (Sales only); null ⇒ sell at stock/FIFO value. */
  salePrice: number | null
  status: EntityStatus
  reorder: ItemReorderSetting[]
  createdAt: string
  updatedAt: string | null
}

export interface CreateItemRequest {
  /** Client-generated; the server only enforces uniqueness (`SKU_DUPLICATE`). */
  sku: string
  name: string
  description?: string | null
  categoryId: number
  /** Rejected with `CONFIG_DISABLED` when subcategories are switched off (docs/11 §2.8). */
  subCategoryId?: number | null
  /** Rejected with `CONFIG_DISABLED` when brands are switched off. */
  brandId?: number | null
  baseUomId: number
  defaultVendorId?: number | null
  stockNature: StockNature
  trackingMode: TrackingMode
  /** Defaults to `NonWarranty` server-side when omitted. */
  warranty?: Warranty
  /** Required (one of `WARRANTY_PERIOD_MONTHS_OPTIONS`) when `warranty` is `"Warranty"`; ignored otherwise. */
  warrantyPeriodMonths?: WarrantyPeriodMonths | null
  taxClass?: string | null
  /** Optional fixed sale price (Sales only). Null/omitted ⇒ sell at stock/FIFO value. */
  salePrice?: number | null
  /**
   * Content per pack. Send both or neither — a half-filled pair is a 422. The base pair is
   * derived server-side and is deliberately not accepted here.
   */
  contentQty?: number | null
  contentUnit?: MeasureUnit | null
}

export type UpdateItemRequest = CreateItemRequest

export interface UpdateItemReorderRequest {
  settings: ItemReorderSetting[]
}

export interface Warehouse {
  warehouseId: number
  code: string
  name: string
}

export interface CreateWarehouseRequest {
  code: string
  name: string
}

export interface Bin {
  binId: number
  warehouseId: number
  code: string
  binType: string | null
}

export interface CreateBinRequest {
  code: string
  binType?: string | null
}

export interface Vendor {
  vendorId: number
  code: string
  name: string
  terms: string | null
  taxReg: string | null
  currency: string
  status: EntityStatus
  createdAt: string
  updatedAt: string | null
}

export interface CreateVendorRequest {
  code: string
  name: string
  terms?: string | null
  taxReg?: string | null
  currency: string
}

export type UpdateVendorRequest = CreateVendorRequest

export interface Uom {
  uomId: number
  name: string
}

export interface CreateUomRequest {
  name: string
}

// Category / SubCategory — a fixed two-level hierarchy. Categories no longer self-nest:
// `parentId` and `GET /categories?tree=true` were removed on 2026-07-16 (docs/11 §2.3).

export interface Category {
  categoryId: number
  name: string
  status: EntityStatus
  createdAt: string
  updatedAt: string | null
}

export interface CreateCategoryRequest {
  name: string
}

export interface UpdateCategoryRequest {
  name: string
}

export interface SubCategory {
  subCategoryId: number
  categoryId: number
  name: string
  status: EntityStatus
  createdAt: string
  updatedAt: string | null
}

export interface CreateSubCategoryRequest {
  name: string
}

/** Name only — a subcategory cannot be reparented (docs/11 §2.3). */
export interface UpdateSubCategoryRequest {
  name: string
}

export interface Brand {
  brandId: number
  name: string
  status: EntityStatus
  createdAt: string
  updatedAt: string | null
}

export interface CreateBrandRequest {
  name: string
}

export interface UpdateBrandRequest {
  name: string
}

/**
 * Item type master (docs/11 §2.7) — a dimension *name* such as Color, Size or Material.
 * Formerly `VariantCategory` in this app.
 *
 * Nothing links an item to one of these, and the chosen values are baked into the SKU
 * client-side. It is no longer *only* a dropdown source, though: `isMeasurable` changes how
 * the builder captures values. Not to be confused with {@link StockNature}, which is what
 * the old `itemType` enum became.
 */
export interface ItemType {
  itemTypeId: number
  name: string
  /**
   * True ⇒ this dimension's values are content measurements (500 ml, 1 L), so the builder
   * captures a number + unit per value and writes it to each generated item's content size.
   * False ⇒ plain labels (Red, S) — which is what an apparel "Size" wants.
   */
  isMeasurable: boolean
  status: EntityStatus
  createdAt: string
  updatedAt: string | null
}

export interface CreateItemTypeRequest {
  name: string
  /** Omitted ⇒ false. */
  isMeasurable?: boolean
}

export interface UpdateItemTypeRequest {
  name: string
  /** Omitted ⇒ the stored value is preserved. Always send it from a form that shows it. */
  isMeasurable?: boolean
}

/**
 * Product configuration (docs/11 §2.8) — singleton feature gate.
 *
 * `subcategoriesEnabled`/`brandsEnabled` are enforced server-side (`CONFIG_DISABLED` on
 * item writes). `itemTypesEnabled` is **advisory**: items carry no item-type reference, so
 * there is nothing for the server to reject — the frontend is what honours it by hiding
 * the builder's type section.
 */
export interface ProductConfig {
  subcategoriesEnabled: boolean
  brandsEnabled: boolean
  itemTypesEnabled: boolean
  updatedAt: string | null
  updatedBy: number | null
}

/** All three flags are required: an omitted flag is a 400, never a silent disable. */
export interface UpdateProductConfigRequest {
  subcategoriesEnabled: boolean
  brandsEnabled: boolean
  itemTypesEnabled: boolean
}
