import {
  TemplateSampleFileInfo,
  TemplateSampleRequest,
  TemplateSampleRequestSetting,
  TemplateSampleResource,
  TemplateSampleSetting,
} from "@/user-management/services/TemplateConfiguration/types/templateTypes";
import { isFontSetting } from "../components/FontSettingsEditor";
import {
  isCustomListStyleImage,
  ListBulletResource,
} from "./templateResourceConstants";

export function isListStyleSettingCode(code: string): boolean {
  return code.trim().toLowerCase().includes("list-style");
}

export function extractListStyleResourceId(
  value: Record<string, string>,
  bulletResources: ListBulletResource[],
): string | null {
  const imageValue = value["list-style-image"];
  if (isCustomListStyleImage(imageValue)) {
    const match = bulletResources.find(
      (resource) =>
        imageValue.includes(resource.presigned) ||
        imageValue.includes(resource.id) ||
        Boolean(
          resource.fileInfo?.fileName &&
            imageValue.includes(resource.fileInfo.fileName),
        ),
    );

    return match?.id ?? null;
  }

  if (value["list-style-type"] === "custom-image") {
    return null;
  }

  return null;
}

export function resolveSettingResourceId(
  setting: Pick<TemplateSampleSetting, "id" | "code">,
  value: Record<string, unknown>,
  resourceIds: Record<string, string | null>,
  bulletResources: ListBulletResource[],
): string | null {
  if (isFontSetting(setting.code)) {
    return resourceIds[setting.id] ?? null;
  }

  const cssValue = value as Record<string, string>;
  if (cssValue["list-style-type"] === "custom-image") {
    return resourceIds[setting.id] ?? null;
  }

  return (
    resourceIds[setting.id] ??
    extractListStyleResourceId(cssValue, bulletResources)
  );
}

export function formatSettingValueForApi(
  value: Record<string, unknown>,
  resourceId: string | null,
  settingCode: string,
): Record<string, unknown> {
  const formatted: Record<string, unknown> = { ...value };

  if (!isListStyleSettingCode(settingCode)) {
    return formatted;
  }

  if (resourceId) {
    delete formatted["list-style-image"];
    delete formatted["list-style"];
    formatted["list-style-type"] = "custom-image";
    return formatted;
  }

  delete formatted["list-style-image"];

  const listStyle =
    (formatted["list-style"] as string | undefined)?.split(" ")[0] ||
    (formatted["list-style-type"] as string | undefined);

  if (
    listStyle &&
    listStyle !== "custom-image" &&
    listStyle !== "none"
  ) {
    formatted["list-style-type"] = listStyle;
    formatted["list-style"] = listStyle;
  }

  return formatted;
}

function toSampleFileInfo(
  fileInfo?: ListBulletResource["fileInfo"],
): TemplateSampleFileInfo | undefined {
  if (!fileInfo) return undefined;

  return {
    bucket: fileInfo.bucket || "",
    originalname: fileInfo.originalname || "",
    contentType: fileInfo.contentType || "application/octet-stream",
    fileName: fileInfo.fileName,
    size: fileInfo.size,
  };
}

export function buildSampleResources(
  resourceIds: Array<string | null | undefined>,
  bulletResources: ListBulletResource[],
): TemplateSampleResource[] {
  const uniqueIds = [
    ...new Set(resourceIds.filter((id): id is string => Boolean(id))),
  ];

  return uniqueIds.map((resourceId) => {
    const resource = bulletResources.find((item) => item.id === resourceId);

    return {
      resourceId,
      presigned: resource?.presigned,
      fileInfo: toSampleFileInfo(resource?.fileInfo),
    };
  });
}

export function buildSampleSettingPayload(
  setting: TemplateSampleSetting,
  value: Record<string, unknown>,
  resourceIds: Record<string, string | null>,
  bulletResources: ListBulletResource[],
): TemplateSampleRequestSetting {
  const resourceId = resolveSettingResourceId(
    setting,
    value,
    resourceIds,
    bulletResources,
  );

  return {
    id: setting.id,
    code: setting.code,
    value: formatSettingValueForApi(value, resourceId, setting.code),
    resourceId: resourceId ?? null,
  };
}

export function buildTemplateSamplePayload(input: {
  data: TemplateSampleRequest["data"];
  settings: TemplateSampleSetting[];
  resourceIds: Record<string, string | null>;
  bulletResources: ListBulletResource[];
  resolveSettingValue: (
    setting: TemplateSampleSetting,
  ) => Record<string, unknown>;
}): TemplateSampleRequest {
  const settingsForAPI = input.settings.map((setting) =>
    buildSampleSettingPayload(
      setting,
      input.resolveSettingValue(setting),
      input.resourceIds,
      input.bulletResources,
    ),
  );

  const resources = buildSampleResources(
    settingsForAPI.map((setting) => setting.resourceId),
    input.bulletResources,
  );

  return {
    data: input.data,
    settings: settingsForAPI,
    resources,
  };
}
