import axiosInstance from "./axiosInstance";
import { withHeaders } from "@/record-management/services/api/withHeaders";
import { AxiosResponse } from "axios";

export interface PositionConfiguration {
  id?: string;
  positionId: string;
  smsNotificationWhenRecordSubmitted: boolean;
  emailNotificationWhenRecordSubmitted: boolean;
  inboxNotificationWhenRecordSubmitted: boolean;
  skipWorkflowIfNotAssigned: boolean;
  positionScopeToFetch?: string;
  createdAt?: string;
  updatedAt?: string;
  /** Legacy read-only shape; new saves use top-level positionScopeToFetch. */
  items?: {
    data: string;
  };
}

export interface PositionConfigurationPayload {
  positionId: string;
  smsNotificationWhenRecordSubmitted: boolean;
  emailNotificationWhenRecordSubmitted: boolean;
  inboxNotificationWhenRecordSubmitted: boolean;
  skipWorkflowIfNotAssigned: boolean;
  positionScopeToFetch: string;
}

export type CreatePositionConfigurationPayload = PositionConfigurationPayload;
export type UpdatePositionConfigurationPayload = PositionConfigurationPayload;

export const normalizePositionConfigurationResponse = (
  response: AxiosResponse<unknown>,
): PositionConfiguration | null => {
  const data = response?.data;

  if (!data) return null;

  if (Array.isArray(data)) {
    return (data[0] as PositionConfiguration | undefined) ?? null;
  }

  if (typeof data === "object" && data !== null) {
    if ("items" in data && Array.isArray((data as { items: unknown }).items)) {
      const items = (data as { items: PositionConfiguration[] }).items;
      const match =
        items.find((item) => item.positionId) ?? items[0];
      return (match as PositionConfiguration | undefined) ?? null;
    }

    if ("data" in data && (data as { data: unknown }).data) {
      const nested = (data as { data: unknown }).data;
      if (Array.isArray(nested)) {
        return (nested[0] as PositionConfiguration | undefined) ?? null;
      }
      if (typeof nested === "object" && nested !== null && "positionId" in nested) {
        return nested as PositionConfiguration;
      }
    }

    if ("positionId" in data) {
      return data as PositionConfiguration;
    }
  }

  return null;
};

const isNotFoundError = (error: unknown) => {
  const err = error as {
    response?: { status?: number; data?: { message?: string } };
    message?: string;
  };
  const message = err?.response?.data?.message || err?.message || "";
  return (
    err?.response?.status === 404 ||
    (err?.response?.status === 400 && /could not be found|not found/i.test(message))
  );
};

const extractConfigurationId = (
  configuration: PositionConfiguration | null,
): string | undefined => configuration?.id;

const extractConfigurationFromList = (
  response: AxiosResponse<unknown>,
  positionId: string,
): PositionConfiguration | null => {
  const data = response?.data;

  if (!data || typeof data !== "object") {
    return null;
  }

  const candidates: PositionConfiguration[] = [];

  if (Array.isArray(data)) {
    candidates.push(...(data as PositionConfiguration[]));
  } else if ("items" in data && Array.isArray((data as { items: unknown }).items)) {
    candidates.push(...((data as { items: PositionConfiguration[] }).items ?? []));
  } else if ("data" in data) {
    const nested = (data as { data: unknown }).data;
    if (Array.isArray(nested)) {
      candidates.push(...(nested as PositionConfiguration[]));
    } else if (nested && typeof nested === "object" && "positionId" in nested) {
      candidates.push(nested as PositionConfiguration);
    }
  } else if ("positionId" in data) {
    candidates.push(data as PositionConfiguration);
  }

  return (
    candidates.find((item) => item.positionId === positionId) ??
    candidates[0] ??
    null
  );
};

// List configurations for a position.
export const getPositionConfigurationList = async (
  positionId: string,
): Promise<AxiosResponse<unknown>> => {
  return axiosInstance.get(`/position-configurations/list/${positionId}`, {
    headers: withHeaders(),
  });
};

// Get a single configuration by its configuration record id.
export const getPositionConfigurationById = async (
  configurationId: string,
): Promise<AxiosResponse<PositionConfiguration>> => {
  return axiosInstance.get(`/position-configurations/${configurationId}`, {
    headers: withHeaders(),
  });
};

// Load configuration for a position: list first, then fetch the full record by id.
export const fetchPositionConfigurationByPositionId = async (
  positionId: string,
): Promise<PositionConfiguration | null> => {
  try {
    const listResponse = await getPositionConfigurationList(positionId);
    const listedConfiguration = extractConfigurationFromList(
      listResponse,
      positionId,
    );

    const configurationId = extractConfigurationId(listedConfiguration);
    if (!configurationId) {
      return listedConfiguration;
    }

    const detailResponse = await getPositionConfigurationById(configurationId);
    return (
      normalizePositionConfigurationResponse(detailResponse) ??
      listedConfiguration
    );
  } catch (error) {
    if (isNotFoundError(error)) {
      return null;
    }

    throw error;
  }
};

export const createPositionConfiguration = async (
  payload: CreatePositionConfigurationPayload,
): Promise<AxiosResponse<PositionConfiguration>> => {
  return axiosInstance.post("/position-configurations", payload, {
    headers: withHeaders(),
  });
};

export const updatePositionConfiguration = async (
  configurationId: string,
  payload: UpdatePositionConfigurationPayload,
): Promise<AxiosResponse<PositionConfiguration>> => {
  return axiosInstance.put(
    `/position-configurations/${configurationId}`,
    payload,
    {
      headers: withHeaders(),
    },
  );
};

// Create when no record exists; update by configuration id when it does.
export const savePositionConfiguration = async (
  payload: PositionConfigurationPayload,
  existingConfigurationId?: string,
): Promise<AxiosResponse<PositionConfiguration>> => {
  if (existingConfigurationId) {
    return updatePositionConfiguration(existingConfigurationId, payload);
  }

  return createPositionConfiguration(payload);
};

export const getPositionConfigurationsList = getPositionConfigurationList;

export const deletePositionConfiguration = async (
  configurationId: string,
): Promise<AxiosResponse<void>> => {
  return axiosInstance.delete(`/position-configurations/${configurationId}`, {
    headers: withHeaders(),
  });
};
