import { ApiValidationError } from "../../Models/Server.Error.model";
import {
    Body,
    FormField,
    UploadedFile,
    Controller,
    Middlewares,
    Post,
    Response,
    Route,
    SuccessResponse,
} from "tsoa";

import { UsersService } from "./Users.Service";
import {
    FindUsersParams,
    UpdateUserParams,
    PaginateUsersParams,
    PaginateUsersResults,
    IUserView,
    ChangePasswordParams,
    FindCollaboratorByEmailParams,
    CollaboratorView,
    DeleteUserParams,
    SavePayerEmailParams,
    GetPayerEmailParams,
    PayerEmailResult,
    CheckUserPhoneParams,
    UserAssistanceInfo,
} from "../../Models/Users/Users.Interface";
import { authenticateMiddleware } from "../../middleware/authentication";
import { ApiVoidResult } from "../../Models/Api.VoidResult.type";

@Route("users/check-phone")
@Middlewares(authenticateMiddleware)
export class CheckUserPhoneController extends Controller {
    @Response<ApiValidationError>(500, "Ha ocurrido un error")
    @SuccessResponse(200, "Done")
    @Post()
    public async checkUserPhone(
        @Body() requestBody: CheckUserPhoneParams
    ): Promise<boolean | ApiValidationError> {
        try {
            const result = await new UsersService().checkUserPhone(requestBody);
            this.setStatus(200);
            return result;
        } catch (e) {
            const errorOccurred: Error = e as Error;
            this.setStatus(500);
            return new ApiValidationError(500, errorOccurred.message);
        }
    }
}

@Route("users/save-payer-email")
@Middlewares(authenticateMiddleware)
export class SavePayerEmailController extends Controller {
    @Response<ApiValidationError>(500, "Ha ocurrido un error")
    @SuccessResponse(200, "Done")
    @Post()
    public async setPayerEmail(
        @Body() requestBody: SavePayerEmailParams
    ): Promise<ApiVoidResult | ApiValidationError> {
        try {
            await new UsersService().setPayerEmail(requestBody);
            this.setStatus(200);
            return {
                success: true,
                message: "Done",
            };
        } catch (e) {
            const errorOccurred: Error = e as Error;
            this.setStatus(500);
            return new ApiValidationError(500, errorOccurred.message);
        }
    }
}

@Route("users/get-payer-email")
@Middlewares(authenticateMiddleware)
export class GetPayerEmailController extends Controller {
    @Response<ApiValidationError>(500, "Ha ocurrido un error")
    @SuccessResponse(200, "Done")
    @Post()
    public async getPayerEmail(
        @Body() requestBody: GetPayerEmailParams
    ): Promise<PayerEmailResult | ApiValidationError> {
        try {
            const result = await new UsersService().getPayerEmail(requestBody);
            this.setStatus(200);
            return result;
        } catch (e) {
            const errorOccurred: Error = e as Error;
            this.setStatus(500);
            return new ApiValidationError(500, errorOccurred.message);
        }
    }
}

@Route("users/delete")
@Middlewares(authenticateMiddleware)
export class DeleteUserController extends Controller {
    @Response<ApiValidationError>(500, "Ha ocurrido un error")
    @SuccessResponse(200, "El usuario fue eliminado")
    @Post()
    public async deleteUser(
        @Body() requestBody: DeleteUserParams
    ): Promise<ApiVoidResult | ApiValidationError> {
        try {
            await new UsersService().deleteUser(requestBody);
            this.setStatus(200);
            return {
                success: true,
                message: "Done",
            };
        } catch (e) {
            const errorOccurred: Error = e as Error;
            this.setStatus(500);
            return new ApiValidationError(500, errorOccurred.message);
        }
    }
}

@Route("users/paginate")
@Middlewares(authenticateMiddleware)
export class CreateUserController extends Controller {
    @Response<ApiValidationError>(500, "Ha ocurrido un error")
    @SuccessResponse(200, "Done")
    @Post()
    public async paginateUsers(
        @Body() requestBody: PaginateUsersParams
    ): Promise<PaginateUsersResults | ApiValidationError> {
        try {
            const users = await new UsersService().paginateUsers(requestBody);
            this.setStatus(200);
            return users;
        } catch (e) {
            const errorOccurred: Error = e as Error;
            this.setStatus(500);
            return new ApiValidationError(500, errorOccurred.message);
        }
    }
}

