import { WEB_SERVICE_PREFIX } from '@/constants/service';
import { request } from '../request';
import {
  type ServiceRequestResult,
  mapServiceResult,
  normalizeNullableStringId,
  normalizeStringId,
  safeJsonRequestConfig
} from './shared';

const WORK_REPORT_PREFIX = `${WEB_SERVICE_PREFIX}/project/work-reports`;
const WEEKLY_PREFIX = `${WORK_REPORT_PREFIX}/weekly`;
const MONTHLY_PREFIX = `${WORK_REPORT_PREFIX}/monthly`;
const PROJECT_PREFIX = `${WORK_REPORT_PREFIX}/project`;

type StringIdResponse = string | number;
type MaybeStringIdResponse = string | number | null | undefined;

type PageResponse<T> = {
  total: number | string;
  list: T[];
};

type ReviewItemResponse = Omit<Api.WorkReport.Common.PersonalReportReviewItem, 'id'> & {
  id?: MaybeStringIdResponse;
};

type PlanItemResponse = Omit<Api.WorkReport.Common.PersonalReportPlanItem, 'id'> & {
  id?: MaybeStringIdResponse;
};

type WeeklyTravelSegmentResponse = Omit<Api.WorkReport.Weekly.WeeklyReportTravelSegment, 'id'> & {
  id?: MaybeStringIdResponse;
};

type WeeklyReportResponse = Omit<
  Api.WorkReport.Weekly.WeeklyReport,
  'id' | 'reporterId' | 'supervisorUserId' | 'reviewItems' | 'planItems' | 'travelSegments'
> & {
  id: StringIdResponse;
  reporterId: StringIdResponse;
  supervisorUserId: StringIdResponse;
  reviewItems?: ReviewItemResponse[] | null;
  planItems?: PlanItemResponse[] | null;
  travelSegments?: WeeklyTravelSegmentResponse[] | null;
};

type MonthlyReportResponse = Omit<
  Api.WorkReport.Monthly.MonthlyReport,
  'id' | 'reporterId' | 'supervisorUserId' | 'reviewItems' | 'planItems'
> & {
  id: StringIdResponse;
  reporterId: StringIdResponse;
  supervisorUserId: StringIdResponse;
  reviewItems?: ReviewItemResponse[] | null;
  planItems?: PlanItemResponse[] | null;
};

type MemberSnapshotResponse = Omit<Api.WorkReport.Project.WorkReportMemberSnapshot, 'userId'> & {
  userId: StringIdResponse;
};

type ProjectReportItemResponse = Omit<Api.WorkReport.Project.ProjectReportItem, 'id'> & {
  id?: MaybeStringIdResponse;
};

type ProjectReportResponse = Omit<
  Api.WorkReport.Project.ProjectReport,
  'id' | 'projectId' | 'projectOwnerId' | 'projectMemberSnapshot' | 'supervisorUserId' | 'currentItems' | 'nextItems'
> & {
  id: StringIdResponse;
  projectId: StringIdResponse;
  projectOwnerId: StringIdResponse;
  projectMemberSnapshot?: MemberSnapshotResponse[] | null;
  supervisorUserId: StringIdResponse;
  currentItems?: ProjectReportItemResponse[] | null;
  nextItems?: ProjectReportItemResponse[] | null;
};

type ApprovalRecordResponse = Omit<
  Api.WorkReport.Common.WorkReportApprovalRecord,
  'id' | 'statusLogId' | 'auditorUserId'
> & {
  id: StringIdResponse;
  statusLogId: StringIdResponse;
  auditorUserId: StringIdResponse;
};

type MonthlyApprovalRecordResponse = Omit<
  Api.WorkReport.Monthly.MonthlyReportApprovalRecord,
  'id' | 'statusLogId' | 'auditorUserId' | 'employeeSignatureFileId' | 'supervisorSignatureFileId'
> & {
  id: StringIdResponse;
  statusLogId: StringIdResponse;
  auditorUserId: StringIdResponse;
  employeeSignatureFileId?: MaybeStringIdResponse;
  supervisorSignatureFileId?: MaybeStringIdResponse;
};

type MonthlySignOffDetailResponse = {
  report: MonthlyReportResponse;
  latestApprovalRecord?: MonthlyApprovalRecordResponse | null;
};

type ProjectOptionResponse = Omit<Api.WorkReport.Project.ProjectReportOwnerProjectOption, 'id'> & {
  id: StringIdResponse;
};

type TeamReportUnsubmittedReportResponse = Omit<
  Api.WorkReport.Common.TeamReportUnsubmittedReport,
  'userId' | 'projectId'
> & {
  userId: StringIdResponse;
  projectId?: StringIdResponse | null;
};

type TeamReportSummaryResponse = Omit<
  Api.WorkReport.Common.TeamReportSummary,
  'unsubmittedReports' | 'periodStartDate' | 'periodEndDate'
> & {
  unsubmittedReports?: TeamReportUnsubmittedReportResponse[] | null;
  periodStartDate?: unknown;
  periodEndDate?: unknown;
};

function normalizeBooleanFlag(value: boolean | number | string | null | undefined) {
  if (typeof value === 'boolean') return value;
  if (typeof value === 'number') return value === 1;
  if (typeof value === 'string') {
    const normalized = value.trim().toLowerCase();
    return !['', '0', 'false', 'n', 'no'].includes(normalized);
  }
  return false;
}

