import { HttpCodes } from '../../config/Errors';
import { db } from '../../settings';
import { ResultSetHeader } from 'mysql2';
import { ErrorResponseC, SuccessResponseC } from '../services.response';
import courseLogs, { ICourseLogs, courseLogger } from './course.logs';
import { formatString } from '../../utils/Strings';
import { VideoServices } from './video.service';
import { DocumentServices } from './document.service';
export class ChapterServices {
static createChapter = async (
course_id: number,
chapter: ChapterI
): Promise<ResponseT> => {
try {
const sqlInsertQuery =
'INSERT INTO chapters (course_id, title, position) VALUES (?, ?, ?)';
const [result]: any = await db.query<ResultSetHeader[]>(sqlInsertQuery, [
course_id,
chapter.title,
chapter.position,
]);
const chapterId = result.insertId;
const resp: ICode<ICourseLogs> = courseLogs.CREATE_CHAPTER_SUCCESS;
const msg = formatString(resp.message, {
chapterId,
});
courseLogger.info(msg, { type: resp.type });
return new SuccessResponseC(resp.type, {}, msg, HttpCodes.Created.code);
} catch (err) {
const msg = formatString(courseLogs.CHAPTER_ERROR_GENERIC.message, {
error: (err as Error)?.message || '',
});
courseLogger.error(msg, err as Error);
return new ErrorResponseC(
courseLogs.CHAPTER_ERROR_GENERIC.type,
HttpCodes.InternalServerError.code,
msg
);
}
};
static createChapters = async (
course_id: number,
chapters: ChapterI[]
): Promise<ResponseT> => {
try {
const sqlInsertQuery =
'INSERT INTO chapters (course_id, title, position) VALUES (?, ?, ?)';
for (const chapter of chapters) {
const { title, position, data } = chapter;
// if data item has video_id then it is a video
const videos = data?.filter(
(item) => (item as VideoI).videoLength
) as VideoI[];
// documents = rest of the data items
const documents = data?.filter(
(item) => !(item as VideoI).videoLength
) as DocumentI[];
const [result]: any = await db.query<ResultSetHeader[]>(
sqlInsertQuery,
[course_id, title, position]
);
const chapterId = result.insertId;
chapter.chapter_id = chapterId;
if (videos.length > 0) {
videos.forEach((video) => (video.chapter_id = chapterId));
const videosResponse = await VideoServices.insertVideos(videos);
if (videosResponse instanceof ErrorResponseC) {
return videosResponse;
}
}
if (documents.length > 0) {
documents.forEach((document) => (document.chapter_id = chapterId));
const documentsResponse = await DocumentServices.insertDocuments(
documents
);
if (documentsResponse instanceof ErrorResponseC) {
return documentsResponse;
}
}
}
const resp: ICode<ICourseLogs> = courseLogs.CREATE_CHAPTERS_SUCCESS;
const msg = formatString(resp.message, {
chapterIds: chapters.map((chapter) => chapter.chapter_id).join(', '),
});
courseLogger.info(msg, { type: resp.type });
return new SuccessResponseC(
resp.type,
chapters,
msg,
HttpCodes.Created.code
);
} catch (err) {
const msg = formatString(courseLogs.CHAPTER_ERROR_GENERIC.message, {
error: (err as Error)?.message || '',
});
courseLogger.error(msg, err as Error);
return new ErrorResponseC(
courseLogs.CHAPTER_ERROR_GENERIC.type,
HttpCodes.InternalServerError.code,
msg
);
}
};
static updateChapters = async (chapters: ChapterI[]): Promise<ResponseT> => {
try {
const sqlUpdateQuery =
'UPDATE chapters SET title = ?, position = ? WHERE chapter_id = ?';
const values: any = chapters.map((chapter) => [
chapter.title,
chapter.position,
chapter.chapter_id,
]);
for (const value of values) {
// const [result]: any =
await db.query<ResultSetHeader>(sqlUpdateQuery, [
value.title,
value.position,
value.chapter_id,
]);
// if (result.affectedRows === 0) {
// const msg = formatString(courseLogs.CHAPTER_ERROR_NOT_FOUND.message, {
// chapterId: chapters.map((chapter) => chapter.chapter_id).join(', '),
// });
// courseLogger.error(msg);
// return new ErrorResponseC(
// courseLogs.CHAPTER_ERROR_NOT_FOUND.type,
// HttpCodes.NotFound.code,
// msg
// );
// }
}
const resp: ICode<ICourseLogs> = courseLogs.UPDATE_CHAPTER_SUCCESS;
const msg = formatString(resp.message, {
chapterIds: chapters.map((chapter) => chapter.chapter_id).join(', '),
});
courseLogger.info(msg, { type: resp.type });
return new SuccessResponseC(resp.type, {}, msg, HttpCodes.Accepted.code);
} catch (err) {
const msg = formatString(courseLogs.CHAPTER_ERROR_GENERIC.message, {
error: (err as Error)?.message || '',
});
courseLogger.error(msg, err as Error);
return new ErrorResponseC(
courseLogs.CHAPTER_ERROR_GENERIC.type,
HttpCodes.InternalServerError.code,
msg
);
}
};
static deleteChapters = async (chapter_ids: number[]): Promise<ResponseT> => {
try {
const sqlDeleteQuery = 'DELETE FROM chapters WHERE chapter_id IN (?)';
const [result]: any = await db.query<ResultSetHeader[]>(sqlDeleteQuery, [
chapter_ids,
]);
if (result.affectedRows === 0) {
const msg = formatString(courseLogs.CHAPTER_ERROR_NOT_FOUND.message, {
chapterId: chapter_ids.join(', '),
});
courseLogger.error(msg);
return new ErrorResponseC(
courseLogs.CHAPTER_ERROR_NOT_FOUND.type,
HttpCodes.NotFound.code,
msg
);
}
const resp: ICode<ICourseLogs> = courseLogs.DELETE_CHAPTERS_SUCCESS;
const msg = formatString(resp.message, {
chapterIds: chapter_ids.join(', '),
});
courseLogger.info(msg, { type: resp.type });
return new SuccessResponseC(resp.type, {}, msg, HttpCodes.Accepted.code);
} catch (err) {
const msg = formatString(courseLogs.CHAPTER_ERROR_GENERIC.message, {
error: (err as Error)?.message || '',
});
courseLogger.error(msg, err as Error);
return new ErrorResponseC(
courseLogs.CHAPTER_ERROR_GENERIC.type,
HttpCodes.InternalServerError.code,
msg
);
}
};
static identifyAddedChapters = (
oldChapters: ChapterI[],
newChapters: ChapterI[]
) => {
const addedChapters = newChapters.filter(
(newChapter) =>
!oldChapters.some(
(oldChapter) => oldChapter.chapter_id === newChapter.chapter_id
)
);
return addedChapters;
};
static identifyDeletedChapters = (
oldChapters: ChapterI[],
newChapters: ChapterI[]
) => {
const deletedChapters = oldChapters.filter(
(oldChapter) =>
!newChapters.some(
(newChapter) => newChapter.chapter_id === oldChapter.chapter_id
)
);
return deletedChapters;
};
static identifyUpdatedChapters = (
oldChapters: ChapterI[],
newChapters: ChapterI[]
) => {
const updatedChapters = newChapters.filter((newChapter) =>
oldChapters.some(
(oldChapter) =>
oldChapter.chapter_id === newChapter.chapter_id &&
(oldChapter.title !== newChapter.title ||
oldChapter.position !== newChapter.position)
)
);
return updatedChapters;
};
static filterChapters = (
chapters: ChapterI[],
deletedChapters: ChapterI[]
) => {
const filteredChapters = chapters.filter(
(chapter) =>
!deletedChapters.some(
(deletedChapter) => deletedChapter.chapter_id === chapter.chapter_id
)
);
return filteredChapters;
};
}