import ApiRequest from "@services/Api.Service";
import * as Yup from "yup";
import { ApiError } from "@core/Models/Server.Error.model";
import {
    AppointmentAdminByClientView,
    DeleteAppointmentParams,
    FindAppointmentsByUserParams,
    FindAppointmentsByCollaboratorParams,
    FindAppointmentsByUserPaginatedParams,
    FindAppointmentsByCollaboratorPaginatedParams,
    PaginatedAppointmentEventByClientResult,
} from "@core/Models/Appointments.model";
import { UserAppointmentView, UserAppointmentViewParams } from "@core/Models/Views.model";
import { ApiVoidResult } from "@core/Models/Api.VoidResult.type";

const schemaCancellAppointment = Yup.object().shape({
    id: Yup.string().required("El turno no ha sido especificado."),
    validation: Yup.boolean().oneOf([true], "No es posible cancelar la reserva."),
    sessionUser: Yup.string().required("Para cancelar un turno debe iniciar sesión."),
});

export const deleteAppointment = async (data: DeleteAppointmentParams): Promise<ApiVoidResult> => {
    return new Promise<ApiVoidResult>((resolve, reject) => {
        schemaCancellAppointment
            .validate(data, { abortEarly: true })
            .then(() => {
                resolve(ApiRequest.post<ApiVoidResult>("appointments/delete", data));
            })
            .catch((error) => {
                reject(new ApiError(500, error.message));
            });
    });
};

const schemaFindAppointmentByUser = Yup.object().shape({
    sessionUser: Yup.string().required("Para crear un turno debe iniciar sesión."),
});

export const findAppointmentByUser = async (
    data: FindAppointmentsByUserParams
): Promise<AppointmentAdminByClientView> => {
    return new Promise<AppointmentAdminByClientView>((resolve, reject) => {
        schemaFindAppointmentByUser
            .validate(data, { abortEarly: true })
            .then(() => {
                resolve(
                    ApiRequest.post<AppointmentAdminByClientView>("appointments/find-by-user", data)
                );
            })
            .catch((error) => {
                reject(new ApiError(500, error.message));
            });
    });
};

export const findAppointmentByCollaborator = async (
    data: FindAppointmentsByCollaboratorParams
): Promise<AppointmentAdminByClientView> => {
    return new Promise<AppointmentAdminByClientView>((resolve, reject) => {
        schemaFindAppointmentByUser
            .validate(data, { abortEarly: true })
            .then(() => {
                resolve(
                    ApiRequest.post<AppointmentAdminByClientView>("appointments/find-by-collaborator", data)
                );
            })
            .catch((error) => {
                reject(new ApiError(500, error.message));
            });
    });
};

const schemaFindAppointmentByUserPaginated = Yup.object().shape({
    sessionUser: Yup.string().required("Para crear un turno debe iniciar sesión."),
    page: Yup.number().required(),
    limit: Yup.number().required(),
});

export const findAppointmentByUserPaginated = async (
    data: FindAppointmentsByUserPaginatedParams
): Promise<PaginatedAppointmentEventByClientResult> => {
    return new Promise<PaginatedAppointmentEventByClientResult>((resolve, reject) => {
        schemaFindAppointmentByUserPaginated
            .validate(data, { abortEarly: true })
            .then(() => {
                resolve(ApiRequest.post<PaginatedAppointmentEventByClientResult>("appointments/find-by-user-paginated", data));
            })
            .catch((error) => {
                reject(new ApiError(500, error.message));
            });
    });
};

const schemaFindAppointmentByCollaboratorPaginated = Yup.object().shape({
    sessionUser: Yup.string().required("Para crear un turno debe iniciar sesión."),
    page: Yup.number().required(),
    limit: Yup.number().required(),
});

export const findAppointmentByCollaboratorPaginated = async (
    data: FindAppointmentsByCollaboratorPaginatedParams
): Promise<PaginatedAppointmentEventByClientResult> => {
    return new Promise<PaginatedAppointmentEventByClientResult>((resolve, reject) => {
        schemaFindAppointmentByCollaboratorPaginated
            .validate(data, { abortEarly: true })
            .then(() => {
                resolve(ApiRequest.post<PaginatedAppointmentEventByClientResult>("appointments/find-by-collaborator-paginated", data));
            })
            .catch((error) => {
                reject(new ApiError(500, error.message));
            });
    });
};

const schemaViewAppointment = Yup.object().shape({
    appointmentId: Yup.string().required("No se ha proporcionado ningun turno."),
    sessionUser: Yup.string().required("Para visuzlizar el turno debe iniciar sesión."),
});

export const viewAppointment = async (
    data: UserAppointmentViewParams
): Promise<UserAppointmentView> => {
    return new Promise<UserAppointmentView>((resolve, reject) => {
        schemaViewAppointment
            .validate(data, { abortEarly: true })
            .then(() => {
                resolve(ApiRequest.post<UserAppointmentView>("views/appointment", data));
            })
            .catch((error) => {
                reject(new ApiError(500, error.message));
            });
    });
};
