import { Injectable, Logger, OnApplicationBootstrap } from "@nestjs/common";
import { EntityManager } from "typeorm";
import UserEntity from "./entity/user.entity";
import * as bcrypt from 'bcrypt';
import StoreEntity from "./entity/store.entity";
import PriceEntity from "./entity/price.entity";
import StorageEntity from "./entity/storage.entity";
import DeviceEntity from "./entity/device.entity";
import UnitMeasureEntity from "./entity/unit_measure.entity";
import OperatorEntity from "./entity/operator.entity";
import RateEntity from "./entity/rate.entity";
import CategoryEntity from "./entity/category.entity";
import ArticleEntity from "./entity/article.entity";
import ArticleCategoryEntity from "./entity/article_category.entity";
import ArticlePriceEntity from "./entity/article_price.entity";
import ArticleBarcodeEntity from "./entity/article_barcode.entity";
import ArticleStoreEntity from "./entity/article_store.entity";
import PaymentEntity from "./entity/payment.entity";
import InvoiceCounterEntity from "./entity/invoice_counter.entity";
import CreditNoteCounterEntity from "./entity/credit_note.entity";
import DocumentProgressiveEntity from "./entity/document_progressive.entity";
import { documentTypes } from "./types/constants";
import TipologyEntity from "./entity/tipology.entity";
import AttributeEntity from "./entity/attribute.entity";
import CustomerEntity from "./entity/customer.entity";
import SupplierEntity from "./entity/supplier.entity";
import HelperProvider from "./module/helper/helper.provider";

@Injectable()
export default class StartupProvider implements OnApplicationBootstrap {

    private logger: Logger = new Logger(StartupProvider.name);

    constructor(private readonly entityManager: EntityManager, private readonly helperProvider: HelperProvider){}