function normalizeApprovalConclusion(value: unknown) {
  const conclusion = String(value || '')
    .trim()
    .toLowerCase();

  if (conclusion === 'approve') return 'approved';
  if (conclusion === 'reject') return 'rejected';

  return conclusion;
}

function normalizeDateText(value: unknown) {
  if (value === null || value === undefined) return undefined;
  const text = String(value).trim();
  const commaDateMatch = text.match(/^(\d{4}),(\d{1,2}),(\d{1,2})$/);

  if (commaDateMatch) {
    const [, year, month, day] = commaDateMatch;
    return `${year}-${month.padStart(2, '0')}-${day.padStart(2, '0')}`;
  }

  return text || undefined;
}

function normalizeTotal(total: number | string) {
  const value = Number(total);
  return Number.isFinite(value) ? Math.max(0, value) : 0;
}

function sumWorkHours(items: Array<{ workHours?: number | string | null }> = []) {
  return items.reduce((sum, item) => {
    const value = Number(item.workHours ?? 0);
    return Number.isFinite(value) ? sum + value : sum;
  }, 0);
}

function normalizeReportTotalWorkHours(
  totalWorkHours: number | string | null | undefined,
  fallbackTotalWorkHours: number
) {
  const normalizedTotal = Number(totalWorkHours ?? 0);

  if (
    (totalWorkHours === null ||
      totalWorkHours === undefined ||
      totalWorkHours === '' ||
      (Number.isFinite(normalizedTotal) && normalizedTotal === 0)) &&
    fallbackTotalWorkHours > 0
  ) {
    return fallbackTotalWorkHours;
  }

  return totalWorkHours ?? 0;
}

function appendValue(query: URLSearchParams, key: string, value: unknown) {
  if (value === null || value === undefined || value === '') return;
  query.append(key, String(value));
}

function appendArray(query: URLSearchParams, key: string, values?: Array<string | null | undefined> | null) {
  values?.forEach(value => appendValue(query, key, value));
}

function appendNullableArrayFlag(
  query: URLSearchParams,
  key: string,
  values?: Array<string | null | undefined> | null
) {
  if (values === null || values === undefined) return;

  if (!values.length) {
    query.append(key, '');
    return;
  }

  appendArray(query, key, values);
}

function createBasePageQuery(params: Api.WorkReport.Common.WorkReportBaseSearchParams = {}) {
  const query = new URLSearchParams();

  appendValue(query, 'pageNo', params.pageNo ?? 1);
  appendValue(query, 'pageSize', params.pageSize ?? 10);
  appendValue(query, 'keyword', params.keyword);
  appendValue(query, 'statusCode', params.statusCode);
  appendValue(query, 'supervisorName', params.supervisorName);
  appendArray(query, 'periodStartDate', params.periodStartDate);
  appendArray(query, 'submitTime', params.submitTime);

  return query;
}

function createWeeklyPageQuery(params: Api.WorkReport.Weekly.WeeklyReportSearchParams = {}) {
  const query = createBasePageQuery(params);
  appendNullableArrayFlag(query, 'reporterIds', params.reporterIds);
  appendValue(query, 'isBusinessTrip', params.isBusinessTrip);
  return query.toString();
}

function createMonthlyPageQuery(params: Api.WorkReport.Monthly.MonthlyReportSearchParams = {}) {
  const query = createBasePageQuery(params);
  appendNullableArrayFlag(query, 'reporterIds', params.reporterIds);
  appendValue(query, 'signOffStatus', params.signOffStatus);
  return query.toString();
}

function createProjectPageQuery(params: Api.WorkReport.Project.ProjectReportSearchParams = {}) {
  const query = createBasePageQuery(params);
  appendNullableArrayFlag(query, 'projectOwnerIds', params.projectOwnerIds);
  appendValue(query, 'projectId', params.projectId);
  appendValue(query, 'flag', params.flag);
  return query.toString();
}

function normalizeReviewItem(item: ReviewItemResponse): Api.WorkReport.Common.PersonalReportReviewItem {
  return {
    ...item,
    id: normalizeNullableStringId(item.id) ?? undefined
  };
}

function normalizePlanItem(item: PlanItemResponse): Api.WorkReport.Common.PersonalReportPlanItem {
  return {
    ...item,
    id: normalizeNullableStringId(item.id) ?? undefined
  };
}

function normalizeWeeklyTravelSegment(
  item: WeeklyTravelSegmentResponse
): Api.WorkReport.Weekly.WeeklyReportTravelSegment {
  return {
    ...item,
    id: normalizeNullableStringId(item.id) ?? undefined,
    startDate: normalizeDateText(item.startDate),
    endDate: normalizeDateText(item.endDate)
  };
}