@Route("users/get")
@Middlewares(authenticateMiddleware)
export class GetUserController extends Controller {
    @Response<ApiValidationError>(500, "Ha ocurrido un error")
    @SuccessResponse(200, "Done")
    @Post()
    public async getUser(
        @Body() requestBody: FindUsersParams
    ): Promise<IUserView | ApiValidationError> {
        try {
            const user = await new UsersService().getUserById(requestBody);
            this.setStatus(200);
            return user;
        } catch (e) {
            const errorOccurred: Error = e as Error;
            this.setStatus(500);
            return new ApiValidationError(500, errorOccurred.message);
        }
    }
}

@Route("users/get-by-email")
@Middlewares(authenticateMiddleware)
export class GetUserByEmailController extends Controller {
    @Response<ApiValidationError>(500, "Ha ocurrido un error")
    @SuccessResponse(200, "Done")
    @Post()
    public async getUserByEmail(
        @Body() requestBody: FindCollaboratorByEmailParams
    ): Promise<CollaboratorView | null | ApiValidationError> {
        try {
            const user = await new UsersService().findByEmail(requestBody);
            this.setStatus(200);
            return user;
        } catch (e) {
            const errorOccurred: Error = e as Error;
            this.setStatus(500);
            return new ApiValidationError(500, errorOccurred.message);
        }
    }
}

@Route("users/change-password")
@Middlewares(authenticateMiddleware)
export class ChangeUserPasswordController extends Controller {
    @Response<ApiValidationError>(500, "Ha ocurrido un error")
    @SuccessResponse(200, "La contraseña fue modificada con exito")
    @Post()
    public async changeUserPassword(
        @Body() requestBody: ChangePasswordParams
    ): Promise<ApiVoidResult | ApiValidationError> {
        try {
            await new UsersService().changeUserPassword(requestBody);
            this.setStatus(200);
            return {
                success: true,
                message: "Done",
            };
        } catch (e) {
            const errorOccurred: Error = e as Error;
            this.setStatus(500);
            return new ApiValidationError(500, errorOccurred.message);
        }
    }
}

@Route("users/update")
@Middlewares(authenticateMiddleware)
export class UpdateUserController extends Controller {
    @Response<ApiValidationError>(500, "Ha ocurrido un error")
    @SuccessResponse(200, "La compañia fue modificada con exito")
    @Post()
    public async updateUser(
        @Body() requestBody: UpdateUserParams
    ): Promise<ApiVoidResult | ApiValidationError> {
        try {
            await new UsersService().updateUser(requestBody);
            this.setStatus(200);
            return {
                success: true,
                message: "Done",
            };
        } catch (e) {
            const errorOccurred: Error = e as Error;
            this.setStatus(500);
            return new ApiValidationError(500, errorOccurred.message);
        }
    }
}

@Route("users/upload-avatar")
@Middlewares([authenticateMiddleware])
export class UploadUserIconController extends Controller {
    @Response<ApiValidationError>(500, "Ha ocurrido un error")
    @SuccessResponse(200, "El archivo fue cargado con exito")
    @Post()
    public async uploadUserIcon(
        @FormField() sessionUser: string,
        @UploadedFile() file: Express.Multer.File
    ): Promise<ApiVoidResult | ApiValidationError> {
        try {
            await new UsersService().setUserIcon({
                sessionUser,
                file,
            });
            this.setStatus(200);
            return {
                success: true,
                message: "Done",
            };
        } catch (e) {
            const errorOccurred: Error = e as Error;
            this.setStatus(500);
            return new ApiValidationError(500, errorOccurred.message);
        }
    }
}

@Route("users/assistance-info")
@Middlewares(authenticateMiddleware)
export class GetUserAssistanceInfoController extends Controller {
    @Response<ApiValidationError>(500, "Ha ocurrido un error")
    @SuccessResponse(200, "Done")
    @Post()
    public async getUserAssistanceInfo(
        @Body() requestBody: FindUsersParams
    ): Promise<UserAssistanceInfo | ApiValidationError> {
        try {
            const user = await new UsersService().getUserAssistanceInfo(requestBody);
            this.setStatus(200);
            return user;
        } catch (e) {
            const errorOccurred: Error = e as Error;
            this.setStatus(500);
            return new ApiValidationError(500, errorOccurred.message);
        }
    }
}
