import { ConfirmationType, ConfirmationTypeSchema } from './confirmation-type';
import { CountryAssociation, CountryAssociationSchema } from './country-association';
import { ServiceAttributesEnum, ServiceAttributesEnumSchema } from './services-attributes';
import { LabelSizesEnum, LabelSizesEnumSchema } from './label-sizes';
import { ServiceClassEnum, ServiceClassEnumSchema } from './service-class';
import { ServiceGradeEnum, ServiceGradeEnumSchema } from './service-grade';
import {
  ServiceRequiredPropertiesEnum,
  ServiceRequiredPropertiesEnumSchema,
} from './service-required-properties';
import Joi from 'joi';

import { ApiCodeRegex, ApiCodeValidationMessage } from '@shipengine/connect-runtime';

/** @description Basic structure for each shipping service */
export interface ShippingService {
  /** @description The confirmation types associated with this service */
  ConfirmationTypes?: ConfirmationType[];
  /** @description A list of attributes about this service */
  ServiceAttributes?: ServiceAttributesEnum[];
  /** @description A list of countries supported by this service */
  SupportedCountries?: CountryAssociation[];
  /** @description A list of label sizes supported by this service */
  SupportedLabelSizes?: LabelSizesEnum[];
  /** @description */
  RequiredProperties?: ServiceRequiredPropertiesEnum[];
  /** @description The grade of the service. ex: Economy, Expedited, Overnight */
  Grade?: ServiceGradeEnum;
  /** @description The class of service. ex: Ground, OneDay, ThreeDay */
  Class?: ServiceClassEnum;
  /** @description The label code associated with this shipping service */
  LabelCode?: string;
  /** @description Indicates whether or not this service is for international or domestic use */
  International?: boolean;
  /** @description This is the code that will be sent to requests, this should be the same code the carrier's api would expect */
  Code: string;
  /** @description This is an abbreviation of the name, can match the name if it is short enough */
  Abbreviation: string;
  /** @description The name of this shipping service ex: 'Overnight Guarantee' */
  Name: string;
  /** @description The identifier for this shipping service to be used in API calls. Must be snake cased and unique */
  ApiCode?: string;
  /** @description The unique identifier for this shipping service. It should not change after being published */
  Id: string;
}

export const ShippingServiceSchema = Joi.object({
  ConfirmationTypes: Joi.array().optional().items(ConfirmationTypeSchema).unique('Type'),
  ServiceAttributes: Joi.array().items(ServiceAttributesEnumSchema).optional(),
  SupportedCountries: Joi.array().optional().items(CountryAssociationSchema).unique('FromCountry'),
  SupportedLabelSizes: Joi.array().optional().items(LabelSizesEnumSchema).unique(),
  RequiredProperties: Joi.array().optional().items(ServiceRequiredPropertiesEnumSchema).unique(),
  Grade: ServiceGradeEnumSchema.optional(),
  Class: ServiceClassEnumSchema.optional(),
  LabelCode: Joi.string().optional().max(50),
  International: Joi.boolean().strict().optional(),
  Code: Joi.string().required().max(50),
  Abbreviation: Joi.string().required().max(20),
  Name: Joi.string().required().max(80),
  ApiCode: Joi.string().optional().pattern(ApiCodeRegex, ApiCodeValidationMessage),
  Id: Joi.string().uuid().required(),
});