function normalizeWeeklyReport(response: WeeklyReportResponse): Api.WorkReport.Weekly.WeeklyReport {
  const fallbackTotalWorkHours = sumWorkHours(response.reviewItems ?? []);

  return {
    ...response,
    id: normalizeStringId(response.id),
    reporterId: normalizeStringId(response.reporterId),
    supervisorUserId: normalizeStringId(response.supervisorUserId),
    reporterDeptName: response.reporterDeptName ?? null,
    reporterPostName: response.reporterPostName ?? null,
    statusName: response.statusName || response.statusCode,
    allowEdit: normalizeBooleanFlag(response.allowEdit),
    terminal: normalizeBooleanFlag(response.terminal),
    isBusinessTrip: normalizeBooleanFlag(response.isBusinessTrip),
    periodStartDate: normalizeDateText(response.periodStartDate) ?? '',
    periodEndDate: normalizeDateText(response.periodEndDate) ?? '',
    totalWorkHours: normalizeReportTotalWorkHours(response.totalWorkHours, fallbackTotalWorkHours),
    submitTime: response.submitTime ?? null,
    reviewItems: response.reviewItems?.map(normalizeReviewItem) ?? [],
    planItems: response.planItems?.map(normalizePlanItem) ?? [],
    travelSegments: response.travelSegments?.map(normalizeWeeklyTravelSegment) ?? []
  };
}

function normalizeMonthlyReport(response: MonthlyReportResponse): Api.WorkReport.Monthly.MonthlyReport {
  const fallbackTotalWorkHours = sumWorkHours(response.reviewItems ?? []);

  return {
    ...response,
    id: normalizeStringId(response.id),
    reporterId: normalizeStringId(response.reporterId),
    supervisorUserId: normalizeStringId(response.supervisorUserId),
    reporterDeptName: response.reporterDeptName ?? null,
    reporterPostName: response.reporterPostName ?? null,
    statusName: response.statusName || response.statusCode,
    signOffStatus: response.signOffStatus ?? null,
    signOffStatusName: response.signOffStatusName ?? null,
    allowEdit: normalizeBooleanFlag(response.allowEdit),
    terminal: normalizeBooleanFlag(response.terminal),
    totalWorkHours: normalizeReportTotalWorkHours(response.totalWorkHours, fallbackTotalWorkHours),
    submitTime: response.submitTime ?? null,
    reviewItems: response.reviewItems?.map(normalizeReviewItem) ?? [],
    planItems: response.planItems?.map(normalizePlanItem) ?? []
  };
}

function normalizeMemberSnapshot(item: MemberSnapshotResponse): Api.WorkReport.Project.WorkReportMemberSnapshot {
  return {
    ...item,
    userId: normalizeStringId(item.userId)
  };
}

function normalizeProjectReportItem(item: ProjectReportItemResponse): Api.WorkReport.Project.ProjectReportItem {
  return {
    ...item,
    id: normalizeNullableStringId(item.id) ?? undefined
  };
}

function normalizeProjectReport(response: ProjectReportResponse): Api.WorkReport.Project.ProjectReport {
  const fallbackTotalWorkHours = sumWorkHours(response.currentItems ?? []);

  return {
    ...response,
    id: normalizeStringId(response.id),
    projectId: normalizeStringId(response.projectId),
    projectOwnerId: normalizeStringId(response.projectOwnerId),
    projectMemberSnapshot: response.projectMemberSnapshot?.map(normalizeMemberSnapshot) ?? [],
    supervisorUserId: normalizeStringId(response.supervisorUserId),
    statusName: response.statusName || response.statusCode,
    allowEdit: normalizeBooleanFlag(response.allowEdit),
    terminal: normalizeBooleanFlag(response.terminal),
    totalWorkHours: normalizeReportTotalWorkHours(response.totalWorkHours, fallbackTotalWorkHours),
    submitTime: response.submitTime ?? null,
    currentItems: response.currentItems?.map(normalizeProjectReportItem) ?? [],
    nextItems: response.nextItems?.map(normalizeProjectReportItem) ?? []
  };
}

function normalizeApprovalRecord(response: ApprovalRecordResponse): Api.WorkReport.Common.WorkReportApprovalRecord {
  return {
    ...response,
    id: normalizeStringId(response.id),
    statusLogId: normalizeStringId(response.statusLogId),
    auditorUserId: normalizeStringId(response.auditorUserId),
    conclusion: normalizeApprovalConclusion(response.conclusion),
    opinion: response.opinion ?? null
  };
}

function normalizeMonthlyApprovalRecord(
  response: MonthlyApprovalRecordResponse
): Api.WorkReport.Monthly.MonthlyReportApprovalRecord {
  return {
    ...response,
    id: normalizeStringId(response.id),
    statusLogId: normalizeStringId(response.statusLogId),
    auditorUserId: normalizeStringId(response.auditorUserId),
    conclusion: normalizeApprovalConclusion(response.conclusion),
    opinion: response.opinion ?? null,
    meetingDate: normalizeDateText(response.meetingDate) ?? null,
    employeeSignatureFileId: normalizeNullableStringId(response.employeeSignatureFileId),
    employeeSignedDate: normalizeDateText(response.employeeSignedDate) ?? null,
    supervisorSignatureFileId: normalizeNullableStringId(response.supervisorSignatureFileId),
    supervisorSignedDate: normalizeDateText(response.supervisorSignedDate) ?? null
  };
}

function normalizeProjectOption(
  response: ProjectOptionResponse
): Api.WorkReport.Project.ProjectReportOwnerProjectOption {
  return {
    ...response,
    id: normalizeStringId(response.id)
  };
}

