import {
  Controller,
  Get,
  Post,
  Put,
  Delete,
  Route,
  Security,
  Tags,
  Body,
  Path,
  Request,
  Response,
} from "tsoa";
import { AppDataSource } from "../database/data-source";
import HttpSuccess from "../interfaces/http-success";
import HttpStatusCode from "../interfaces/http-status";
import HttpError from "../interfaces/http-error";
import { Not } from "typeorm";
import { InsigniaType, CreateInsigniaType, UpdateInsigniaType } from "../entities/InsigniaType";
import { Insignia } from "../entities/Insignia";
import permission from "../interfaces/permission";
import { RequestWithUser } from "../middlewares/user";
import { setLogDataDiff } from "../interfaces/utils";
@Route("api/v1/org/insignia/insignia-type")
@Tags("InsigniaType")
@Security("bearerAuth")
@Response(
  HttpStatusCode.INTERNAL_SERVER_ERROR,
  "เกิดข้อผิดพลาด ไม่สามารถแสดงรายการได้ กรุณาลองใหม่ในภายหลัง",
)
export class InsigniaTypeController extends Controller {
  private insigniaTypeRepository = AppDataSource.getRepository(InsigniaType);
  private insigniaRepository = AppDataSource.getRepository(Insignia);

  /**
   * API เพิ่มข้อมูลลำดับชั้นเครื่องราชอิสริยาภรณ์
   *
   * @summary ORG_ - เพิ่มข้อมูลลำดับชั้นเครื่องราชอิสริยาภรณ์ (ADMIN) #
   *
   */
  @Post("")
  async CreateInsigniaType(
    @Body() requestBody: CreateInsigniaType,
    @Request() request: RequestWithUser,
  ) {
    const insigniaType = Object.assign(new InsigniaType(), requestBody);
    if (!insigniaType) {
      throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูล");
    }

    const rowRepeated = await this.insigniaTypeRepository.findOne({
      where: {
        name: requestBody.name,
        isActive: requestBody.isActive,
      },
    });
    if (rowRepeated) {
      throw new HttpError(HttpStatusCode.NOT_FOUND, "ข้อมูล Row นี้มีอยู่ในระบบแล้ว");
    }
    const before = null;
    insigniaType.createdUserId = request.user.sub;
    insigniaType.createdFullName = request.user.name;
    insigniaType.lastUpdateUserId = request.user.sub;
    insigniaType.lastUpdateFullName = request.user.name;
    insigniaType.createdAt = new Date();
    insigniaType.lastUpdatedAt = new Date();
    await this.insigniaTypeRepository.save(insigniaType, { data: request });
    setLogDataDiff(request, { before, after: insigniaType });
    return new HttpSuccess(insigniaType.id);
  }

  /**
   * API แก้ไขลำดับชั้นเครื่องราชอิสริยาภรณ์
   *
   * @summary แก้ไขลำดับชั้นเครื่องราชอิสริยาภรณ์ (ADMIN)
   *
   * @param {string} id  Id ลำดับชั้นเครื่องราชอิสริยาภรณ์
   */
  @Put("{id}")
  async UpdateInsigniaType(
    @Path() id: string,
    @Body() requestBody: UpdateInsigniaType,
    @Request() request: RequestWithUser,
  ) {
    const insigniaType = await this.insigniaTypeRepository.findOne({
      where: { id: id },
    });
    if (!insigniaType) {
      throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลลำดับชั้นเครื่องราชอิสริยาภรณ์นี้");
    }
    const rowRepeated = await this.insigniaTypeRepository.findOne({
      where: {
        id: Not(id),
        name: requestBody.name,
        isActive: requestBody.isActive,
      },
    });
    if (rowRepeated) {
      throw new HttpError(HttpStatusCode.NOT_FOUND, "ข้อมูล Row นี้มีอยู่ในระบบแล้ว");
    }
    const before = structuredClone(insigniaType);
    insigniaType.lastUpdateUserId = request.user.sub;
    insigniaType.lastUpdateFullName = request.user.name;
    insigniaType.lastUpdatedAt = new Date();
    this.insigniaTypeRepository.merge(insigniaType, requestBody);
    await this.insigniaTypeRepository.save(insigniaType, { data: request });
    setLogDataDiff(request, { before, after: insigniaType });
    return new HttpSuccess(insigniaType.id);
  }

