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

export interface UploadKeyResponse {
  uploadKey: string;
  presignedUrl?: string;
  presigned?: string;
  fileInfo: {
    fileName: string;
    originalname: string;
    contentType: string;
    fileType: string;
    size: number;
  };
}

export interface UploadAndCreateResourceParams {
  type: "signature" | "stamp" | "header" | "footer";
  file: File;
  name: { am: string; en: string };
  parentId: string;
  locale?: "am" | "en" | null;
}

const config = {
  signature: {
    uploadKey: "/signatures/get-file-upload-key",
    create: "/signatures",
    parentField: "employeeId",
  },
  stamp: {
    uploadKey: "/employee-stamps/get-file-upload-key",
    create: "/employee-stamps",
    parentField: "employeePositionId",
  },
  header: {
    uploadKey: "/headers/get-file-upload-key",
    create: "/headers",
    parentField: "unitId",
  },
  footer: {
    uploadKey: "/footers/get-file-upload-key",
    create: "/footers",
    parentField: "unitId",
  },
} as const;

/**
 * Get upload key and presigned URL for file upload
 */
export async function getUploadKey(
  endpoint: string,
  file: File,
  axiosInstance: AxiosInstance,
  positionId?: string[],
  recordTypeKey?: string | null,
): Promise<UploadKeyResponse> {
  const payload = {
    fileName: file.name,
    originalname: file.name,
    contentType: file.type || "application/octet-stream",
    size: file.size,
    ...(positionId?.length ? { positionId } : {}),
    recordTypeKey: recordTypeKey,
  };

  const { data } = await axiosInstance.post<UploadKeyResponse>(
    endpoint,
    payload,
    {
      headers: withHeaders(),
    },
  );

  return data;
}

/**
 * Upload file to presigned URL
 */
export async function uploadToPresigned(
  file: File,
  presignedUrl: string,
): Promise<void> {
  if (!presignedUrl) {
    throw new Error("Presigned URL is required");
  }

  const uploadRes = await presignedAxios.put(presignedUrl, file, {
    headers: {
      "Content-Type": file.type,
    },
  });

  if (uploadRes.status < 200 || uploadRes.status >= 300) {
    throw new Error(
      `Upload failed with status ${uploadRes.status}: ${uploadRes.statusText}`,
    );
  }
}

/**
 * Unified upload and create resource function
 */
export async function uploadAndCreateResource(
  params: UploadAndCreateResourceParams,
  axiosInstance: AxiosInstance,
  positionId?: string[],
  recordTypeKey?: string | null,
) {
  const { type, file, name, parentId, locale } = params;
  const typeConfig = config[type];

  // 1. Get upload key and presigned URL
  const uploadKeyResponse = await getUploadKey(
    typeConfig.uploadKey,
    file,
    axiosInstance,
    positionId,
    recordTypeKey,
  );

  const presignedUrl =
    uploadKeyResponse.presignedUrl || uploadKeyResponse.presigned;

  // 2. Upload file to presigned URL
  await uploadToPresigned(file, presignedUrl || "");

  // 3. For header/footer: done — no separate create POST needed
  if (type === "header" || type === "footer") {
    // 4. For signature/stamp: create resource
    const createPayload = {
      fileInfo: uploadKeyResponse.fileInfo,
      name,
      [typeConfig.parentField]: parentId,
      positionIds: positionId,
      isCurrent: true,
      recordTypeKey: recordTypeKey,
    };

    const { data } = await axiosInstance.post(
      typeConfig.create,
      createPayload,
      {
        headers: withHeaders(),
      },
    );

    return data;
  }

  // 4. For signature/stamp: create resource
  const createPayload = {
    fileInfo: uploadKeyResponse.fileInfo,
    name,
    [typeConfig.parentField]: parentId,
    ...(type === "signature" ? { isCurrent: true } : {}),
    ...(type === "stamp" && locale !== undefined ? { locale } : {}),
  };

  const { data } = await axiosInstance.post(typeConfig.create, createPayload, {
    headers: withHeaders(),
  });

  return data;
}