function normalizeTeamReportSummary(response: TeamReportSummaryResponse): Api.WorkReport.Common.TeamReportSummary {
  return {
    ...response,
    periodStartDate: normalizeDateText(response.periodStartDate) ?? undefined,
    periodEndDate: normalizeDateText(response.periodEndDate) ?? undefined,
    expectedReportCount: response.expectedReportCount ?? 0,
    submittedReportCount: response.submittedReportCount ?? 0,
    unsubmittedReportCount: response.unsubmittedReportCount ?? 0,
    pendingApprovalReportCount: response.pendingApprovalReportCount ?? 0,
    unsubmittedReports:
      response.unsubmittedReports?.map(item => ({
        ...item,
        userId: normalizeStringId(item.userId),
        projectId: normalizeNullableStringId(item.projectId),
        projectName: item.projectName ?? null
      })) ?? []
  };
}

function mapPage<TInput, TOutput>(data: PageResponse<TInput>, mapper: (item: TInput) => TOutput) {
  return {
    total: normalizeTotal(data.total),
    list: data.list.map(mapper)
  };
}

function toStatusActionRequest(data: Api.WorkReport.Common.StatusActionParams = {}) {
  return {
    reason: data.reason?.trim() || undefined
  };
}

function toPersonalReviewItems(items: Api.WorkReport.Common.PersonalReportReviewItem[] = []) {
  return items.map((item, index) => ({
    itemNumber: item.itemNumber ?? index + 1,
    itemTitle: item.itemTitle?.trim() || '',
    workHours: item.workHours ?? 0,
    contentText: item.contentText?.trim() || '',
    contentJson: item.contentJson ?? null,
    reflectionText: item.reflectionText?.trim() || ''
  }));
}

function toPersonalPlanItems(items: Api.WorkReport.Common.PersonalReportPlanItem[] = []) {
  return items.map((item, index) => ({
    itemNumber: item.itemNumber ?? index + 1,
    itemTitle: item.itemTitle?.trim() || '',
    targetText: item.targetText?.trim() || '',
    targetJson: item.targetJson ?? null,
    supportNeed: item.supportNeed?.trim() || ''
  }));
}

function toWeeklySaveRequest(data: Api.WorkReport.Weekly.WeeklyReportSaveParams) {
  return {
    periodKey: data.periodKey,
    periodLabel: data.periodLabel,
    periodStartDate: data.periodStartDate,
    periodEndDate: data.periodEndDate,
    isBusinessTrip: data.isBusinessTrip,
    reviewItems: toPersonalReviewItems(data.reviewItems),
    planItems: toPersonalPlanItems(data.planItems),
    travelSegments: data.isBusinessTrip
      ? data.travelSegments.map((item, index) => ({
          sort: item.sort ?? index + 1,
          startDate: item.startDate || undefined,
          endDate: item.endDate || undefined,
          travelDays: item.travelDays ?? 0,
          location: item.location?.trim() || ''
        }))
      : []
  };
}

function toMonthlySaveRequest(data: Api.WorkReport.Monthly.MonthlyReportSaveParams) {
  return {
    periodKey: data.periodKey,
    periodLabel: data.periodLabel,
    periodStartDate: data.periodStartDate,
    periodEndDate: data.periodEndDate,
    reviewItems: toPersonalReviewItems(data.reviewItems),
    planItems: toPersonalPlanItems(data.planItems)
  };
}

function toProjectItems(items: Api.WorkReport.Project.ProjectReportItem[] = []) {
  return items.map(item => ({
    itemTitle: item.itemTitle?.trim() || '',
    workHours: item.workHours ?? 0,
    priorityCode: item.priorityCode || undefined,
    progressRate: item.progressRate ?? 0
  }));
}

function toProjectSaveRequest(data: Api.WorkReport.Project.ProjectReportSaveParams) {
  return {
    projectId: data.projectId,
    periodKey: data.periodKey,
    periodLabel: data.periodLabel,
    periodStartDate: data.periodStartDate,
    periodEndDate: data.periodEndDate,
    flag: data.flag,
    projectStatusDesc: data.projectStatusDesc?.trim() || '',
    projectProgressPlan: data.projectProgressPlan?.trim() || '',
    projectKeyPoints: data.projectKeyPoints?.trim() || '',
    projectProblems: data.projectProblems?.trim() || '',
    currentItems: toProjectItems(data.currentItems),
    nextItems: toProjectItems(data.nextItems)
  };
}

export async function fetchGetWorkReportStatusDict() {
  const result = await request<Api.WorkReport.Common.WorkReportStatusDict[]>({
    ...safeJsonRequestConfig,
    url: `${WORK_REPORT_PREFIX}/status/dict`,
    method: 'get'
  });

  return mapServiceResult(result as ServiceRequestResult<Api.WorkReport.Common.WorkReportStatusDict[]>, data => data);
}

export async function fetchGetTeamReportSummary(params: Api.WorkReport.Common.TeamReportSummaryParams) {
  const result = await request<TeamReportSummaryResponse>({
    ...safeJsonRequestConfig,
    url: `${WORK_REPORT_PREFIX}/team/summary`,
    method: 'get',
    params
  });

  return mapServiceResult(result as ServiceRequestResult<TeamReportSummaryResponse>, normalizeTeamReportSummary);
}

