import { CatalogCrudConfig, CatalogLookupData, CatalogOption } from '../../../models/catalog-crud.model';
import { CategoryProductSale } from '../../../models/category-product-sale.model';
import { ExpenseCategory } from '../../../models/expense-category.model';
import { ExpenseCenter } from '../../../models/expense-center.model';
import { InventoryCategory } from '../../../models/inventory-category.model';
import { InventoryItem } from '../../../models/inventory-item.model';
import { InventoryLocation } from '../../../models/inventory-location.model';
import { InventorySupplier } from '../../../models/inventory-supplier.model';
import { InventoryUnit } from '../../../models/inventory-unit.model';
import { ProductSale } from '../../../models/product-sale.model';

const expenseCenterTypeOptions: CatalogOption[] = [
  { label: 'Planta', value: 'PLANT' },
  { label: 'Oficina', value: 'OFFICE' },
  { label: 'Ruta', value: 'ROUTE' },
  { label: 'Administracion', value: 'ADMINISTRATION' },
  { label: 'General', value: 'GENERAL' },
  { label: 'Otro', value: 'OTHER' }
];

const inventoryItemTypeOptions: CatalogOption[] = [
  { label: 'Materia prima', value: 'RAW_MATERIAL' },
  { label: 'Empaque', value: 'PACKAGING' },
  { label: 'Envase retornable', value: 'RETURNABLE_CONTAINER' },
  { label: 'Producto terminado', value: 'FINISHED_GOOD' },
  { label: 'Suministro', value: 'SUPPLY' }
];

const inventoryLocationTypeOptions: CatalogOption[] = [
  { label: 'Planta', value: 'PLANT' },
  { label: 'Almacen', value: 'WAREHOUSE' },
  { label: 'Sucursal', value: 'BRANCH' },
  { label: 'Vehiculo', value: 'VEHICLE' }
];

const inventoryUnitTypeOptions: CatalogOption[] = [
  { label: 'Conteo', value: 'COUNT' },
  { label: 'Volumen', value: 'VOLUME' },
  { label: 'Peso', value: 'WEIGHT' },
  { label: 'Longitud', value: 'LENGTH' }
];

function valueOrDash(value: unknown, fallback = 'Sin dato'): string {
  if (value === null || value === undefined || value === '') {
    return fallback;
  }

  return String(value);
}

function asCurrency(value: unknown): string {
  const amount = Number(value ?? 0);
  return new Intl.NumberFormat('es-MX', {
    style: 'currency',
    currency: 'MXN',
    minimumFractionDigits: 2
  }).format(Number.isFinite(amount) ? amount : 0);
}

function trimString(value: unknown): string {
  return String(value ?? '').trim();
}

function optionalString(value: unknown): string | undefined {
  const trimmed = trimString(value);
  return trimmed ? trimmed : undefined;
}

function requiredNumber(value: unknown): number {
  return Number(value);
}

function optionalNumber(value: unknown): number | undefined {
  if (value === null || value === undefined || value === '') {
    return undefined;
  }

  const parsed = Number(value);
  return Number.isFinite(parsed) ? parsed : undefined;
}

function findLookupLabel(
  lookupData: CatalogLookupData,
  lookupKey: string,
  id: unknown,
  fallback: string
): string {
  const entries = lookupData[lookupKey] ?? [];
  const match = entries.find(entry => Number(entry['id']) === Number(id));
  return valueOrDash(match?.['name'], fallback);
}

function removeUndefined(payload: Record<string, unknown>): Record<string, unknown> {
  return Object.fromEntries(Object.entries(payload).filter(([, value]) => value !== undefined));
}

