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

const OBJECT_STATUS_MODEL_PREFIX = `${WEB_SERVICE_PREFIX}/project/status/model`;
const OBJECT_STATUS_TRANSITION_PREFIX = `${WEB_SERVICE_PREFIX}/project/status/transition`;

type ObjectStatusModelResponse = Omit<
  Api.Infra.ObjectStatusModel,
  | 'id'
  | 'initialFlag'
  | 'terminalFlag'
  | 'allowEdit'
  | 'progressExcludedFlag'
  | 'allowCreateProject'
  | 'allowCreateRequirement'
> & {
  id: string | number;
  initialFlag: boolean | number | string | null | undefined;
  terminalFlag: boolean | number | string | null | undefined;
  allowEdit: boolean | number | string | null | undefined;
  progressExcludedFlag: boolean | number | string | null | undefined;
  allowCreateProject: boolean | number | string | null | undefined;
  allowCreateRequirement: boolean | number | string | null | undefined;
};

type ObjectStatusTransitionResponse = Omit<Api.Infra.ObjectStatusTransition, 'id' | 'needReason'> & {
  id: string | number;
  needReason: boolean | number | string | null | undefined;
};

type ObjectStatusModelPageResponse = Api.Infra.PageResult<ObjectStatusModelResponse>;

type ObjectStatusTransitionPageResponse = Api.Infra.PageResult<ObjectStatusTransitionResponse>;

function createBatchDeleteQuery(ids: string[]) {
  const query = new URLSearchParams();

  ids.forEach(id => {
    query.append('ids', id);
  });

  return query.toString();
}

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();

    if (!normalized || normalized === '0' || normalized === 'false' || normalized === 'n') {
      return false;
    }

    return true;
  }

  return false;
}

function normalizeObjectStatusModel(model: ObjectStatusModelResponse): Api.Infra.ObjectStatusModel {
  return {
    ...model,
    id: normalizeStringId(model.id),
    initialFlag: normalizeBooleanFlag(model.initialFlag),
    terminalFlag: normalizeBooleanFlag(model.terminalFlag),
    allowEdit: normalizeBooleanFlag(model.allowEdit),
    progressExcludedFlag: normalizeBooleanFlag(model.progressExcludedFlag),
    allowCreateProject: normalizeBooleanFlag(model.allowCreateProject),
    allowCreateRequirement: normalizeBooleanFlag(model.allowCreateRequirement)
  };
}

function normalizeObjectStatusTransition(transition: ObjectStatusTransitionResponse): Api.Infra.ObjectStatusTransition {
  return {
    ...transition,
    id: normalizeStringId(transition.id),
    needReason: normalizeBooleanFlag(transition.needReason)
  };
}

export async function fetchGetObjectStatusModelPage(params?: Api.Infra.ObjectStatusModelSearchParams) {
  const result = await request<ObjectStatusModelPageResponse>({
    ...safeJsonRequestConfig,
    url: `${OBJECT_STATUS_MODEL_PREFIX}/page`,
    method: 'get',
    params
  });

  return mapServiceResult(result as ServiceRequestResult<ObjectStatusModelPageResponse>, data => ({
    ...data,
    list: data.list.map(normalizeObjectStatusModel)
  }));
}

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

  return mapServiceResult(result as ServiceRequestResult<ObjectStatusModelResponse>, normalizeObjectStatusModel);
}

export async function fetchCreateObjectStatusModel(data: Api.Infra.SaveObjectStatusModelParams) {
  const result = await request<string | number>({
    ...safeJsonRequestConfig,
    url: `${OBJECT_STATUS_MODEL_PREFIX}/create`,
    method: 'post',
    data
  });

  return mapServiceResult(result as ServiceRequestResult<string | number>, normalizeStringId);
}

export function fetchUpdateObjectStatusModel(data: { id: string } & Api.Infra.SaveObjectStatusModelParams) {
  return request<boolean>({
    url: `${OBJECT_STATUS_MODEL_PREFIX}/update`,
    method: 'put',
    data
  });
}

export function fetchDeleteObjectStatusModel(id: string) {
  return request<boolean>({
    url: `${OBJECT_STATUS_MODEL_PREFIX}/delete`,
    method: 'delete',
    params: { id }
  });
}

export function fetchBatchDeleteObjectStatusModel(ids: string[]) {
  return request<boolean>({
    url: `${OBJECT_STATUS_MODEL_PREFIX}/delete-list?${createBatchDeleteQuery(ids)}`,
    method: 'delete'
  });
}

export async function fetchGetObjectStatusTransitionPage(params?: Api.Infra.ObjectStatusTransitionSearchParams) {
  const result = await request<ObjectStatusTransitionPageResponse>({
    ...safeJsonRequestConfig,
    url: `${OBJECT_STATUS_TRANSITION_PREFIX}/page`,
    method: 'get',
    params
  });

  return mapServiceResult(result as ServiceRequestResult<ObjectStatusTransitionPageResponse>, data => ({
    ...data,
    list: data.list.map(normalizeObjectStatusTransition)
  }));
}

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

  return mapServiceResult(
    result as ServiceRequestResult<ObjectStatusTransitionResponse>,
    normalizeObjectStatusTransition
  );
}

export async function fetchCreateObjectStatusTransition(data: Api.Infra.SaveObjectStatusTransitionParams) {
  const result = await request<string | number>({
    ...safeJsonRequestConfig,
    url: `${OBJECT_STATUS_TRANSITION_PREFIX}/create`,
    method: 'post',
    data
  });

  return mapServiceResult(result as ServiceRequestResult<string | number>, normalizeStringId);
}

export function fetchUpdateObjectStatusTransition(data: { id: string } & Api.Infra.SaveObjectStatusTransitionParams) {
  return request<boolean>({
    url: `${OBJECT_STATUS_TRANSITION_PREFIX}/update`,
    method: 'put',
    data
  });
}

export function fetchDeleteObjectStatusTransition(id: string) {
  return request<boolean>({
    url: `${OBJECT_STATUS_TRANSITION_PREFIX}/delete`,
    method: 'delete',
    params: { id }
  });
}

export function fetchBatchDeleteObjectStatusTransition(ids: string[]) {
  return request<boolean>({
    url: `${OBJECT_STATUS_TRANSITION_PREFIX}/delete-list?${createBatchDeleteQuery(ids)}`,
    method: 'delete'
  });
}