export async function fetchRemindTeamReport(data: Api.WorkReport.Common.TeamReportRemindParams) {
  const result = await request<Api.WorkReport.Common.TeamReportRemindResult>({
    ...safeJsonRequestConfig,
    url: `${WORK_REPORT_PREFIX}/team/remind`,
    method: 'post',
    data: {
      ...data,
      userIds: data.userIds && data.userIds.length ? data.userIds : undefined
    }
  });

  return mapServiceResult(
    result as ServiceRequestResult<Api.WorkReport.Common.TeamReportRemindResult>,
    payload => payload
  );
}

export async function fetchGetWeeklyReportPage(params: Api.WorkReport.Weekly.WeeklyReportSearchParams = {}) {
  const query = createWeeklyPageQuery(params);
  const result = await request<PageResponse<WeeklyReportResponse>>({
    ...safeJsonRequestConfig,
    url: query ? `${WEEKLY_PREFIX}/page?${query}` : `${WEEKLY_PREFIX}/page`,
    method: 'get'
  });

  return mapServiceResult(result as ServiceRequestResult<PageResponse<WeeklyReportResponse>>, data =>
    mapPage(data, normalizeWeeklyReport)
  );
}

export async function fetchGetWeeklyReportApprovalPage(params: Api.WorkReport.Weekly.WeeklyReportSearchParams = {}) {
  const query = createWeeklyPageQuery(params);
  const result = await request<PageResponse<WeeklyReportResponse>>({
    ...safeJsonRequestConfig,
    url: query ? `${WEEKLY_PREFIX}/approval-page?${query}` : `${WEEKLY_PREFIX}/approval-page`,
    method: 'get'
  });

  return mapServiceResult(result as ServiceRequestResult<PageResponse<WeeklyReportResponse>>, data =>
    mapPage(data, normalizeWeeklyReport)
  );
}

export async function fetchGetWeeklyReportDetail(id: string) {
  const result = await request<WeeklyReportResponse>({
    ...safeJsonRequestConfig,
    url: `${WEEKLY_PREFIX}/${id}`,
    method: 'get'
  });

  return mapServiceResult(result as ServiceRequestResult<WeeklyReportResponse>, normalizeWeeklyReport);
}

export async function fetchInitWeeklyReport() {
  const result = await request<WeeklyReportResponse>({
    ...safeJsonRequestConfig,
    url: `${WEEKLY_PREFIX}/init`,
    method: 'get'
  });

  return mapServiceResult(result as ServiceRequestResult<WeeklyReportResponse>, normalizeWeeklyReport);
}

export async function fetchPreviewWeeklyReportDefaultDraft(
  params: Api.WorkReport.Weekly.WeeklyReportDefaultDraftParams
) {
  const result = await request<WeeklyReportResponse>({
    ...safeJsonRequestConfig,
    url: `${WEEKLY_PREFIX}/default-draft`,
    method: 'get',
    params
  });

  return mapServiceResult(result as ServiceRequestResult<WeeklyReportResponse>, normalizeWeeklyReport);
}

export async function fetchRefreshWeeklyReportDraft(data: Api.WorkReport.Weekly.WeeklyReportRefreshDraftParams) {
  const result = await request<WeeklyReportResponse>({
    ...safeJsonRequestConfig,
    url: `${WEEKLY_PREFIX}/refresh-draft`,
    method: 'post',
    data: toWeeklySaveRequest(data)
  });

  return mapServiceResult(result as ServiceRequestResult<WeeklyReportResponse>, normalizeWeeklyReport);
}

export async function fetchCreateWeeklyReport(data: Api.WorkReport.Weekly.WeeklyReportSaveParams) {
  const result = await request<StringIdResponse>({
    ...safeJsonRequestConfig,
    url: WEEKLY_PREFIX,
    method: 'post',
    data: toWeeklySaveRequest(data)
  });

  return mapServiceResult(result as ServiceRequestResult<StringIdResponse>, normalizeStringId);
}

export function fetchUpdateWeeklyReport(id: string, data: Api.WorkReport.Weekly.WeeklyReportSaveParams) {
  return request<boolean>({
    ...safeJsonRequestConfig,
    url: `${WEEKLY_PREFIX}/${id}`,
    method: 'put',
    data: toWeeklySaveRequest(data)
  });
}

export function fetchSubmitWeeklyReport(id: string) {
  return request<boolean>({ ...safeJsonRequestConfig, url: `${WEEKLY_PREFIX}/${id}/submit`, method: 'post' });
}

export function fetchApproveWeeklyReport(id: string, data: Api.WorkReport.Common.StatusActionParams = {}) {
  return request<boolean>({
    ...safeJsonRequestConfig,
    url: `${WEEKLY_PREFIX}/${id}/approve`,
    method: 'post',
    data: toStatusActionRequest(data)
  });
}

export function fetchRejectWeeklyReport(id: string, data: Api.WorkReport.Common.StatusActionParams) {
  return request<boolean>({
    ...safeJsonRequestConfig,
    url: `${WEEKLY_PREFIX}/${id}/reject`,
    method: 'post',
    data: toStatusActionRequest(data)
  });
}

