import { invert } from 'lodash';

import {
  Customer,
  CustomerTypeName,
  InventoryLevel,
  InventoryLevelTypeName,
  Location,
  LocationTypeName,
  Order,
  OrderTypeName,
  Product,
  ProductTypeName,
  ProductVariant,
  ProductVariantTypeName,
  ShopifyObject,
  ShopifyObjectType,
  ShopifyObjects
} from '../../../models';
import {
  LineItem,
  LineItemTypeName
} from '../../../models/shopify/LineItem';

export type ModelKeysToDefaultFieldName<SO extends ShopifyObject> = Partial<Record<keyof SO['props'], string>>;
export type ModelDefaultFieldNameToKey<SO extends ShopifyObject> = Record<string, keyof SO['props']>;

type DefaultModelFieldNames = {
    [SOT in ShopifyObjectType]: {
      modelKeyToFieldName: ModelKeysToDefaultFieldName<ShopifyObjects[SOT]>;
      fieldNameToModelKey: ModelDefaultFieldNameToKey<ShopifyObjects[SOT]>;
    }
};

export const OrderKeysToDefaultFieldNames:ModelKeysToDefaultFieldName<Order> = {};
export const OrderDefaultFieldNameToKey = invert(OrderKeysToDefaultFieldNames) as ModelDefaultFieldNameToKey<Order>;

export const ProductKeysToDefaultFieldNames:ModelKeysToDefaultFieldName<Product> = {};
export const ProductDefaultFieldNameToKey = invert(ProductKeysToDefaultFieldNames) as ModelDefaultFieldNameToKey<Product>;

export const ProductVariantKeysToDefaultFieldNames:ModelKeysToDefaultFieldName<ProductVariant> = {};
export const ProductVariantDefaultFieldNameToKey = invert(ProductVariantKeysToDefaultFieldNames) as ModelDefaultFieldNameToKey<ProductVariant>;

export const LocationKeysToDefaultFieldNames:ModelKeysToDefaultFieldName<Location> = {};
export const LocationDefaultFieldNameToKey = invert(LocationKeysToDefaultFieldNames) as ModelDefaultFieldNameToKey<Location>;

export const InventoryLevelKeysToDefaultFieldNames:ModelKeysToDefaultFieldName<InventoryLevel> = {};
export const InventoryLevelDefaultFieldNameToKey = invert(InventoryLevelKeysToDefaultFieldNames) as ModelDefaultFieldNameToKey<InventoryLevel>;

export const LineItemKeysToDefaultFieldNames:ModelKeysToDefaultFieldName<LineItem> = {};
export const LineItemDefaultFieldNameToKey = invert(LineItemKeysToDefaultFieldNames) as ModelDefaultFieldNameToKey<LineItem>;

export const CustomerKeysToDefaultFieldNames:ModelKeysToDefaultFieldName<Customer> = {};
export const CustomerDefaultFieldNameToKey = invert(CustomerKeysToDefaultFieldNames) as ModelDefaultFieldNameToKey<Customer>;

export const DefaultModelFieldNames:DefaultModelFieldNames = {
  [OrderTypeName]: {
    modelKeyToFieldName: OrderKeysToDefaultFieldNames,
    fieldNameToModelKey: OrderDefaultFieldNameToKey,
  },
  [ProductTypeName]: {
    modelKeyToFieldName: ProductKeysToDefaultFieldNames,
    fieldNameToModelKey: ProductDefaultFieldNameToKey
  },
  [ProductVariantTypeName]: {
    modelKeyToFieldName: ProductVariantKeysToDefaultFieldNames,
    fieldNameToModelKey: ProductVariantDefaultFieldNameToKey
  },
  [LocationTypeName]: {
    modelKeyToFieldName: LocationKeysToDefaultFieldNames,
    fieldNameToModelKey: LocationDefaultFieldNameToKey,
  },
  [InventoryLevelTypeName]: {
    modelKeyToFieldName: InventoryLevelKeysToDefaultFieldNames,
    fieldNameToModelKey: InventoryLevelDefaultFieldNameToKey,
  },
  [LineItemTypeName]: {
    modelKeyToFieldName: LineItemKeysToDefaultFieldNames,
    fieldNameToModelKey: LineItemDefaultFieldNameToKey,
  },
  [CustomerTypeName]: {
    modelKeyToFieldName: CustomerKeysToDefaultFieldNames,
    fieldNameToModelKey: CustomerDefaultFieldNameToKey,
  }
};

export function getDefaultFieldName(
  type: ShopifyObjectType,
  modelFieldName: keyof ShopifyObjects[typeof type]['props']
):string {
  const defaultModelFieldNames = DefaultModelFieldNames[type].modelKeyToFieldName;

  return (modelFieldName in defaultModelFieldNames) ?
    defaultModelFieldNames[modelFieldName] as string :
    modelFieldName;
}

export function getModelKeyFromDefaultFieldName(
  type: ShopifyObjectType,
  defaultFieldName: string
): keyof ShopifyObjects[typeof type]['props'] {
  return (DefaultModelFieldNames[type].fieldNameToModelKey[defaultFieldName] ?? defaultFieldName) as keyof ShopifyObjects[typeof type]['props'];
}