const { Model, DataTypes, Op } = require('sequelize');
const sequelize = require('../config/db.js');
const Entity = require('./entity.js');
const PEntity = require('./p_entity.js');
const BankAccount = require('./bank_account.js');
const BankBranch = require('./bank_branch.js');
const Bank = require('./bank.js');
const { sanitizeSort, sanitizePagination } = require('./querySafety.js');

class InvoiceTemplate extends Model {

    static associate(models) {
        InvoiceTemplate.belongsToMany(models.Billable, { 
            as: "billable",
            through: "invoice_billables"
        });

        InvoiceTemplate.belongsTo(models.Entity, { 
            as: "biller", 
            foreignKey: "biller_id"
        });
        
        InvoiceTemplate.belongsTo(models.PEntity, { 
            as: "payee", 
            foreignKey: "payee_id"
        });

        InvoiceTemplate.belongsTo(models.BankAccount, {
            as: "bank_accounts",
            foreignKey: "acc_id"
        });

        InvoiceTemplate.hasMany(models.Invoice, {
            as: "invoices",
            foreignKey: "template_id"
        });
    }

    async createInvTemp(data, creatorId) {
        try {
            var user_id = creatorId;
            const invTemp = await InvoiceTemplate.create({...data, creatorId, user_id});
            console.log(invTemp.toJSON());
            return invTemp.toJSON();
        }
        catch (err) {
            console.log(err);
            return err
        }
    }

    async getTempName(id) {
        try {
            const invTemp = await InvoiceTemplate.findAll(
                {
                    where: {
                        biller_id: id
                    },
                    attributes: ["id", "name"]
                }
            );
            console.log(invTemp.map(t => t.toJSON()));
            return invTemp.map(t => t.toJSON());
        }
        catch (err) {
            console.log(err);
            return err;
        }
    }
    
    async readInvTemp(ordCol, ordDir, offsetVal, limitVal, id, searchTerm) {
        try {
            const [safeOrderCol, safeOrderDir] = sanitizeSort(ordCol, ordDir, [
                'id', 'name', 'type', 'user_id', 'payee_id', 'biller_id', 'acc_id', 'tax_id', 'billables', 'note', 'terms', 'status', 'recurrence', 'creatorId', 'createdAt', 'updatedAt'
            ]);
            const { safeOffset, safeLimit } = sanitizePagination(offsetVal, limitVal);
            const invTemp = await InvoiceTemplate.findAll(
                {
                    where: {
                        biller_id: id,
                        ...(searchTerm
                            ? {
                                [Op.or]: [
                                    { name: { [Op.like]: `%${searchTerm}%` } },
                                ]
                            }
                        : {}
                        )
                    },
                    order: [[safeOrderCol, safeOrderDir]],
                    offset: safeOffset,
                    limit: safeLimit,
                    include: [
                        {
                            model: PEntity,
                            as: "payee",
                            attributes: ["id", "name"]
                        },
                        {
                            model: Entity,
                            as: "biller",
                            attributes: ["id", "name"]
                        },
                        {
                            model: BankAccount,
                            as: "bank_accounts",
                            attributes: ["id", "name"],
                            include: [
                                {
                                    model: BankBranch,
                                    as: "bank_branch",
                                    attributes: ["id", "name", "ifsc"],
                                    include: [
                                        {
                                            model: Bank,
                                            as: "bank",
                                            attributes: ["id", "name"]
                                        }
                                    ]
                                }
                            ]
                        }
                    ],
                    raw: true,
                    nest: false
                }
            );
            console.log(invTemp);
            return invTemp;
        }
        catch (err) {
            console.log(err);
            return err;
        }
    }

    async readInvTempRow(data) {
        try {
            const invTemp = await InvoiceTemplate.findOne(
                {
                    where: {
                        id: data.id
                    }
                }
            )
            console.log(invTemp.toJSON());
            return invTemp.toJSON();
        }
        catch (err) {
            console.log(err);
            return err;
        }
    } 

    async updateInvTemp(data) {
        try {
            const result = await InvoiceTemplate.update(data, {where: {id: data.id}});
            console.log(`Invoice Template with ${data.id} updated`, result[0]);
            return result[0];
        }
        catch (err) {
            console.log(err);
            return err;
        }
    }

    async deleteInvTemp(data) {
        try {
            const result = await InvoiceTemplate.destroy(
                {
                    where: {id: data.id}
                }
            );

            if (result) {
                console.log(`Invoice Template ${data.id} deleted`);
                return `Invoice Template ${data.id} deleted`;
            }
            else {
                console.log(`Invoice Template ${data.id} not found`);
                return `Invoice Template ${data.id} not found`;
            }
        }
        catch (err) {
            console.log(err);
        }
    }

    async countInvTemp() {
        try {
            const count = await InvoiceTemplate.count();
            console.log(count);
            return count;
        }
        catch (err) {
            console.log(err);
            return err;
        }
    }
}

InvoiceTemplate.init(
    {
        name: {
            type: DataTypes.STRING(50),
            allowNull: false
        },
        type: {
            type: DataTypes.STRING(50),
            allowNull: false
        },
        user_id: {
            type: DataTypes.INTEGER,
            allowNull: false,
            references: {
                model: 'users',
                key: 'id'
            }
        },
        payee_id: {
            type: DataTypes.INTEGER,
            allowNull: false,
            references: {
                model: 'p_entity',
                key: 'id'
            }
        },
        biller_id: {
            type: DataTypes.INTEGER,
            allowNull: false,
            references: {
                model: 'entity',
                key: 'id'
            }
        },
        acc_id: {
            type: DataTypes.INTEGER,
            allowNull: false,
            references: {
                model: 'bank_accounts',
                key: 'id'
            }
        },
        tax_id: {
            type: DataTypes.JSON,
            allowNull: false
        },
        billables: {
            type: DataTypes.JSON,
            allowNull: false
        },
        note: {
            type: DataTypes.TEXT,
            allowNull: true
        },
        terms: {
            type: DataTypes.JSON,
            allowNull: true
        },
        status: {
            type: DataTypes.STRING(25),
            allowNull: false
        },
        recurrence: {
            type: DataTypes.STRING(25),
            allowNull: false
        },
        creatorId: {
            type: DataTypes.INTEGER,
            allowNull: false
        }
    },
    {
        sequelize,
        modelName: "InvoiceTemplate",
        tableName: "invoice_template"
    }
)

module.exports = InvoiceTemplate;