  /**
   * API ลบลำดับชั้นเครื่องราชอิสริยาภรณ์
   *
   * @summary ORG_ - ลบลำดับชั้นเครื่องราชอิสริยาภรณ์ (ADMIN) #
   *
   * @param {string} id  Id ลำดับชั้นเครื่องราชอิสริยาภรณ์
   */
  @Delete("{id}")
  async delete(@Path() id: string, @Request() request: RequestWithUser) {
    const delInsigniaType = await this.insigniaTypeRepository.findOne({ where: { id } });
    if (!delInsigniaType) {
      throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลลำดับชั้นเครื่องราชอิสริยาภรณ์นี้");
    }
    const Insignia = await this.insigniaRepository.find({
      where: { insigniaTypeId: id },
    });
    if (Insignia.length > 0) {
      throw new HttpError(
        HttpStatusCode.NOT_FOUND,
        "ไม่สามารถลบได้ เนื่องจากพบข้อมูลที่ตารางเครื่องราชอิสริยาภรณ์",
      );
    }
    await this.insigniaTypeRepository.remove(delInsigniaType, { data: request });
    return new HttpSuccess();
  }

  /**
   * API รายการลำดับชั้นเครื่องราชอิสริยาภรณ์ Active
   *
   * @summary ORG_ - รายการลำดับชั้นเครื่องราชอิสริยาภรณ์ Active (ADMIN) #
   *
   */
  @Get("active")
  async GetInsigniaType_Active() {
    const insigniaType_Active = await this.insigniaTypeRepository.find({
      where: { isActive: true, insignias: { isActive: true } },
      order: { name: "ASC", insignias: { level: "ASC" } },
      relations: ["insignias"],
    });
    return new HttpSuccess(insigniaType_Active);
  }

  /**
   * API รายละเอียดข้อมูลลำดับชั้นเครื่องราชอิสริยาภรณ์
   *
   * @summary ORG_037 - รายละเอียดข้อมูลลำดับชั้นเครื่องราชอิสริยาภรณ์ (ADMIN) #
   *
   * @param {string} id  Id ลำดับชั้นเครื่องราชอิสริยาภรณ์
   */
  @Get("{id}")
  async GetInsigniaTypeById(@Path() id: string) {
    const insigniaType = await this.insigniaTypeRepository.findOne({
      relations: ["insignias"],
      select: ["id", "name", "createdAt", "lastUpdatedAt", "lastUpdateFullName", "isActive"],
      where: { id: id },
    });
    if (!insigniaType) {
      throw new HttpError(
        HttpStatusCode.NOT_FOUND,
        "ไม่พบข้อมูลลำดับชั้นเครื่องราชอิสริยาภรณ์ นี้",
      );
    }
    return new HttpSuccess(insigniaType);
  }

  /**
   * API รายการลำดับชั้นเครื่องราชอิสริยาภรณ์
   *
   * @summary ORG_ - รายการลำดับชั้นเครื่องราชอิสริยาภรณ์ (ADMIN) #
   *
   */
  @Get()
  async GetInsigniaType() {
    const insigniaTypeAll = await this.insigniaTypeRepository.find({
      select: ["id", "name", "createdAt", "lastUpdatedAt", "lastUpdateFullName", "isActive"],
      order: { name: "ASC" },
    });
    return new HttpSuccess(insigniaTypeAll);
  }

  /**
   * API รายการลำดับชั้นเครื่องราชอิสริยาภรณ์ (เช็คสิทธิ์)
   *
   * @summary ORG_ - รายการลำดับชั้นเครื่องราชอิสริยาภรณ์ (ADMIN) #เช็คสิทธิ์
   *
   * @param {string} path  เมนูเช็คสิทธิ์
   */
  @Get("path/{path}")
  async GetInsigniaTypePath(@Path() path: string, @Request() request: RequestWithUser) {
    path = path.toLocaleUpperCase();
    let getPermission: string = "";
    if (path == "RECORD") {
      getPermission = "SYS_INSIGNIA_RECORD";
    } else if (path == "ALLOCATE") {
      getPermission = "SYS_INSIGNIA_ALLOCATE";
    } else if (path == "BORROW") {
      getPermission = "SYS_INSIGNIA_BORROW";
    } else {
      getPermission = "SYS_INSIGNIA_RECORD";
    }
    await new permission().PermissionList(request, getPermission);
    const insigniaTypeAll = await this.insigniaTypeRepository.find({
      select: ["id", "name", "createdAt", "lastUpdatedAt", "lastUpdateFullName", "isActive"],
      where: { isActive: true },
      order: { name: "ASC" },
    });
    return new HttpSuccess(insigniaTypeAll);
  }
}