export function fetchDeleteWeeklyReport(id: string) {
  return request<boolean>({ ...safeJsonRequestConfig, url: `${WEEKLY_PREFIX}/${id}`, method: 'delete' });
}

export async function fetchGetWeeklyReportApprovalRecords(id: string) {
  const result = await request<ApprovalRecordResponse[]>({
    ...safeJsonRequestConfig,
    url: `${WEEKLY_PREFIX}/${id}/approval-records`,
    method: 'get'
  });

  return mapServiceResult(result as ServiceRequestResult<ApprovalRecordResponse[]>, data =>
    data.map(normalizeApprovalRecord)
  );
}

export function fetchExportWeeklyReports(params: Api.WorkReport.Weekly.WeeklyReportSearchParams = {}) {
  const query = createWeeklyPageQuery(params);
  return request<Blob, 'blob'>({
    url: query ? `${WEEKLY_PREFIX}/export?${query}` : `${WEEKLY_PREFIX}/export`,
    method: 'get',
    responseType: 'blob'
  });
}

export function fetchExportWeeklyReportContent(
  data: Api.WorkReport.Common.ContentExportParams<Api.WorkReport.Weekly.WeeklyReportSearchParams>
) {
  return request<Blob, 'blob'>({
    url: `${WEEKLY_PREFIX}/content-export`,
    method: 'post',
    data,
    responseType: 'blob'
  });
}

export async function fetchGetMonthlyReportPage(params: Api.WorkReport.Monthly.MonthlyReportSearchParams = {}) {
  const query = createMonthlyPageQuery(params);
  const result = await request<PageResponse<MonthlyReportResponse>>({
    ...safeJsonRequestConfig,
    url: query ? `${MONTHLY_PREFIX}/page?${query}` : `${MONTHLY_PREFIX}/page`,
    method: 'get'
  });

  return mapServiceResult(result as ServiceRequestResult<PageResponse<MonthlyReportResponse>>, data =>
    mapPage(data, normalizeMonthlyReport)
  );
}

export async function fetchGetMonthlyReportApprovalPage(params: Api.WorkReport.Monthly.MonthlyReportSearchParams = {}) {
  const query = createMonthlyPageQuery(params);
  const result = await request<PageResponse<MonthlyReportResponse>>({
    ...safeJsonRequestConfig,
    url: query ? `${MONTHLY_PREFIX}/approval-page?${query}` : `${MONTHLY_PREFIX}/approval-page`,
    method: 'get'
  });

  return mapServiceResult(result as ServiceRequestResult<PageResponse<MonthlyReportResponse>>, data =>
    mapPage(data, normalizeMonthlyReport)
  );
}

export async function fetchGetMonthlyReportSignOffPage(params: Api.WorkReport.Monthly.MonthlyReportSearchParams = {}) {
  const query = createMonthlyPageQuery(params);
  const result = await request<PageResponse<MonthlyReportResponse>>({
    ...safeJsonRequestConfig,
    url: query ? `${MONTHLY_PREFIX}/sign-off-page?${query}` : `${MONTHLY_PREFIX}/sign-off-page`,
    method: 'get'
  });

  return mapServiceResult(result as ServiceRequestResult<PageResponse<MonthlyReportResponse>>, data =>
    mapPage(data, normalizeMonthlyReport)
  );
}

export async function fetchGetMonthlyReportDetail(id: string) {
  const result = await request<MonthlyReportResponse>({
    ...safeJsonRequestConfig,
    url: `${MONTHLY_PREFIX}/${id}`,
    method: 'get'
  });

  return mapServiceResult(result as ServiceRequestResult<MonthlyReportResponse>, normalizeMonthlyReport);
}

export async function fetchInitMonthlyReport() {
  const result = await request<MonthlyReportResponse>({
    ...safeJsonRequestConfig,
    url: `${MONTHLY_PREFIX}/init`,
    method: 'get'
  });

  return mapServiceResult(result as ServiceRequestResult<MonthlyReportResponse>, normalizeMonthlyReport);
}

export async function fetchPreviewMonthlyReportDefaultDraft(
  params: Api.WorkReport.Monthly.MonthlyReportDefaultDraftParams
) {
  const result = await request<MonthlyReportResponse>({
    ...safeJsonRequestConfig,
    url: `${MONTHLY_PREFIX}/default-draft`,
    method: 'get',
    params
  });

  return mapServiceResult(result as ServiceRequestResult<MonthlyReportResponse>, normalizeMonthlyReport);
}

export async function fetchRefreshMonthlyReportDraft(data: Api.WorkReport.Monthly.MonthlyReportRefreshDraftParams) {
  const result = await request<MonthlyReportResponse>({
    ...safeJsonRequestConfig,
    url: `${MONTHLY_PREFIX}/refresh-draft`,
    method: 'post',
    data: toMonthlySaveRequest(data)
  });

  return mapServiceResult(result as ServiceRequestResult<MonthlyReportResponse>, normalizeMonthlyReport);
}

export async function fetchCreateMonthlyReport(data: Api.WorkReport.Monthly.MonthlyReportSaveParams) {
  const result = await request<StringIdResponse>({
    ...safeJsonRequestConfig,
    url: MONTHLY_PREFIX,
    method: 'post',
    data: toMonthlySaveRequest(data)
  });

  return mapServiceResult(result as ServiceRequestResult<StringIdResponse>, normalizeStringId);
}

