import HttpStatus from "../interfaces/http-status";
import HttpError from "../interfaces/http-error";
import moment from "moment";
import { promisify } from "util";

class Extension {
  public static ConvertToDateTime(value: any) {
    if (value != "" && value != null) {
      if (isNaN(value)) {
        let date = moment(value, "DD/MM/YYYY").toDate();
        let year = date.getFullYear();
        if (year < 1800) {
          return null;
        } else if (year > 2500) {
          date.setFullYear(year - 543);
        }
        return date;
      } else {
        if (value.toString().length == 4) {
          if (value < 1800) {
            return null;
          } else if (value > 2500) {
            return new Date(value - 543, 0, 1);
          }
        }
      }
    }
    return null;
  }
  public static ConvertToDateTimeV2(value: any) {
    if (value != "" && value != null) {
      if (value.toString().length > 4) {
        const chars = value.split("/");
        let year = Number(chars[2]) + 1900;
        let month = Extension.MonthToNumber(chars[1]);
        return new Date(year, month, chars[0]);
      } else {
        if (value.toString().length == 4) {
          if (value < 1800) {
            return null;
          } else if (value > 2500) {
            return new Date(value - 543, 0, 1);
          }
        }
      }
    }
    return null;
  }

  public static CheckRelationship(value: any) {
    if (value != "" && value != null) {
      switch (value) {
        case 1:
          return "โสด";
        case 2:
          return "สมรส";
        case 3:
          return "หย่า";
        case 4:
          return "หม้าย";
        default:
          return "";
      }
    }
    return "";
  }

  public static ToThaiMonth(value: number) {
    switch (value) {
      case 1:
        return "มกราคม";
      case 2:
        return "กุมภาพันธ์";
      case 3:
        return "มีนาคม";
      case 4:
        return "เมษายน";
      case 5:
        return "พฤษภาคม";
      case 6:
        return "มิถุนายน";
      case 7:
        return "กรกฎาคม";
      case 8:
        return "สิงหาคม";
      case 9:
        return "กันยายน";
      case 10:
        return "ตุลาคม";
      case 11:
        return "พฤศจิกายน";
      case 12:
        return "ธันวาคม";
      default:
        return "";
    }
  }
  public static MonthToNumber(value: string) {
    switch (value.trim().toUpperCase()) {
      case "JAN":
        return 0;
      case "FEB":
        return 1;
      case "MAR":
        return 2;
      case "APR":
        return 3;
      case "MAY":
        return 4;
      case "JUN":
        return 5;
      case "JUL":
        return 6;
      case "AUG":
        return 7;
      case "SEP":
        return 8;
      case "OCT":
        return 9;
      case "NOV":
        return 10;
      case "DEC":
        return 11;
      default:
        return 0;
    }
  }

  public static ToThaiShortMonth(value: number) {
    switch (value) {
      case 1:
        return "ม.ค.";
      case 2:
        return "ก.พ.";
      case 3:
        return "มี.ค.";
      case 4:
        return "เม.ย.";
      case 5:
        return "พ.ค.";
      case 6:
        return "มิ.ย.";
      case 7:
        return "ก.ค.";
      case 8:
        return "ส.ค.";
      case 9:
        return "ก.ย.";
      case 10:
        return "ต.ค.";
      case 11:
        return "พ.ย.";
      case 12:
        return "ธ.ค.";
      default:
        return "";
    }
  }

  public static ToThaiYear(value: number) {
    if (value < 2400) return value + 543;
    else return value;
  }

  public static ToCeYear(value: number) {
    if (value >= 2400) return value - 543;
    else return value;
  }

  public static ToThaiNumber(value: string) {
    if (value == null) return "";
    let arabicNumbers = "0123456789";
    let thaiNumbers = "๐๑๒๓๔๕๖๗๘๙";
    let result = "";
    for (let digit of value) {
      let index = arabicNumbers.indexOf(digit);
      if (index >= 0) {
        result += thaiNumbers[index];
      } else {
        result += digit;
      }
    }
    return result;
  }

