// tslint:disable:no-console
import * as mongoose from 'mongoose';

import { chevre } from '../../../../lib/index';

const project = { id: String(process.env.PROJECT_ID) };
const NUM_CREATE_OFFERS = 300;
const NUM_CREATE_SUB_CATALOGS = 10;

// tslint:disable-next-line:max-func-body-length
async function main() {
    await mongoose.connect(<string>process.env.MONGOLAB_URI, { autoIndex: false });

    const aggregateOfferRepo = await chevre.repository.AggregateOffer.createInstance(mongoose.connection);
    const offerCatalogRepo = await chevre.repository.OfferCatalog.createInstance(mongoose.connection);
    const productRepo = await chevre.repository.Product.createInstance(mongoose.connection);
    const offerCatalogItemRepo = await chevre.repository.OfferCatalogItem.createInstance(mongoose.connection);

    const savingOffers: Omit<chevre.factory.unitPriceOffer.IUnitPriceOffer, 'id'>[] =
        // tslint:disable-next-line:prefer-array-literal
        [...Array(NUM_CREATE_OFFERS)].map<Omit<chevre.factory.unitPriceOffer.IUnitPriceOffer, 'id'>>((__, i) => {
            const identifier = `sampleFreeOffer${i}`;
            const priceSpecification: chevre.factory.unitPriceOffer.IUnitPriceOfferPriceSpecification = {
                typeOf: chevre.factory.priceSpecificationType.UnitPriceSpecification,
                priceCurrency: chevre.factory.priceCurrency.JPY,
                valueAddedTaxIncluded: true,
                price: 0,
                referenceQuantity: {
                    value: 1,
                    typeOf: 'QuantitativeValue',
                    unitCode: chevre.factory.unitCode.C62
                },
                accounting: {
                    typeOf: 'Accounting',
                    accountsReceivable: 0
                }
            };

            return {
                project: { id: project.id, typeOf: chevre.factory.organizationType.Project },
                typeOf: chevre.factory.offerType.Offer,
                identifier,
                description: { en: identifier, ja: identifier },
                alternateName: { ja: identifier },
                name: { en: identifier, ja: identifier },
                availability: chevre.factory.itemAvailability.InStock,
                availableAtOrFrom: [
                    { id: '51qbjcfr72h62m06vtv5kkhgje' }
                ],
                itemOffered: { typeOf: chevre.factory.product.ProductType.EventService },
                priceCurrency: chevre.factory.priceCurrency.JPY,
                priceSpecification
            };
        });
    const saveOfferResult = await aggregateOfferRepo.upsertByIdentifier(savingOffers);
    console.log('saveOfferResult:', saveOfferResult);

    const offerIds: string[] = (Array.isArray(saveOfferResult?.modifiedOffers)) ? saveOfferResult.modifiedOffers.map(({ id }) => id) : [];
    const catalogIdentifier = 'sampleFreeOffersCatalog';
    const savingOfferCatalog: chevre.factory.offerCatalog.IOfferCatalog = {
        project: { id: project.id, typeOf: chevre.factory.organizationType.Project },
        typeOf: 'OfferCatalog',
        identifier: catalogIdentifier,
        description: { en: catalogIdentifier, ja: catalogIdentifier },
        name: { en: catalogIdentifier, ja: catalogIdentifier },
        itemListElement: offerIds.map((id) => ({ id, typeOf: chevre.factory.offerType.Offer })),
        itemOffered: { typeOf: chevre.factory.product.ProductType.EventService }
    };
    const saveCatalogResult = await offerCatalogRepo.saveByIdentifier(savingOfferCatalog);
    console.log('saveCatalogResult:', saveCatalogResult);

    const productId = 'sampleFreeEventService';
    const savingProduct: chevre.factory.product.IProduct & {
        offers?: never;
    } = {
        project: { id: project.id, typeOf: chevre.factory.organizationType.Project },
        typeOf: chevre.factory.product.ProductType.EventService,
        name: { en: productId, ja: productId },
        productID: productId,
        hasOfferCatalog: {
            typeOf: 'OfferCatalog',
            itemListElement: [{ id: saveCatalogResult.id }]
        }
    };
    const saveProductResult = await productRepo.upsertManyByProductId([{
        $set: savingProduct
    }]);
    console.log('saveProductResult:', saveProductResult);

    // 以下サブカタログ
    const offerIds4subCatalog: string[] = (Array.isArray(saveOfferResult?.modifiedOffers))
        // tslint:disable-next-line:no-magic-numbers
        ? saveOfferResult.modifiedOffers.slice(0, 100)
            .map(({ id }) => id) :
        [];
    const savingSubOfferCatalogs: chevre.factory.offerCatalog.IOfferCatalog[] =
        // tslint:disable-next-line:prefer-array-literal
        [...Array(NUM_CREATE_SUB_CATALOGS)].map<chevre.factory.offerCatalog.IOfferCatalog>((__, i) => {
            const subCatalogIdentifier = `sampleFreeOffersSubCatalog${i}`;

            return {
                project: { id: project.id, typeOf: chevre.factory.organizationType.Project },
                typeOf: 'OfferCatalog',
                identifier: subCatalogIdentifier,
                description: { en: subCatalogIdentifier, ja: subCatalogIdentifier },
                name: { en: subCatalogIdentifier, ja: subCatalogIdentifier },
                itemListElement: offerIds4subCatalog.map((id) => ({ id, typeOf: chevre.factory.offerType.Offer })),
                itemOffered: { typeOf: chevre.factory.product.ProductType.EventService }
            };
        });
    const saveSubCatalogResult = await offerCatalogItemRepo.upsertManyByIdentifier(savingSubOfferCatalogs.map((savingSubOfferCatalog) => {
        return {
            $set: savingSubOfferCatalog
        };
    }));
    console.log('saveSubCatalogResult:', saveSubCatalogResult);

    const subCatalogIds: string[] =
        (Array.isArray(saveSubCatalogResult?.modifiedCatalogs)) ? saveSubCatalogResult.modifiedCatalogs.map(({ id }) => id) : [];
    const catalogBySubCatalogIdentifier = 'sampleFreeOffersCatalogBySub';
    const savingOfferCatalogBySubCatalog: chevre.factory.offerCatalog.IOfferCatalog = {
        project: { id: project.id, typeOf: chevre.factory.organizationType.Project },
        typeOf: 'OfferCatalog',
        identifier: catalogBySubCatalogIdentifier,
        description: { en: catalogBySubCatalogIdentifier, ja: catalogBySubCatalogIdentifier },
        name: { en: catalogBySubCatalogIdentifier, ja: catalogBySubCatalogIdentifier },
        itemListElement: subCatalogIds.map((id) => ({ id, typeOf: 'OfferCatalog' })),
        itemOffered: { typeOf: chevre.factory.product.ProductType.EventService }
    };
    const saveCatalogBySubResult = await offerCatalogRepo.saveByIdentifier(savingOfferCatalogBySubCatalog);
    console.log('saveCatalogBySubResult:', saveCatalogBySubResult);

    const productIdBySubCatalog = 'sampleFreeEventServiceBySub';
    const savingProductBySubCatalog: chevre.factory.product.IProduct & {
        offers?: never;
    } = {
        project: { id: project.id, typeOf: chevre.factory.organizationType.Project },
        typeOf: chevre.factory.product.ProductType.EventService,
        name: { en: productIdBySubCatalog, ja: productIdBySubCatalog },
        productID: productIdBySubCatalog,
        hasOfferCatalog: {
            typeOf: 'OfferCatalog',
            itemListElement: [{ id: saveCatalogBySubResult.id }]
        }
    };
    const saveProductBySubCatalogResult = await productRepo.upsertManyByProductId([{
        $set: savingProductBySubCatalog
    }]);
    console.log('saveProductBySubCatalogResult:', saveProductBySubCatalogResult);
}

main()
    .then()
    .catch(console.error);