export const catalogCrudConfigMap: Record<string, CatalogCrudConfig<any>> = {
  saleCategories: {
    key: 'saleCategories',
    title: 'Categorias de producto de venta',
    singular: 'categoria',
    description: 'Clasifica los productos que se venden al cliente final.',
    endpoint: '/category-product-sale',
    createButtonLabel: 'Agregar categoria',
    emptyMessage: 'No hay categorias de producto de venta registradas.',
    searchPlaceholder: 'Buscar por nombre o descripcion',
    searchKeys: ['name', 'description'],
    updateMethod: 'PATCH',
    columns: [
      { key: 'name', label: 'Nombre' },
      { key: 'description', label: 'Descripcion' }
    ],
    fields: [
      { key: 'name', label: 'Nombre', type: 'text', required: true, placeholder: 'Bebidas, Garrafones, etc.' },
      { key: 'description', label: 'Descripcion', type: 'textarea', placeholder: 'Descripcion opcional' }
    ],
    toPayload: rawValue =>
      removeUndefined({
        name: trimString(rawValue['name']),
        description: optionalString(rawValue['description'])
      }),
    toTableRow: (entity: CategoryProductSale) => ({
      name: entity.name,
      description: valueOrDash(entity.description)
    })
  },
  productSales: {
    key: 'productSales',
    title: 'Productos de venta',
    singular: 'producto de venta',
    description: 'Catalogo de productos comercializables. Se mantiene separado del inventario interno.',
    endpoint: '/product-sales',
    createButtonLabel: 'Agregar producto',
    emptyMessage: 'No hay productos de venta registrados.',
    searchPlaceholder: 'Buscar por nombre, marca, tipo o categoria',
    searchKeys: ['name', 'description', 'brand', 'type'],
    columns: [
      { key: 'name', label: 'Nombre' },
      { key: 'price', label: 'Precio' },
      { key: 'category', label: 'Categoria' },
      { key: 'type', label: 'Tipo' },
      { key: 'inventoryItem', label: 'Articulo ligado' }
    ],
    fields: [
      { key: 'name', label: 'Nombre', type: 'text', required: true, placeholder: 'Garrafon 20L' },
      { key: 'description', label: 'Descripcion', type: 'textarea', placeholder: 'Descripcion opcional' },
      { key: 'brand', label: 'Marca', type: 'text', placeholder: 'Marca o linea' },
      { key: 'type', label: 'Tipo', type: 'text', placeholder: 'Presentacion o familia' },
      { key: 'price', label: 'Precio', type: 'number', required: true, min: 0, placeholder: '0.00' },
      {
        key: 'categoryProductSaleId',
        label: 'Categoria',
        type: 'select',
        required: true,
        lookupKey: 'saleCategories',
        placeholder: 'Selecciona una categoria'
      },
      {
        key: 'inventoryItemId',
        label: 'Articulo de inventario ligado',
        type: 'select',
        lookupKey: 'inventoryItems',
        placeholder: 'Opcional'
      }
    ],
    lookups: [
      { key: 'saleCategories', endpoint: '/category-product-sale' },
      { key: 'inventoryItems', endpoint: '/inventory/items' }
    ],
    toPayload: rawValue =>
      removeUndefined({
        name: trimString(rawValue['name']),
        description: optionalString(rawValue['description']),
        brand: optionalString(rawValue['brand']),
        type: optionalString(rawValue['type']),
        price: requiredNumber(rawValue['price']),
        categoryProductSaleId: requiredNumber(rawValue['categoryProductSaleId']),
        inventoryItemId: optionalNumber(rawValue['inventoryItemId'])
      }),
    toTableRow: (entity: ProductSale, lookupData) => ({
      name: entity.name,
      price: asCurrency(entity.price),
      category: findLookupLabel(lookupData, 'saleCategories', entity.categoryProductSaleId, 'Sin categoria'),
      type: valueOrDash(entity.type),
      inventoryItem: findLookupLabel(lookupData, 'inventoryItems', entity.inventoryItemId, 'Sin ligar')
    })
  },
  inventoryCategories: {
    key: 'inventoryCategories',
    title: 'Categorias de inventario',
    singular: 'categoria de inventario',
    description: 'Organiza los articulos de inventario por familia o uso.',
    endpoint: '/inventory/categories',
    createButtonLabel: 'Agregar categoria',
    emptyMessage: 'No hay categorias de inventario registradas.',
    searchPlaceholder: 'Buscar por nombre o descripcion',
    searchKeys: ['name', 'description'],
    columns: [
      { key: 'name', label: 'Nombre' },
      { key: 'description', label: 'Descripcion' }
    ],
    fields: [
      { key: 'name', label: 'Nombre', type: 'text', required: true, placeholder: 'Envases, Refacciones, etc.' },
      { key: 'description', label: 'Descripcion', type: 'textarea', placeholder: 'Descripcion opcional' }
    ],
    toPayload: rawValue =>
      removeUndefined({
        name: trimString(rawValue['name']),
        description: optionalString(rawValue['description'])
      }),
    toTableRow: (entity: InventoryCategory) => ({
      name: entity.name,
      description: valueOrDash(entity.description)
    })
  },
  inventoryUnits: {
    key: 'inventoryUnits',
    title: 'Unidades de inventario',
    singular: 'unidad',
    description: 'Define las unidades de medida del inventario.',
    endpoint: '/inventory/units',
    createButtonLabel: 'Agregar unidad',
    emptyMessage: 'No hay unidades de inventario registradas.',
    searchPlaceholder: 'Buscar por nombre, abreviatura o tipo',
    searchKeys: ['name', 'abbreviation', 'type'],
    columns: [
      { key: 'name', label: 'Nombre' },
      { key: 'abbreviation', label: 'Abreviatura' },
      { key: 'type', label: 'Tipo' }
    ],
    fields: [
      { key: 'name', label: 'Nombre', type: 'text', required: true, placeholder: 'Kilogramo' },
      { key: 'abbreviation', label: 'Abreviatura', type: 'text', placeholder: 'kg, pza, lt...' },
      {
        key: 'type',
        label: 'Tipo',
        type: 'select',
        required: true,
        options: inventoryUnitTypeOptions,
        placeholder: 'Selecciona un tipo'
      }
    ],
    toPayload: rawValue =>
      removeUndefined({
        name: trimString(rawValue['name']),
        abbreviation: optionalString(rawValue['abbreviation']),
        type: trimString(rawValue['type'])
      }),
    toTableRow: (entity: InventoryUnit) => ({
      name: entity.name,
      abbreviation: valueOrDash(entity.abbreviation),
      type: valueOrDash(entity.type)
    })
  },
  inventoryLocations: {
    key: 'inventoryLocations',
    title: 'Ubicaciones de inventario',
    singular: 'ubicacion',
    description: 'Ubicaciones fisicas donde se resguarda inventario.',
    endpoint: '/inventory/locations',
    createButtonLabel: 'Agregar ubicacion',
    emptyMessage: 'No hay ubicaciones de inventario registradas.',
    searchPlaceholder: 'Buscar por nombre, tipo o descripcion',
    searchKeys: ['name', 'type', 'description'],
    columns: [
      { key: 'name', label: 'Nombre' },
      { key: 'type', label: 'Tipo' },
      { key: 'description', label: 'Descripcion' }
    ],
    fields: [
      { key: 'name', label: 'Nombre', type: 'text', required: true, placeholder: 'Almacen principal' },
      {
        key: 'type',
        label: 'Tipo',
        type: 'select',
        required: true,
        options: inventoryLocationTypeOptions,
        placeholder: 'Selecciona un tipo'
      },
      { key: 'description', label: 'Descripcion', type: 'textarea', placeholder: 'Descripcion opcional' }
    ],
    toPayload: rawValue =>
      removeUndefined({
        name: trimString(rawValue['name']),
        type: trimString(rawValue['type']),
        description: optionalString(rawValue['description'])
      }),
    toTableRow: (entity: InventoryLocation) => ({
      name: entity.name,
      type: valueOrDash(entity.type),
      description: valueOrDash(entity.description)
    })
  },
  inventorySuppliers: {
    key: 'inventorySuppliers',
    title: 'Proveedores de inventario',
    singular: 'proveedor',
    description: 'Proveedores usados en compras y abastecimiento de inventario.',
    endpoint: '/inventory/suppliers',
    createButtonLabel: 'Agregar proveedor',
    emptyMessage: 'No hay proveedores de inventario registrados.',
    searchPlaceholder: 'Buscar por nombre o telefono',
    searchKeys: ['name', 'phoneNumber'],
    columns: [
      { key: 'name', label: 'Nombre' },
      { key: 'phoneNumber', label: 'Telefono' }
    ],
    fields: [
      { key: 'name', label: 'Nombre', type: 'text', required: true, placeholder: 'Proveedor del Norte' },
      { key: 'phoneNumber', label: 'Telefono', type: 'text', placeholder: 'Telefono de contacto' }
    ],
    toPayload: rawValue =>
      removeUndefined({
        name: trimString(rawValue['name']),
        phoneNumber: optionalString(rawValue['phoneNumber'])
      }),
    toTableRow: (entity: InventorySupplier) => ({
      name: entity.name,
      phoneNumber: valueOrDash(entity.phoneNumber)
    })
  },
  inventoryItems: {
    key: 'inventoryItems',
    title: 'Articulos de inventario',
    singular: 'articulo',
    description: 'Catalogo maestro de articulos internos. No se mezcla con los productos de venta.',
    endpoint: '/inventory/items',
    createButtonLabel: 'Agregar articulo',
    emptyMessage: 'No hay articulos de inventario registrados.',
    searchPlaceholder: 'Buscar por nombre, SKU, tipo o categoria',
    searchKeys: ['name', 'sku', 'type', 'description'],
    columns: [
      { key: 'name', label: 'Nombre' },
      { key: 'sku', label: 'SKU' },
      { key: 'type', label: 'Tipo' },
      { key: 'category', label: 'Categoria' },
      { key: 'unit', label: 'Unidad' },
      { key: 'location', label: 'Ubicacion' },
      { key: 'supplier', label: 'Proveedor' }
    ],
    fields: [
      { key: 'name', label: 'Nombre', type: 'text', required: true, placeholder: 'Botella PET 1L' },
      { key: 'sku', label: 'SKU', type: 'text', placeholder: 'Codigo interno opcional' },
      {
        key: 'type',
        label: 'Tipo de articulo',
        type: 'select',
        required: true,
        options: inventoryItemTypeOptions,
        placeholder: 'Selecciona un tipo'
      },
      {
        key: 'categoryId',
        label: 'Categoria',
        type: 'select',
        required: true,
        lookupKey: 'inventoryCategories',
        placeholder: 'Selecciona una categoria'
      },
      {
        key: 'unitId',
        label: 'Unidad',
        type: 'select',
        required: true,
        lookupKey: 'inventoryUnits',
        placeholder: 'Selecciona una unidad'
      },
      {
        key: 'locationId',
        label: 'Ubicacion',
        type: 'select',
        required: true,
        lookupKey: 'inventoryLocations',
        placeholder: 'Selecciona una ubicacion'
      },
      {
        key: 'supplierId',
        label: 'Proveedor',
        type: 'select',
        lookupKey: 'inventorySuppliers',
        placeholder: 'Opcional'
      },
      { key: 'description', label: 'Descripcion', type: 'textarea', placeholder: 'Descripcion opcional' }
    ],
    lookups: [
      { key: 'inventoryCategories', endpoint: '/inventory/categories' },
      { key: 'inventoryUnits', endpoint: '/inventory/units' },
      { key: 'inventoryLocations', endpoint: '/inventory/locations' },
      { key: 'inventorySuppliers', endpoint: '/inventory/suppliers' }
    ],
    toPayload: rawValue =>
      removeUndefined({
        name: trimString(rawValue['name']),
        sku: optionalString(rawValue['sku']),
        type: trimString(rawValue['type']),
        categoryId: requiredNumber(rawValue['categoryId']),
        unitId: requiredNumber(rawValue['unitId']),
        locationId: requiredNumber(rawValue['locationId']),
        supplierId: optionalNumber(rawValue['supplierId']),
        description: optionalString(rawValue['description'])
      }),
    toTableRow: (entity: InventoryItem, lookupData) => ({
      name: entity.name,
      sku: valueOrDash(entity.sku),
      type: valueOrDash(entity.type),
      category: findLookupLabel(lookupData, 'inventoryCategories', entity.categoryId, 'Sin categoria'),
      unit: findLookupLabel(lookupData, 'inventoryUnits', entity.unitId, 'Sin unidad'),
      location: findLookupLabel(lookupData, 'inventoryLocations', entity.locationId, 'Sin ubicacion'),
      supplier: findLookupLabel(lookupData, 'inventorySuppliers', entity.supplierId, 'Sin proveedor')
    })
  },
  expenseCategories: {
    key: 'expenseCategories',
    title: 'Categorias de gasto',
    singular: 'categoria de gasto',
    description: 'Clasifica los gastos internos del negocio.',
    endpoint: '/expenses/categories',
    createButtonLabel: 'Agregar categoria',
    emptyMessage: 'No hay categorias de gasto registradas.',
    searchPlaceholder: 'Buscar por nombre o descripcion',
    searchKeys: ['name', 'description'],
    columns: [
      { key: 'name', label: 'Nombre' },
      { key: 'description', label: 'Descripcion' }
    ],
    fields: [
      { key: 'name', label: 'Nombre', type: 'text', required: true, placeholder: 'Papeleria, mantenimiento...' },
      { key: 'description', label: 'Descripcion', type: 'textarea', placeholder: 'Descripcion opcional' }
    ],
    toPayload: rawValue =>
      removeUndefined({
        name: trimString(rawValue['name']),
        description: optionalString(rawValue['description'])
      }),
    toTableRow: (entity: ExpenseCategory) => ({
      name: entity.name,
      description: valueOrDash(entity.description)
    })
  },
  expenseCenters: {
    key: 'expenseCenters',
    title: 'Centros de gasto',
    singular: 'centro de gasto',
    description: 'Catalogo independiente para gastos internos. No usa sucursales comerciales.',
    endpoint: '/expenses/centers',
    createButtonLabel: 'Agregar centro de gasto',
    emptyMessage: 'No hay centros de gasto registrados.',
    searchPlaceholder: 'Buscar por nombre, tipo o descripcion',
    searchKeys: ['name', 'type', 'description'],
    columns: [
      { key: 'name', label: 'Nombre' },
      { key: 'type', label: 'Tipo' },
      { key: 'description', label: 'Descripcion' }
    ],
    fields: [
      { key: 'name', label: 'Nombre', type: 'text', required: true, placeholder: 'Planta, Ruta Norte, General...' },
      {
        key: 'type',
        label: 'Tipo',
        type: 'select',
        required: true,
        options: expenseCenterTypeOptions,
        placeholder: 'Selecciona un tipo'
      },
      { key: 'description', label: 'Descripcion', type: 'textarea', placeholder: 'Descripcion opcional' }
    ],
    toPayload: rawValue =>
      removeUndefined({
        name: trimString(rawValue['name']),
        type: trimString(rawValue['type']),
        description: optionalString(rawValue['description'])
      }),
    toTableRow: (entity: ExpenseCenter) => ({
      name: entity.name,
      type: valueOrDash(entity.type),
      description: valueOrDash(entity.description)
    })
  }
};