  public static ToThaiFullDate(value: Date) {
    if (value == null || value == undefined || isNaN(value.getTime())) return "";
    let yy = value.getFullYear() < 2400 ? value.getFullYear() + 543 : value.getFullYear();
    return (
      "วันที่ " +
      value.getDate() +
      " เดือน " +
      Extension.ToThaiMonth(value.getMonth() + 1) +
      " พ.ศ. " +
      yy
    );
  }
  public static ToThaiFullDate2(value: Date) {
    if (value == null || value == undefined || isNaN(value.getTime())) return "";
    let yy = value.getFullYear() < 2400 ? value.getFullYear() + 543 : value.getFullYear();
    return value.getDate() + " " + Extension.ToThaiMonth(value.getMonth() + 1) + " " + yy;
  }

  public static ToThaiShortDate(value: Date) {
    if (value == null || value == undefined || isNaN(value.getTime())) return "";
    let yy = value.getFullYear() < 2400 ? value.getFullYear() + 543 : value.getFullYear();
    return (
      "วันที่ " +
      value.getDate() +
      " " +
      Extension.ToThaiShortMonth(value.getMonth() + 1) +
      " " +
      yy.toString().slice(-2)
    );
  }

  public static ToThaiShortDate_noPrefix(value: Date) {
    if (value == null || value == undefined || isNaN(value.getTime())) return "";
    let yy = value.getFullYear() < 2400 ? value.getFullYear() + 543 : value.getFullYear();
    return (
      value.getDate() +
      " " +
      Extension.ToThaiShortMonth(value.getMonth() + 1) +
      " " +
      yy.toString().slice(-2)
    );
  }

  public static ToThaiShortDate_monthYear(value: Date) {
    if (value == null || value == undefined || isNaN(value.getTime())) return "";
    let yy = value.getFullYear() < 2400 ? value.getFullYear() + 543 : value.getFullYear();
    return (
      value.getDate() + " เดือน " + Extension.ToThaiMonth(value.getMonth() + 1) + " พ.ศ. " + yy
    );
  }

  public static ToThaiShortDate_monthYear2(value: Date) {
    if (value == null || value == undefined || isNaN(value.getTime())) return "";
    let yy = value.getFullYear() < 2400 ? value.getFullYear() + 543 : value.getFullYear();
    return value.getDate() + " " + Extension.ToThaiMonth(value.getMonth() + 1) + " พ.ศ. " + yy;
  }

  public static ToThaiShortYear(value: Date) {
    if (value == null || value == undefined || isNaN(value.getTime())) return "";
    let yy = value.getFullYear() < 2400 ? value.getFullYear() + 543 : value.getFullYear();
    return yy.toString();
  }

  public static sumObjectValues(array: any, propertyName: any) {
    let sum = 0;
    for (let i = 0; i < array.length; i++) {
      if (array[i][propertyName] !== undefined) {
        sum += array[i][propertyName];
      }
    }
    return sum;
  }

  public static CheckCitizen(value: string) {
    let citizen = value;
    if (citizen == null || citizen == "" || citizen == undefined) {
      throw new HttpError(HttpStatus.NOT_FOUND, "กรุณากรอกข้อมูลรหัสบัตรประจำตัวประชาชน");
    }
    if (citizen.length !== 13) {
      throw new HttpError(
        HttpStatus.NOT_FOUND,
        "กรุณากรอกข้อมูลรหัสบัตรประจำตัวประชาชนให้ครบ 13 หลัก",
      );
    }
    const citizenIdDigits = citizen.toString().split("").map(Number);
    const cal =
      citizenIdDigits[0] * 13 +
      citizenIdDigits[1] * 12 +
      citizenIdDigits[2] * 11 +
      citizenIdDigits[3] * 10 +
      citizenIdDigits[4] * 9 +
      citizenIdDigits[5] * 8 +
      citizenIdDigits[6] * 7 +
      citizenIdDigits[7] * 6 +
      citizenIdDigits[8] * 5 +
      citizenIdDigits[9] * 4 +
      citizenIdDigits[10] * 3 +
      citizenIdDigits[11] * 2;
    const calStp2 = cal % 11;
    const chkDigit = (11 - calStp2) % 10;

    if (citizenIdDigits[12] !== chkDigit) {
      throw new HttpError(HttpStatus.NOT_FOUND, "ข้อมูลรหัสบัตรประจำตัวประชาชนไม่ถูกต้อง");
    }
    return citizen;
  }

