"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.redisConn = exports.cacheSize = exports.deleteTicketsFieldsCache = exports.flushCache = exports.deleteTicketsByIdCache = exports.updateTicketsByContactsCache = exports.deleteTicketsByContactsCache = exports.updateTicketCacheByTicketId = exports.searchTicketCache = exports.createOrUpdateTicketCache = exports.updateTicketCache = exports.loadTicketsCache = void 0;
const ioredis_1 = __importDefault(require("ioredis"));
const unflatten = require('flat').unflatten;
var flatten = require('flat');
const ListTicketServiceCache_1 = __importDefault(require("../services/TicketServices/ListTicketServiceCache"));
const ContactsCache_1 = require("./ContactsCache");
let redis = null;
if (process.env.CACHE) {
    redis = new ioredis_1.default();
}
const redisConn = () => __awaiter(void 0, void 0, void 0, function* () {
    if (!process.env.CACHE) {
        return null;
    }
    // try {
    //     const redis = new Redis();
    //     const conn = () => new Promise((resolve, reject) => {
    //         redis.on('error', async (err) => {
    //             if (err.code === 'ECONNREFUSED') {
    //                 console.error(`Redis connection error: ${err}.`)
    //                 // await redis.quit()
    //             }
    //             else {
    //                 console.error(`Redis encountered an error: ${err.message}.`)
    //             }
    //             reject(err)
    //         })
    //         redis.on('connect', () => {
    //             // console.log('CacheStore - Connection status: connected');
    //             resolve(redis);
    //         })
    //         redis.on('end', () => {
    //             // console.log('CacheStore - Connection status: disconnected');
    //         });
    //         redis.on('reconnecting', () => {
    //             // console.log('CacheStore - Connection status: reconnecting');
    //         });
    //     });
    //     return await conn();
    // } catch (e) {
    //     console.error(`There whas an error on redis connection: ${e}`);
    //     return Promise.resolve([]);
    // }
    return redis;
});
exports.redisConn = redisConn;
const flushCache = () => __awaiter(void 0, void 0, void 0, function* () {
    const redis = yield redisConn();
    if (!redis)
        return false;
    // if (redis.status === 'connect') {
    //     console.log('TICKETS CACHE REMOVED')
    //     await redis.call('FLUSHALL') 
    // }
    yield redis.call('FLUSHALL');
});
exports.flushCache = flushCache;
const cacheSize = () => __awaiter(void 0, void 0, void 0, function* () {
    const redis = yield redisConn();
    if (!redis)
        return null;
    // if (redis.status !== 'connect') return -1
    const size = yield redis.call('dbsize');
    // await redis.quit()
    return size;
});
exports.cacheSize = cacheSize;
const loadTicketsCache = () => __awaiter(void 0, void 0, void 0, function* () {
    const redis = yield redisConn();
    if (!redis)
        return;
    //  if (redis.status !== 'connect') return
    yield createTicketIndexCache('idx_ticket');
    let tickets = yield ListTicketServiceCache_1.default({});
    const pipeline = redis.pipeline();
    for (let i = 0; i < tickets.length; i++) {
        tickets[i].createdAt = new Date(tickets[i].createdAt).toISOString();
        tickets[i].updatedAt = new Date(tickets[i].updatedAt).toISOString();
        tickets[i].escaped_name = ContactsCache_1.escapeCharCache(tickets[i]['contact.name']);
        // tickets[i]['contact_name'] = tickets[i]['contact.name']
        // delete tickets[i]['contact.name']
        tickets[i]['contact_number'] = tickets[i]['contact.number'];
        delete tickets[i]['contact.number'];
        pipeline.hmset(`ticket:${tickets[i].id}`, tickets[i]);
    }
    yield pipeline.exec(() => { console.log(`${tickets.length} TICKETS INSERTED IN CACHE!`); });
    // await redis.quit()
});
exports.loadTicketsCache = loadTicketsCache;
const createTicketIndexCache = (hashIndex) => __awaiter(void 0, void 0, void 0, function* () {
    const redis = yield redisConn();
    if (!redis)
        return;
    //  if (redis.status !== 'connect') return
    try {
        const lst_index_redis = yield redis.call('FT._LIST');
        if (lst_index_redis.includes(hashIndex)) {
            console.log('entrou...');
            yield redis.call('FT.DROPINDEX', hashIndex);
        }
        const response = yield redis.call('FT.CREATE', hashIndex, 'ON', 'HASH', 'PREFIX', '1', 'ticket:', 'SCHEMA', 'escaped_name', 'TEXT', 'SORTABLE', 'contact_number', 'TEXT', 'SORTABLE', 'status', 'TAG', 'SORTABLE');
        console.log('Ticket index created: ', response);
    }
    catch (error) {
        console.log('There was an error on createTicketIndexCache: ', error);
    }
    // await redis.quit()
});
const updateTicketCache = (hash, json_object) => __awaiter(void 0, void 0, void 0, function* () {
    const redis = yield redisConn();
    if (!redis)
        return;
    //  if (redis.status !== 'connect') return
    const pipeline = redis.pipeline();
    let entries = Object.entries(json_object);
    entries.forEach((e) => {
        pipeline.hset(hash, e[0], e[1]);
    });
    yield pipeline.exec(() => { console.log("updateTicketCache Key/value inserted/updated"); });
    // await redis.quit()
});
exports.updateTicketCache = updateTicketCache;
const updateTicketCacheByTicketId = (ticketId, update_fields) => __awaiter(void 0, void 0, void 0, function* () {
    const redis = yield redisConn();
    if (!redis)
        return;
    //  if (redis.status !== 'connect') return
    const ticket_cache = yield redis.hgetall(`ticket:${ticketId}`);
    try {
        if (ticket_cache && Object.keys(ticket_cache).length > 0) {
            if (update_fields.escaped_name) {
                update_fields.escaped_name = ContactsCache_1.escapeCharCache(update_fields['contact.name']);
            }
            yield updateTicketCache(`ticket:${ticketId}`, update_fields);
            console.log(`updateTicketCacheByTicketId TICKET ${ticket_cache['contact_number']} CACHE WAS UPDATED!`);
        }
        else {
            console.log('TICKET CACHE NOT FOUND!');
        }
    }
    catch (error) {
        console.log(`There was an error on updateTicketCacheByTicketId:  ${error}`);
    }
    // await redis.quit()
});
exports.updateTicketCacheByTicketId = updateTicketCacheByTicketId;
const createOrUpdateTicketCache = (hash, ticket) => __awaiter(void 0, void 0, void 0, function* () {
    const redis = yield redisConn();
    if (!redis)
        return;
    //  if (redis.status !== 'connect') return 
    ticket.escaped_name = ContactsCache_1.escapeCharCache(ticket['contact.name']);
    ticket['contact_number'] = ticket['contact.number'];
    delete ticket['contact.number'];
    yield redis.hmset(hash, ticket);
    console.log('CREATED/UPDATED TICKET CACHE');
    // await redis.quit()
});
exports.createOrUpdateTicketCache = createOrUpdateTicketCache;
const deleteTicketsByIdCache = (ticketId) => __awaiter(void 0, void 0, void 0, function* () {
    const redis = yield redisConn();
    if (!redis)
        return;
    //  if (redis.status !== 'connect') return
    const ticket_cache = yield redis.hgetall(`ticket:${ticketId}`);
    try {
        if (ticket_cache && Object.keys(ticket_cache).length > 0) {
            yield redis.del(`ticket:${ticketId}`);
            console.log(`TICKET ${ticket_cache['id']} CACHE WAS DELETED!`);
        }
        else {
            console.log('TICKET CACHE NOT FOUND!');
        }
    }
    catch (error) {
        console.log(`There was an error on deleteTicketsByIdCache:  ${error}`);
    }
    // await redis.quit()
});
exports.deleteTicketsByIdCache = deleteTicketsByIdCache;
const deleteTicketsFieldsCache = (tickets, del_fields) => __awaiter(void 0, void 0, void 0, function* () {
    const redis = yield redisConn();
    if (!redis)
        return;
    //  if (redis.status !== 'connect') return
    const pipeline = redis.pipeline();
    if (tickets && tickets.length > 0) {
        try {
            for (let i = 0; i < tickets.length; i++) {
                pipeline.hdel(`ticket:${tickets[i]['id']}`, del_fields);
            }
            yield pipeline.exec(() => { console.log(`Tickets cache contact updated!`); });
        }
        catch (error) {
            console.log('There was an error on deleteTicketsFieldsByContactsCache function: ', error);
        }
    }
    // await redis.quit()
});
exports.deleteTicketsFieldsCache = deleteTicketsFieldsCache;
const updateTicketsByContactsCache = (oldNumber, newName, newNumber) => __awaiter(void 0, void 0, void 0, function* () {
    const redis = yield redisConn();
    if (!redis)
        return;
    //  if (redis.status !== 'connect') return
    const pipeline = redis.pipeline();
    const tickets = yield searchTicketCache(oldNumber);
    if (tickets && tickets.length > 0) {
        try {
            for (let i = 0; i < tickets.length; i++) {
                tickets[i]['contact.name'] = newName;
                tickets[i].escaped_name = ContactsCache_1.escapeCharCache(newName);
                tickets[i]['contact_number'] = newNumber;
                pipeline.hmset(`ticket:${tickets[i]['id']}`, tickets[i]);
            }
            yield pipeline.exec(() => { console.log(`updateTicketsByContactsCache Tickets cache contact updated!`); });
        }
        catch (error) {
            console.log('There was an error on updateTicketsByContactsCache function: ', error);
        }
    }
    // await redis.quit()
});
exports.updateTicketsByContactsCache = updateTicketsByContactsCache;
const deleteTicketsByContactsCache = (number) => __awaiter(void 0, void 0, void 0, function* () {
    const redis = yield redisConn();
    if (!redis)
        return;
    //  if (redis.status !== 'connect') return
    const pipeline = redis.pipeline();
    const tickets = yield searchTicketCache(number);
    if (tickets && tickets.length > 0) {
        try {
            for (let i = 0; i < tickets.length; i++) {
                pipeline.del(`ticket:${tickets[i]['id']}`);
            }
            yield pipeline.exec(() => { console.log(`Tickets cache number ${tickets[0]['contact_number']} deleted!`); });
        }
        catch (error) {
            console.log('There was an error on deleteTicketsByContactsCache function: ', error);
        }
    }
    // await redis.quit()
});
exports.deleteTicketsByContactsCache = deleteTicketsByContactsCache;
const deleteTicketCache = (hash) => __awaiter(void 0, void 0, void 0, function* () {
    const redis = yield redisConn();
    if (!redis)
        return;
    //  if (redis.status !== 'connect') return
    yield redis.del(hash);
    // await redis.quit()
});
function searchTicketCache(search, offset, limit) {
    return __awaiter(this, void 0, void 0, function* () {
        const redis = yield redisConn();
        if (!redis)
            return;
        // if(redis.status!=='connect') return null 
        search = ContactsCache_1.escapeCharCache(search);
        let response = undefined;
        if (offset != undefined && limit != undefined) {
            response = yield redis.call('FT.SEARCH', 'idx_ticket', `(@escaped_name:*${search}*)|(@contact_number:*${search}*)`, 'LIMIT', offset, limit, 'SORTBY', 'status', 'DESC');
        }
        else {
            response = yield redis.call('FT.SEARCH', 'idx_ticket', `(@escaped_name:*${search}*)|(@contact_number:*${search}*)`);
        }
        // await redis.quit()
        // console.log('response: ', response)
        if (response.length === 1) {
            return [];
        }
        const results = [];
        for (let n = 2; n < response.length; n += 2) {
            const result = {};
            const fieldNamesAndValues = response[n];
            for (let m = 0; m < fieldNamesAndValues.length; m += 2) {
                const k = fieldNamesAndValues[m];
                const v = fieldNamesAndValues[m + 1];
                result[k] = v;
            }
            results.push(result);
        }
        return results;
    });
}
exports.searchTicketCache = searchTicketCache;
