import axios from "axios";
import {
  Controller,
  Post,
  Delete,
  Route,
  Security,
  Tags,
  Body,
  Path,
  Request,
  Response,
  Get,
} from "tsoa";
import HttpError from "../interfaces/http-error";
import HttpStatusCode from "../interfaces/http-status";
import { addLogSequence } from "../interfaces/utils";
import HttpSuccess from "../interfaces/http-success";

interface CachedToken {
  token: string;
  expiry: Date;
}
const API_URL_BANGKOK = "https://exprofile.bangkok.go.th/API";
const clientId = "e5f6ad6ce374177eef023bf5d0c018b6";
const clientSecret = "5EhOvN5DwHOKakupqT9FmCk7MOwpT3zLqLPkPh4ZhJpxBN2nMG@2022";

class TokenCache {
  private static cache: Map<string, CachedToken> = new Map();

  static get(key: string): string | null {
    const cached = this.cache.get(key);
    if (!cached) return null;
    return cached.token;
  }

  static set(key: string, token: string): void {
    this.cache.set(key, { token, expiry: new Date(Date.now() + 50 * 60 * 1000) });
  }

  static delete(key: string): void {
    this.cache.delete(key);
  }
}

@Route("api/v1/org/ex/retirement")
@Tags("ExRetirement")
@Security("bearerAuth")
export class ExRetirementController extends Controller {
  @Post()
  async getExRetirement(
    @Body()
    requestBody: {
      type: string; //ประเภท
      retireYear: string; //ปีที่เกษียณ
      citizenID: string; //เลขบัตรประชาชน
      firstNameTH: string; //ชื่อ
      lastNameTH: string; //นามสกุล
      page: number; //หน้า
    },
  ) {
    let retryCount = 0;
    const maxRetries = 2;

    while (retryCount < maxRetries) {
      try {
        const token = await getToken(clientId, clientSecret);

        if (!token) {
          throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่สามารถขอ Token ได้");
        }

        // const scope = requestBody.type === "officer" ? "getOfficerRetireData" : "";
        const scope = "getOfficerRetireData";
        const startRecord = requestBody.page !== 1 ? (requestBody.page - 1) * 25 : 0;

        const formData = new FormData();
        formData.append("scope", scope);
        formData.append("startRecord", startRecord.toString());
        formData.append("retireYear", requestBody.retireYear);
        formData.append("citizenID", requestBody.citizenID);
        formData.append("firstNameTH", requestBody.firstNameTH);
        formData.append("lastNameTH", requestBody.lastNameTH);
        formData.append("officerTypeID", requestBody.type === "officer" ? "1" : "2");

        const res = await axios.post(API_URL_BANGKOK + "/getData", formData, {
          headers: {
            Authorization: `Bearer ${token}`,
          },
        });

        // return res.data;
        return new HttpSuccess(res.data.data);
      } catch (error: any) {
        if (error.response?.status === 500 && retryCount < maxRetries - 1) {
          TokenCache.delete(`${clientId}:${clientSecret}`);
          retryCount++;
          continue;
        }
        throw new HttpError(HttpStatusCode.INTERNAL_SERVER_ERROR, "ไม่สามารถติดต่อ API ได้");
      }
    }
  }

  @Get("/document/{documentId}")
  async getDocument(@Path("documentId") officerDocumentID: string, @Request() req: any) {
    let retryCount = 0;
    const maxRetries = 2;
    while (retryCount < maxRetries) {
      try {
        const token = await getToken(clientId, clientSecret);
        if (!token) {
          throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่สามารถขอ Token ได้");
        }

        const formData = new FormData();
        formData.append("scope", "getOfficerRetireFile");
        formData.append("officerDocumentID", officerDocumentID);

        const res = await axios.post(API_URL_BANGKOK + "/getData", formData, {
          headers: {
            Authorization: `Bearer ${token}`,
          },
          responseType: "arraybuffer",
        });

        if (!req.res.headersSent && !req.res.destroyed) {
          // Set response headers
          req.res.setHeader("Content-Type", "application/pdf");
          req.res.setHeader("Content-Disposition", `inline; filename="${officerDocumentID}.pdf"`);
          req.res.setHeader("Content-Length", res.data.byteLength.toString());

          req.res.end(Buffer.from(res.data));
          return;
        }
      } catch (error: any) {
        if (error.response?.status === 500 && retryCount < maxRetries - 1) {
          TokenCache.delete(`${clientId}:${clientSecret}`);
          retryCount++;
          continue;
        }
        throw new HttpError(HttpStatusCode.INTERNAL_SERVER_ERROR, "ไม่สามารถติดต่อ API ได้");
      }
    }
  }
}

