console.clear();

require('log-timestamp');
const cors = require('cors');
const DateSystem = require('date-and-time')
const express = require('express');
const bodyParser = require('body-parser')
const {USSD} = require('./USSD.js');
const {DoCommand} = require('./db.js');
const {SendSuccess, SendFailure} = require('./sms.js');


const limit = 1024;
const app = express();
app.use(express.json());
app.use(express.urlencoded({extended: true}));

app.use(bodyParser.raw({limit, extended: true}));
app.use(bodyParser.urlencoded({limit, extended: true}))
app.use(bodyParser.json({limit, extended: true}))

app.use(express.json());
app.use(express.urlencoded({extended: true}));


var corsOptions = {
      origin: 'https://app.nikan-ussd.ir',
}
app.use(cors(corsOptions));

function GetUserId(recordId) {
  return new Promise(async resolve => {
    try {
      const qu = await DoCommand("SELECT mobile,date,Code FROM Appointment WHERE IsReject=0 AND IsAccept=0 AND Id=?", [recordId]);
      if (qu.status) {
        if (qu.results.length === 1) {
          const [{mobile, date, Code}] = qu.results;
          const mob = '98' + mobile.substring(1, mobile.length);
          const res = GetRecipCode(date, Code);
          return resolve({mob, res, error: null, status: true, c: 4});
        } else {
          return resolve({status: false, c: 0});
        }
      } else {
        return resolve({status: false, c: 1});
      }
    } catch (e) {
      return resolve({status: false, error: e.toString(), c: 2});
    }
    return resolve({status: false, error: "", c: 3});
  });
}

function escapeRegExp(string) {
  return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
}

function replaceAll(str, find, replace) {
  return str.replace(new RegExp(escapeRegExp(find), 'g'), replace);
}

function GetRecipCode(date, code) {
  const res = ("000" + code).slice(-4);
  return replaceAll(date + '-' + res, '/', '').slice(-9);
}

let logs = [];
app.get('/', (req, res) => {
  // const mob = "989192457489";
  // const rers = "0801-0000";
  // const time = "1402/05/10 14:13:38"
  // SendSuccess(mob, rers, time, async function ({text, body}) {
  //   res.set('Content-Type', 'application/json');
  //   res.status(200).send({text, body})
  // });
  res.status(200).send({body:"ok"})
  
});

app.get('/logs', (req, res) => {
  res.set('Content-Type', 'application/json');
  res.status(200).send(logs);
});

app.get('/clear', (req, res) => {
  res.set('Content-Type', 'application/json');
  logs = [];
  res.status(200).send(logs);
});

app.get('/ussd.ptx', async (req, res) => {
    const query =  req.query;
    logs.push(query);
    if (logs.length > 10) logs.splice(0, logs.length - 10);
    if(query.hasOwnProperty("mobile") && query.hasOwnProperty("call") && query.hasOwnProperty("session_id") && query.hasOwnProperty("password")){
        const {mobile, call, session_id, password} = query;
        const text = await USSD.Executed.call(USSD, mobile, call, session_id, password);
        res.set('Content-Type', 'text/html');
        res.status(200).send(text);
    } else {
        res.set('Content-Type', 'text/html');
        res.status(200).send("error");
    }
});

app.get('/logs-today', async function (req, res) {
  res.set('Content-Type', 'application/json');
  const now = new Date();
  const date = DateSystem.format(now, 'YYYY/MM/DD', true);
  const {
    status,
    results
  } = await DoCommand("Select * from Appointment where `date` = ? or `reserveDate` = ? ", [date, date]);
  res.status(200).send(status ? results : []);
});