    /**
     * On startup
     * create all base data
     * if user is not present
     */
    async onApplicationBootstrap() {
        
        try{

            // Useful date
            const now   = new Date();
            const year  = now.getFullYear();

            const nUser = await this.entityManager.count(UserEntity);
            if(nUser == 0){

                // ________ User ________

                const user: UserEntity  = new UserEntity();
                user.code               = this.helperProvider.generateRandomCode();
                user.title              = "AMMINISTRATORE";
                user.username           = "admin";
                user.password           = bcrypt.hashSync('Admin2026!', 10);

                await this.entityManager.save(user);

                // ________ Price ________

                const price: PriceEntity    = new PriceEntity();
                price.code                  = this.helperProvider.generateRandomCode();
                price.title                 = "LISTINO VENDITA";

                await this.entityManager.save(price);

                const priceBought: PriceEntity    = new PriceEntity();
                priceBought.code                  = this.helperProvider.generateRandomCode();
                priceBought.title                 = "LISTINO ACQUISTO";

                await this.entityManager.save(priceBought);

                // ________ Store ________

                const store: StoreEntity    = new StoreEntity();
                store.code                  = this.helperProvider.generateRandomCode();
                store.title                 = "NEGOZIO";
                store.businessName          = "NEGOZIO DEMO";
                store.fiscalRegim           = "RF01";
                store.price                 = new PriceEntity(price.id);

                await this.entityManager.save(store);

                // ________ Storage ________

                const storage: StorageEntity    = new StorageEntity();
                storage.code                    = this.helperProvider.generateRandomCode();
                storage.title                   = "DEPOSITO";
                storage.store                   = new StoreEntity(store.id);

                await this.entityManager.save(storage);

                // ________ Device ________

                const device: DeviceEntity  = new DeviceEntity();
                device.code                 = this.helperProvider.generateRandomCode();
                device.title                = "CASSA";
                device.store                = new StoreEntity(store.id);

                await this.entityManager.save(device);

                // ________ Unit measure ________

                const unitMeasure: UnitMeasureEntity    = new UnitMeasureEntity();
                unitMeasure.code                        = this.helperProvider.generateRandomCode();
                unitMeasure.title                       = "PEZZO";

                await this.entityManager.save(unitMeasure);

                // ________ Operator ________

                const operator: OperatorEntity  = new OperatorEntity();
                operator.code                   = this.helperProvider.generateRandomCode();
                operator.title                  = "CASSIERE";
                operator.pin                    = "111111";

                await this.entityManager.save(operator);

                // ________ Rate ________

                let indexRate = 1;
                let firstRate: RateEntity | null = null;

                for await (const rateValue of [0, 4, 5, 10, 22]){

                    const rate: RateEntity  = new RateEntity();
                    rate.code               = this.helperProvider.generateRandomCode();
                    rate.title              = `IVA ${rateValue}%`;
                    rate.value              = rateValue;
                    rate.departmentNumber   = 1;
                    rate.enforceability     = "I";

                    await this.entityManager.save(rate);

                    if(rateValue > 0 && !firstRate){
                        firstRate = rate;
                    }

                    indexRate++;
                }

                // ________ Payment ________

                const payment: PaymentEntity    = new PaymentEntity();
                payment.code                    = this.helperProvider.generateRandomCode();
                payment.title                   = "CONTANTI";
                payment.paymentType             = "MP01";
                payment.tend                    = 1;
                payment.subTend                 = 1;
                payment.availableOnPos          = 1;

                await this.entityManager.save(payment);

                const paymentCreditCard: PaymentEntity    = new PaymentEntity();
                paymentCreditCard.code                    = this.helperProvider.generateRandomCode();
                paymentCreditCard.title                   = "CARTA DI CREDITO";
                paymentCreditCard.paymentType             = "MP08";
                paymentCreditCard.tend                    = 1;
                paymentCreditCard.subTend                 = 1;
                paymentCreditCard.availableOnPos          = 1;

                await this.entityManager.save(paymentCreditCard);

                // ________ Tipology ________

                const tipology: TipologyEntity  = new TipologyEntity();
                tipology.code                   = this.helperProvider.generateRandomCode();
                tipology.title                  = "TAGLIA";

                const tipologyColor: TipologyEntity = new TipologyEntity();
                tipologyColor.code                  = this.helperProvider.generateRandomCode();
                tipologyColor.title                 = "COLORE";

                await this.entityManager.save(tipology);
                await this.entityManager.save(tipologyColor);

                // ________ Attribute ________

                const attribute: AttributeEntity    = new AttributeEntity();
                attribute.code                      = this.helperProvider.generateRandomCode();
                attribute.title                     = "39";
                attribute.tipology                  = new TipologyEntity(tipology.id);

                const attributeColor: AttributeEntity   = new AttributeEntity();
                attributeColor.code                     = this.helperProvider.generateRandomCode();
                attributeColor.title                    = "ROSSO";
                attributeColor.tipology                 = new TipologyEntity(tipologyColor.id);

                await this.entityManager.save(attribute);
                await this.entityManager.save(attributeColor);

                // ________ Customer ________

                const customer: CustomerEntity  = new CustomerEntity();
                customer.code                   = this.helperProvider.generateRandomCode();
                customer.businessName           = "CLIENTE BASE";
                customer.vatNumber              = "0000000000";

                await this.entityManager.save(customer);

                // ________ Supplier ________

                const supplier: SupplierEntity  = new SupplierEntity();
                supplier.code                   = this.helperProvider.generateRandomCode();
                supplier.businessName           = "FORNITORE BASE";
                supplier.vatNumber              = "0000000000";

                await this.entityManager.save(supplier);

                // ________ Category ________

                const category: CategoryEntity  = new CategoryEntity();
                category.code                   = this.helperProvider.generateRandomCode();
                category.title                  = "CATEGORIA DEMO";
                category.color                  = "#000000";
                category.availableOnPos        = 1;

                await this.entityManager.save(category);

                // ________ Article ________

                const article: ArticleEntity    = new ArticleEntity();
                article.code                    = this.helperProvider.generateRandomCode();
                article.title                   = "ARTICOLO DEMO";
                article.sku                     = "ART-001";
                article.availableOnPos         = 1;
                article.unitMeasure             = new UnitMeasureEntity(unitMeasure.id);
                article.rate                    = new RateEntity(firstRate!.id);

                await this.entityManager.save(article);
                
                // ________ Article category ________

                const articleCategory: ArticleCategoryEntity    = new ArticleCategoryEntity();
                articleCategory.article                         = new ArticleEntity(article.id);
                articleCategory.category                        = new CategoryEntity(category.id);

                await this.entityManager.save(articleCategory);

                // ________ Article price ________

                const articlePrice: ArticlePriceEntity  = new ArticlePriceEntity();
                articlePrice.article                    = new ArticleEntity(article.id);
                articlePrice.priceEntity                = new PriceEntity(price.id);
                articlePrice.price                      = 1.00;
                articlePrice.taxable                    = 0.81967213;

                await this.entityManager.save(articlePrice);

                // ________ Article barcode ________

                const articleBarcode: ArticleBarcodeEntity  = new ArticleBarcodeEntity();
                articleBarcode.article                      = new ArticleEntity(article.id);
                articleBarcode.barcode                      = "1234567890128";
                articleBarcode.ratio                        = 1;

                await this.entityManager.save(articleBarcode);

                // ________ Article store ________

                const articleStore: ArticleStoreEntity  = new ArticleStoreEntity();
                articleStore.article                    = new ArticleEntity(article.id);
                articleStore.store                      = new StoreEntity(store.id);

                await this.entityManager.save(articleStore);

                // ________ Invoice counter ________

                const invoiceCounter: InvoiceCounterEntity  = new InvoiceCounterEntity();
                invoiceCounter.code                         = this.helperProvider.generateRandomCode();
                invoiceCounter.active                       = 1;
                invoiceCounter.currentNumber                = 1;
                invoiceCounter.suffix                       = `-${year}`;
                invoiceCounter.prefix                       = "FAD/";
                invoiceCounter.store                        = new StoreEntity(store.id);
                invoiceCounter.title                        = `CONTATORE FATTURA`;

                await this.entityManager.save(invoiceCounter);

                // ________ Credit note counter ________

                const creditNoteCounter: CreditNoteCounterEntity    = new CreditNoteCounterEntity();
                creditNoteCounter.code                              = this.helperProvider.generateRandomCode();
                creditNoteCounter.active                            = 1;
                creditNoteCounter.currentNumber                     = 1;
                creditNoteCounter.suffix                            = `-${year}`;
                creditNoteCounter.prefix                            = "NC/";
                creditNoteCounter.store                             = new StoreEntity(store.id);
                creditNoteCounter.title                             = `CONTATORE NOTA DI CREDITO`;

                await this.entityManager.save(creditNoteCounter);

                // ________ Document progressive ________

                for await (const documentType of documentTypes){

                    const documentProgressive: DocumentProgressiveEntity = new DocumentProgressiveEntity();
                    documentProgressive.documentArea                     = documentType;
                    documentProgressive.progressive                      = 1;
                    documentProgressive.store                            = new StoreEntity(store.id);

                    await this.entityManager.save(documentProgressive);
                }

            }

        }catch(e: any){
            this.logger.error(e.message);
        }

    }

}