async function getToken(ClientID: string, ClientSecret: string): Promise<string> {
  const cacheKey = `${ClientID}:${ClientSecret}`;

  // ลองหา token ใน cache ก่อน
  const cachedToken = TokenCache.get(cacheKey);
  if (cachedToken) {
    return cachedToken;
  }

  // ถ้าไม่มีใน cache ให้ขอใหม่
  try {
    const formData = new FormData();
    formData.append("ClientID", ClientID);
    formData.append("ClientSecret", ClientSecret);
    const res = await axios.post(API_URL_BANGKOK + "/authorize", formData, {
      headers: {
        "Content-Type": "application/json",
      },
    });
    const token = res.data.token;
    TokenCache.set(cacheKey, token);
    return token;
  } catch (error) {
    return Promise.reject({ message: "Error occurred", error });
  }
}

// function post retire data to exprofile system
export async function PostRetireToExprofile(
  request: any,
  citizenID: string,
  prefix: string,
  firstName: string,
  lastName: string,
  retireYear: string,
  positionName: string,
  positionTypeName: string,
  positionLevelName: string,
  retireDate: Date,
  organizeName: string, // child4Name child3Name child2Name child1Name rootName
  retireTypeName: string, // เช่น เกษียณ, ขอโอนออก, ลาออก, ปลดออก, ไล่ออก, ...
) {
  // check NODE_ENV ถ้าเป็น production ถึงจะทำการส่งข้อมูลไปยัง exprofile
  const NODE_ENV = process.env.NODE_ENV || "development";
  if (NODE_ENV !== "production") {
    return;
  }

  let retryCount = 0;
  const maxRetries = 2;

  while (retryCount < maxRetries) {
    try {
      const token = await getToken(clientId, clientSecret);

      if (!token) {
        throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่สามารถขอ Token ได้");
      }

      const scope = "importOfficerRetireData";
      const body = {
        scope: scope,
        data: {
          citizenID: citizenID,
          prenameTH: prefix,
          firstNameTH: firstName,
          lastNameTH: lastName,
          retireYear,
          positionNameTH: positionName,
          positionTypeNameTH: positionTypeName,
          positionLevelNameTH: positionLevelName,
          retireDate,
          organizeNameTH: organizeName,
          retireTypeNameTH: retireTypeName,
        },
      };

      const res = await axios.post(API_URL_BANGKOK + "/importData", body, {
        headers: {
          Authorization: `Bearer ${token}`,
          "Content-Type": "application/json",
        },
      });

      return res.data;
    } catch (error: any) {
      if (error.response?.status === 500 && retryCount < maxRetries - 1) {
        TokenCache.delete(`${clientId}:${clientSecret}`);
        retryCount++;
        continue;
      }

      // เช็ค request ก่อนเรียก addLogSequence (สำหรับ cronjob ที่ส่ง null)
      if (request) {
        addLogSequence(request, {
          action: "request",
          status: "error",
          description: "unconnected to exprofile api",
          request: {
            method: "POST",
            url: API_URL_BANGKOK + "/importData",
            response: JSON.stringify(error),
          },
        });
      }

      throw new HttpError(HttpStatusCode.INTERNAL_SERVER_ERROR, "ไม่สามารถติดต่อ API ได้");
    }
  }
}