export function fetchUpdateMonthlyReport(id: string, data: Api.WorkReport.Monthly.MonthlyReportSaveParams) {
  return request<boolean>({
    ...safeJsonRequestConfig,
    url: `${MONTHLY_PREFIX}/${id}`,
    method: 'put',
    data: toMonthlySaveRequest(data)
  });
}

export function fetchSubmitMonthlyReport(id: string) {
  return request<boolean>({ ...safeJsonRequestConfig, url: `${MONTHLY_PREFIX}/${id}/submit`, method: 'post' });
}

export function fetchApproveMonthlyReport(id: string, data: Api.WorkReport.Monthly.MonthlyReportApproveParams) {
  return request<boolean>({
    ...safeJsonRequestConfig,
    url: `${MONTHLY_PREFIX}/${id}/approve`,
    method: 'post',
    data
  });
}

export function fetchRejectMonthlyReport(id: string, data: Api.WorkReport.Common.StatusActionParams) {
  return request<boolean>({
    ...safeJsonRequestConfig,
    url: `${MONTHLY_PREFIX}/${id}/reject`,
    method: 'post',
    data: toStatusActionRequest(data)
  });
}

export function fetchDeleteMonthlyReport(id: string) {
  return request<boolean>({ ...safeJsonRequestConfig, url: `${MONTHLY_PREFIX}/${id}`, method: 'delete' });
}

export async function fetchGetMonthlyReportApprovalRecords(id: string) {
  const result = await request<MonthlyApprovalRecordResponse[]>({
    ...safeJsonRequestConfig,
    url: `${MONTHLY_PREFIX}/${id}/approval-records`,
    method: 'get'
  });

  return mapServiceResult(result as ServiceRequestResult<MonthlyApprovalRecordResponse[]>, data =>
    data.map(normalizeMonthlyApprovalRecord)
  );
}

export async function fetchGetMonthlyReportSignOffDetail(id: string) {
  const result = await request<MonthlySignOffDetailResponse>({
    ...safeJsonRequestConfig,
    url: `${MONTHLY_PREFIX}/${id}/sign-off-detail`,
    method: 'get'
  });

  return mapServiceResult(result as ServiceRequestResult<MonthlySignOffDetailResponse>, data => ({
    report: normalizeMonthlyReport(data.report),
    latestApprovalRecord: data.latestApprovalRecord ? normalizeMonthlyApprovalRecord(data.latestApprovalRecord) : null
  }));
}

export function fetchConfirmMonthlyReportSignOff(
  id: string,
  data: Api.WorkReport.Monthly.MonthlyReportSignOffConfirmParams
) {
  return request<boolean>({
    ...safeJsonRequestConfig,
    url: `${MONTHLY_PREFIX}/${id}/confirm-sign-off`,
    method: 'post',
    data: {
      meetingDate: data.meetingDate,
      employeeSignedDate: data.employeeSignedDate || undefined
    }
  });
}

export function fetchExportMonthlyReports(params: Api.WorkReport.Monthly.MonthlyReportSearchParams = {}) {
  const query = createMonthlyPageQuery(params);
  return request<Blob, 'blob'>({
    url: query ? `${MONTHLY_PREFIX}/export?${query}` : `${MONTHLY_PREFIX}/export`,
    method: 'get',
    responseType: 'blob'
  });
}

export function fetchExportMonthlyReportContent(
  data: Api.WorkReport.Common.ContentExportParams<Api.WorkReport.Monthly.MonthlyReportSearchParams>
) {
  return request<Blob, 'blob'>({
    url: `${MONTHLY_PREFIX}/content-export`,
    method: 'post',
    data,
    responseType: 'blob'
  });
}

export async function fetchGetProjectReportOwnerProjectOptions() {
  const result = await request<ProjectOptionResponse[]>({
    ...safeJsonRequestConfig,
    url: `${PROJECT_PREFIX}/owner-project-options`,
    method: 'get'
  });

  return mapServiceResult(result as ServiceRequestResult<ProjectOptionResponse[]>, data =>
    data.map(normalizeProjectOption)
  );
}

export async function fetchGetProjectReportPage(params: Api.WorkReport.Project.ProjectReportSearchParams = {}) {
  const query = createProjectPageQuery(params);
  const result = await request<PageResponse<ProjectReportResponse>>({
    ...safeJsonRequestConfig,
    url: query ? `${PROJECT_PREFIX}/page?${query}` : `${PROJECT_PREFIX}/page`,
    method: 'get'
  });

  return mapServiceResult(result as ServiceRequestResult<PageResponse<ProjectReportResponse>>, data =>
    mapPage(data, normalizeProjectReport)
  );
}

export async function fetchGetProjectReportApprovalPage(params: Api.WorkReport.Project.ProjectReportSearchParams = {}) {
  const query = createProjectPageQuery(params);
  const result = await request<PageResponse<ProjectReportResponse>>({
    ...safeJsonRequestConfig,
    url: query ? `${PROJECT_PREFIX}/approval-page?${query}` : `${PROJECT_PREFIX}/approval-page`,
    method: 'get'
  });

  return mapServiceResult(result as ServiceRequestResult<PageResponse<ProjectReportResponse>>, data =>
    mapPage(data, normalizeProjectReport)
  );
}