  public static CalculateGovAge(
    appointDate: Date,
    plusYear: number = 0,
    subtractYear: number = 0,
  ): number {
    if (appointDate == null || appointDate == undefined) return 0;
    // Check for Invalid Date
    if (isNaN(appointDate.getTime())) return 0;
    const now = new Date();
    if (now.getMonth() - appointDate.getMonth() >= 6) {
      return now.getFullYear() - appointDate.getFullYear() + 1 + plusYear - subtractYear;
    } else {
      return now.getFullYear() - appointDate.getFullYear() + plusYear - subtractYear;
    }
  }

  public static CalculateAge(appointDate: Date, plusYear: number = 0, subtractYear: number = 0) {
    if (appointDate == null || appointDate == undefined) return 0;
    // Check for Invalid Date
    if (isNaN(appointDate.getTime())) return 0;
    let currentDate = new Date().getTime();
    let appointDateTime = new Date(appointDate).getTime();
    let ageInMilliseconds = currentDate - appointDateTime;
    let ageInDays = ageInMilliseconds / (1000 * 60 * 60 * 24);
    let years = Math.floor(ageInDays / 365.25) + plusYear - subtractYear;
    return years;
  }

  public static CalculateAgeStrV2(
    date: Date,
    plusYear: number = 0,
    subtractYear: number = 0,
    method?: string,
  ) {
    if (date == null || date == undefined) return "";
    // Check for Invalid Date
    if (isNaN(date.getTime())) return "";
    const currentDate = new Date();
    if (date > currentDate && method !== "GET") {
      throw new Error("วันเกิดต้องไม่มากกว่าวันที่ปัจจุบัน");
    } else if (date > currentDate && method === "GET") {
      return "";
    }

    let years = currentDate.getFullYear() - date.getFullYear();
    let months = 0;
    let days = 0;

    if (
      currentDate.getMonth() < date.getMonth() ||
      (currentDate.getMonth() === date.getMonth() && currentDate.getDate() < date.getDate())
    ) {
      years--;
      months = 12 - date.getMonth() + currentDate.getMonth();

      if (currentDate.getDate() < date.getDate()) {
        months--;
        let lastMonthDays = 0;
        if (currentDate.getMonth() === 0) {
          lastMonthDays = new Date(currentDate.getFullYear() - 1, 11, 0).getDate();
        } else {
          lastMonthDays = new Date(currentDate.getFullYear(), currentDate.getMonth(), 0).getDate();
          days = lastMonthDays - date.getDate() + currentDate.getDate();
        }
      } else {
        days = currentDate.getDate() - date.getDate();
      }
    } else {
      months = currentDate.getMonth() - date.getMonth();

      if (currentDate.getDate() < date.getDate()) {
        months--;
        let lastMonthDays = 0;
        if (currentDate.getMonth() === 0) {
          lastMonthDays = new Date(currentDate.getFullYear() - 1, 11, 0).getDate();
        } else {
          lastMonthDays = new Date(currentDate.getFullYear(), currentDate.getMonth(), 0).getDate();
          days = lastMonthDays - date.getDate() + currentDate.getDate();
        }
      } else {
        days = currentDate.getDate() - date.getDate();
      }
    }
    years += plusYear - subtractYear;
    return `${years} ปี ${months} เดือน ${days} วัน`;
  }

  public static deleteRedisByID(type: string, id: string) {
    const redis = require("redis");
    const REDIS_HOST = process.env.REDIS_HOST;
    const REDIS_PORT = process.env.REDIS_PORT;
    const redisClient = redis.createClient({
      host: REDIS_HOST,
      port: REDIS_PORT,
    });
    const delAsync = promisify(redisClient.del).bind(redisClient);
    const deleteKey = delAsync(type + id);
    return;
  }

  public static textPoint(val: number | undefined) {
    if (val == undefined) val = -1;
    if (val >= 0 && val <= 60) return "ต้องปรับปรุง";
    if (val >= 60 && val <= 69) return "พอใช้";
    if (val >= 70 && val <= 79) return "ดี";
    if (val >= 80 && val <= 89) return "ดีมาก";
    if (val >= 90 && val <= 100) return "ดีเด่น";
    else return "-";
  }

  public static toDateOnlyString(date: Date): string {
    if (date == null || date == undefined || isNaN(date.getTime())) return "";
    return (
      date.getFullYear() +
      "-" +
      String(date.getMonth() + 1).padStart(2, "0") +
      "-" +
      String(date.getDate()).padStart(2, "0")
    );
  }
}

export default Extension;
