import { Body, Controller, Delete, Get, Path, Post, Request, Route, Security, Tags } from "tsoa";
import { AppDataSource } from "../database/data-source";
import HttpSuccess from "../interfaces/http-success";
import HttpStatus from "../interfaces/http-status";
import HttpError from "../interfaces/http-error";
import { RequestWithUser } from "../middlewares/user";
import { Profile } from "../entities/Profile";
import { CreateProfileAvatar, ProfileAvatar } from "../entities/ProfileAvatar";
import permission from "../interfaces/permission";
import { setLogDataDiff } from "../interfaces/utils";
import CallAPI from "../interfaces/call-api";
@Route("api/v1/org/profile/avatar")
@Tags("ProfileAvatar")
@Security("bearerAuth")
export class ProfileAvatarController extends Controller {
  private profileRepository = AppDataSource.getRepository(Profile);
  private avatarRepository = AppDataSource.getRepository(ProfileAvatar);

  @Get("{profileId}")
  public async getAvatar(@Path() profileId: string, @Request() req: RequestWithUser) {
    let _workflow = await new permission().Workflow(req, profileId, "SYS_REGISTRY_OFFICER");
    if (_workflow == false)
      await new permission().PermissionOrgUserGet(req, "SYS_REGISTRY_OFFICER", profileId);
    const lists = await this.avatarRepository.find({
      where: { profileId: profileId },
      order: { createdAt: "ASC" },
    });
    return new HttpSuccess(lists);
  }

  @Get("profileId/{id}")
  async getProfile(@Path() id: string, @Request() req: RequestWithUser) {
    try {
      // let _workflow = await new permission().Workflow(req, id, "SYS_REGISTRY_OFFICER");
      // if (_workflow == false)
      // await new permission().PermissionOrgUserGet(req, "SYS_REGISTRY_OFFICER", id);
      const profile = await this.profileRepository.findOne({
        where: { id },
      });

      if (!profile) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูล");

      return new HttpSuccess(profile);
    } catch (error) {
      console.error("Error in getProfile:", error);

      if (error instanceof HttpError) {
        throw error;
      }

      throw new HttpError(HttpStatus.INTERNAL_SERVER_ERROR, "เกิดข้อผิดพลาดภายในระบบ");
    }
  }

  @Get("profileId-admin/{id}")
  async getProfileAdmin(@Path() id: string) {
    const profile = await this.profileRepository.findOne({
      where: { id },
    });

    if (!profile) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูล");

    return new HttpSuccess(profile);
  }

  @Get("select/{profileId}/{id}")
  public async selectAvatar(
    @Path() profileId: string,
    @Path() id: string,
    @Request() req: RequestWithUser,
  ) {
    await new permission().PermissionOrgUserGet(req, "SYS_REGISTRY_OFFICER", profileId);
    const result = await this.avatarRepository.findOneBy({ id: id });
    if (!result) {
      throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูล");
    }
    const profile = await this.profileRepository.findOne({
      where: { id: profileId },
      relations: ["profileAvatars"],
    });
    if (!profile) {
      throw new HttpError(HttpStatus.BAD_REQUEST, "ไม่พบ profile ดังกล่าว");
    }
    await Promise.all(
      profile.profileAvatars.map(async (item: any) => {
        item.isActive = false;
        await this.avatarRepository.save(item);
      }),
    );
    result.isActive = true;
    profile.avatar = result.avatar;
    profile.avatarName = result.avatarName;
    await this.avatarRepository.save(result);
    await this.profileRepository.save(profile);
    return new HttpSuccess();
  }

  @Post()
  public async newAvatar(@Request() req: RequestWithUser, @Body() body: CreateProfileAvatar) {
    const profile = await this.profileRepository.findOne({
      where: { id: body.profileId },
    });

    if (!profile) {
      throw new HttpError(HttpStatus.BAD_REQUEST, "ไม่พบ profile ดังกล่าว");
    }
    await new permission().PermissionOrgUserUpdate(req, "SYS_REGISTRY_OFFICER", profile.id);

    const data = new ProfileAvatar();

    const meta = {
      createdUserId: req.user.sub,
      createdFullName: req.user.name,
      lastUpdateUserId: req.user.sub,
      lastUpdateFullName: req.user.name,
      createdAt: new Date(),
      lastUpdatedAt: new Date(),
    };

    Object.assign(data, { ...body, ...meta });

    const _profile = await this.profileRepository.findOne({
      where: { id: body.profileId },
      relations: ["profileAvatars"],
    });

    if (!_profile) {
      throw new HttpError(HttpStatus.BAD_REQUEST, "ไม่พบ profile ดังกล่าว");
    }
    await Promise.all(
      _profile.profileAvatars.map(async (item: any) => {
        item.isActive = false;
        await this.avatarRepository.save(item);
      }),
    );

    await this.avatarRepository.save(data);
    let avatar = `ทะเบียนประวัติ/โปรไฟล์/${profile.id}`;
    let fileName = `profile-${data.id}`;
    const before = null;
    data.isActive = true;
    data.avatar = avatar;
    data.avatarName = fileName;
    await this.avatarRepository.save(data, { data: req });
    setLogDataDiff(req, { before, after: data });
    profile.avatar = avatar;
    profile.avatarName = fileName;
    await this.profileRepository.save(profile, { data: req });

    return new HttpSuccess({ avatar: avatar, avatarName: fileName });
  }

  @Delete("{avatarId}")
  public async deleteAvatar(@Path() avatarId: string, @Request() req: RequestWithUser) {
    const _record = await this.avatarRepository.findOneBy({ id: avatarId });
    if (_record) {
      await new permission().PermissionOrgUserDelete(
        req,
        "SYS_REGISTRY_OFFICER",
        _record.profileId,
      );

      if (_record.isActive) {
        const profile = await this.profileRepository.findOne({
          where: { id: _record.profileId },
        });
        if (profile) {
          profile.avatar = null;
          profile.avatarName = null;
          await this.profileRepository.save(profile, { data: req });
        }
      }

      await new CallAPI().DeleteFile(req, `${_record?.avatar}/${_record?.avatarName}`);
    }
    if (!_record) {
      throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูล");
    }

    await this.avatarRepository.remove(_record, { data: req });

    return new HttpSuccess();
  }
}