export async function fetchGetProjectReportDetail(id: string) {
  const result = await request<ProjectReportResponse>({
    ...safeJsonRequestConfig,
    url: `${PROJECT_PREFIX}/${id}`,
    method: 'get'
  });

  return mapServiceResult(result as ServiceRequestResult<ProjectReportResponse>, normalizeProjectReport);
}

export async function fetchInitProjectReport(projectId: string) {
  const result = await request<ProjectReportResponse>({
    ...safeJsonRequestConfig,
    url: `${PROJECT_PREFIX}/init`,
    method: 'get',
    params: { projectId }
  });

  return mapServiceResult(result as ServiceRequestResult<ProjectReportResponse>, normalizeProjectReport);
}

export async function fetchPreviewProjectReportDefaultDraft(
  projectId: string,
  params: Api.WorkReport.Project.ProjectReportDefaultDraftParams
) {
  const result = await request<ProjectReportResponse>({
    ...safeJsonRequestConfig,
    url: `${PROJECT_PREFIX}/${projectId}/default-draft`,
    method: 'get',
    params
  });

  return mapServiceResult(result as ServiceRequestResult<ProjectReportResponse>, normalizeProjectReport);
}

export async function fetchRefreshProjectReportDraft(
  projectId: string,
  data: Api.WorkReport.Project.ProjectReportRefreshDraftParams
) {
  const result = await request<ProjectReportResponse>({
    ...safeJsonRequestConfig,
    url: `${PROJECT_PREFIX}/${projectId}/refresh-draft`,
    method: 'post',
    data: {
      periodKey: data.periodKey,
      periodLabel: data.periodLabel,
      periodStartDate: data.periodStartDate,
      periodEndDate: data.periodEndDate,
      flag: data.flag,
      projectStatusDesc: data.projectStatusDesc?.trim() || '',
      projectProgressPlan: data.projectProgressPlan?.trim() || '',
      projectKeyPoints: data.projectKeyPoints?.trim() || '',
      projectProblems: data.projectProblems?.trim() || '',
      currentItems: toProjectItems(data.currentItems),
      nextItems: toProjectItems(data.nextItems)
    }
  });

  return mapServiceResult(result as ServiceRequestResult<ProjectReportResponse>, normalizeProjectReport);
}

export async function fetchCreateProjectReport(data: Api.WorkReport.Project.ProjectReportSaveParams) {
  const result = await request<StringIdResponse>({
    ...safeJsonRequestConfig,
    url: PROJECT_PREFIX,
    method: 'post',
    data: toProjectSaveRequest(data)
  });

  return mapServiceResult(result as ServiceRequestResult<StringIdResponse>, normalizeStringId);
}

export function fetchUpdateProjectReport(id: string, data: Api.WorkReport.Project.ProjectReportSaveParams) {
  return request<boolean>({
    ...safeJsonRequestConfig,
    url: `${PROJECT_PREFIX}/${id}`,
    method: 'put',
    data: toProjectSaveRequest(data)
  });
}

export function fetchSubmitProjectReport(id: string) {
  return request<boolean>({ ...safeJsonRequestConfig, url: `${PROJECT_PREFIX}/${id}/submit`, method: 'post' });
}

export function fetchApproveProjectReport(id: string, data: Api.WorkReport.Common.StatusActionParams = {}) {
  return request<boolean>({
    ...safeJsonRequestConfig,
    url: `${PROJECT_PREFIX}/${id}/approve`,
    method: 'post',
    data: toStatusActionRequest(data)
  });
}

export function fetchRejectProjectReport(id: string, data: Api.WorkReport.Common.StatusActionParams) {
  return request<boolean>({
    ...safeJsonRequestConfig,
    url: `${PROJECT_PREFIX}/${id}/reject`,
    method: 'post',
    data: toStatusActionRequest(data)
  });
}

export function fetchDeleteProjectReport(id: string) {
  return request<boolean>({ ...safeJsonRequestConfig, url: `${PROJECT_PREFIX}/${id}`, method: 'delete' });
}

export async function fetchGetProjectReportApprovalRecords(id: string) {
  const result = await request<ApprovalRecordResponse[]>({
    ...safeJsonRequestConfig,
    url: `${PROJECT_PREFIX}/${id}/approval-records`,
    method: 'get'
  });

  return mapServiceResult(result as ServiceRequestResult<ApprovalRecordResponse[]>, data =>
    data.map(normalizeApprovalRecord)
  );
}

export function fetchExportProjectReports(params: Api.WorkReport.Project.ProjectReportSearchParams = {}) {
  const query = createProjectPageQuery(params);
  return request<Blob, 'blob'>({
    url: query ? `${PROJECT_PREFIX}/export?${query}` : `${PROJECT_PREFIX}/export`,
    method: 'get',
    responseType: 'blob'
  });
}

export function fetchExportProjectReportContent(
  data: Api.WorkReport.Common.ContentExportParams<Api.WorkReport.Project.ProjectReportSearchParams>
) {
  return request<Blob, 'blob'>({
    url: `${PROJECT_PREFIX}/content-export`,
    method: 'post',
    data,
    responseType: 'blob'
  });
}