app.get('/logs-filter/:meli?/:mobi?/:t1?/:t2?/', async function (req, res) {
  const keys = Object.keys(req.params);
  const params = [];
  let query = "SELECT * from Appointment where ", output = [];
  if (keys.length > 0) {
    if (req.params.hasOwnProperty("meli")) {
      const codeMeli = req.params.meli;
      if (typeof codeMeli !== 'undefined' && codeMeli !== 'null') {
        if (codeMeli.length >= 4) {
          query += "codeMeli LIKE ?"
          params.push('%' + codeMeli + '%');
        }
      }
    }
    
    if (req.params.hasOwnProperty("meli")) {
      const mobile = req.params.mobi;
      if (typeof mobile !== 'undefined') {
        if (mobile.length >= 4 && mobile !== 'null') {
          if (params.length > 0) query += " AND ";
          query += "mobile LIKE ?"
          params.push('%' + mobile + '%');
        }
      }
    }
    
    
    if (params.length > 0){
        //time condition
        if(req.params.hasOwnProperty("t1") || req.params.hasOwnProperty("t2")){
            //from date t1
            let t1 = req.params.t1;
            
            //to date t2
            let t2 = req.params.t2;
            
            if(t1 == "null") t1 = null;
            if(t2 == "null") t2 = null;
            
            if(t1 !=null || t2 != null ) {
                query += " AND ";
                if(t1 != null && t2 != null){
                    query += " ((str_to_date(`date`,'%Y/%m/%d') >= ? and str_to_date(`date`,'%Y/%m/%d') <= ?) OR (str_to_date(`date`,'%Y/%m/%d') >= ? and str_to_date(`date`,'%Y/%m/%d') <= ?) or (str_to_date(`reserveDate`,'%Y/%m/%d') >= ? and str_to_date(`reserveDate`,'%Y/%m/%d') <= ?) OR (str_to_date(`reserveDate`,'%Y/%m/%d') >= ? and str_to_date(`reserveDate`,'%Y/%m/%d')` <= ?))";
                    params.push(t1,t2, t1,t2, t1,t2, t1,t2,);
                } else {
                    //part query
                    if(t1==null){
                        query += "(str_to_date(`date`,'%Y/%m/%d') <= ? OR str_to_date(`reserveDate`,'%Y/%m/%d') <= ?)";
                        params.push(t2,t2);
                    }
                    if(t2==null){
                        query += "(str_to_date(`date`,'%Y/%m/%d') >= ? OR str_to_date(`reserveDate`,'%Y/%m/%d') >= ?)";
                        params.push(t1,t1);
                    }
                }
            }
        }
    }
    
    
    
    const {status, results} = await DoCommand(query, params);
    output = status ? results : [];
  }
  res.status(200).send(output);
});

app.get('/delete/:id', async function (req, res) {
  const Id = req.params.id;
  const query = "DELETE FROM Appointment where Id=?";
  await DoCommand(query, [Id]);
  res.status(200).send({});
});

app.get('/cancel/:id/:sms', async function (req, res) {
  const {id: Id, sms} = req.params;
  if (parseInt(sms) === 1) {
    const number = await GetUserId(Id);
    if (number.status) {
      const {mob, res} = number;
      SendFailure(mob, async function ({text, body}) {
        const e = body[0] + text;
        const query = `UPDATE Appointment
                       SET IsReject=1,
                           Sms=?
                       WHERE Id = ?`;
        await DoCommand(query, [e, Id]);
        res.status(200).send({});
      });
    } else {
      res.status(200).send({number});
    }
  } else {
    const e = "لغو اس ام اس";
    const query = `UPDATE Appointment
                   SET IsReject=1,
                       Sms=?
                   WHERE Id = ?`;
    await DoCommand(query, [e, Id]);
    res.status(200).send({});
  }
});


app.post('/accept/:id', async function (req, res) {
  const {id: Id} = req.params;
  const {utc, time} = req.body;
  if (Id !== undefined && utc !== undefined && time !== undefined) {
    const number = await GetUserId(Id);
    if (number.status) {
      const {res: results, mob} = number;
      SendSuccess(mob, results, time, async function ({text, body}) {
        const e = body[0] + text;
        const query = `UPDATE Appointment
                       SET IsAccept=1,
                           Sms=?,
                           reserveTime=?,
                           persianTime=?
                       WHERE Id = ?`;
        await DoCommand(query, [e, utc, time, Id]);
        res.status(200).send({});
      });
    } else {
      res.status(200).send({number});
    }
  } else res.status(200).send({});
});

const server = app.listen(0, function () {
  var host = server.address().address
  var port = server.address().port
  console.log("Example app listening at http://%s:%s", host, port)
});