import { resolveLinkedInMemberId } from "@/lib/social/linkedin-member";
import { loadPublishableImageBuffer } from "@/lib/social/publish-image";

export interface LinkedInPublishResult {
  success: boolean;
  postUrn?: string;
  permalink?: string;
  error?: string;
  imageAttached: boolean;
}


async function resolvePersonUrn(accessToken: string, externalId?: string | null): Promise<string> {
  return resolveLinkedInMemberId(accessToken, externalId);
}

async function uploadLinkedInImage(
  accessToken: string,
  personUrn: string,
  imageBuffer: Buffer,
): Promise<string> {
  const registerRes = await fetch(
    "https://api.linkedin.com/v2/assets?action=registerUpload",
    {
      method: "POST",
      headers: {
        Authorization: `Bearer ${accessToken}`,
        "Content-Type": "application/json",
        "X-Restli-Protocol-Version": "2.0.0",
      },
      body: JSON.stringify({
        registerUploadRequest: {
          recipes: ["urn:li:digitalmediaRecipe:feedshare-image"],
          owner: personUrn,
          serviceRelationships: [
            {
              relationshipType: "OWNER",
              identifier: "urn:li:userGeneratedContent",
            },
          ],
        },
      }),
    },
  );

  const registerData = (await registerRes.json()) as {
    value?: {
      asset?: string;
      uploadMechanism?: {
        "com.linkedin.digitalmedia.uploading.MediaUploadHttpRequest"?: {
          uploadUrl?: string;
        };
      };
    };
    message?: string;
  };

  if (!registerRes.ok || !registerData.value?.asset) {
    throw new Error(registerData.message ?? "LinkedIn image upload registration failed");
  }

  const uploadUrl =
    registerData.value.uploadMechanism?.[
      "com.linkedin.digitalmedia.uploading.MediaUploadHttpRequest"
    ]?.uploadUrl;

  if (!uploadUrl) {
    throw new Error("LinkedIn did not return an image upload URL");
  }

  const uploadRes = await fetch(uploadUrl, {
    method: "PUT",
    headers: { "Content-Type": "application/octet-stream" },
    body: new Uint8Array(imageBuffer),
  });

  if (!uploadRes.ok) {
    throw new Error(`LinkedIn image upload failed (${uploadRes.status})`);
  }

  return registerData.value.asset;
}

export async function publishToLinkedIn(input: {
  accessToken: string;
  externalId?: string | null;
  caption: string;
  imageUrl?: string | null;
  appOrigin: string;
}): Promise<LinkedInPublishResult> {
  try {
    const personUrn = await resolvePersonUrn(input.accessToken, input.externalId);
    let assetUrn: string | null = null;
    let imageAttached = false;

    if (input.imageUrl) {
      const buffer = await loadPublishableImageBuffer(input.imageUrl, input.appOrigin);
      if (buffer) {
        assetUrn = await uploadLinkedInImage(input.accessToken, personUrn, buffer);
        imageAttached = true;
      }
    }

    const shareContent: Record<string, unknown> = {
      shareCommentary: { text: input.caption.slice(0, 3000) },
      shareMediaCategory: assetUrn ? "IMAGE" : "NONE",
    };

    if (assetUrn) {
      shareContent.media = [
        {
          status: "READY",
          description: { text: "Post image" },
          media: assetUrn,
          title: { text: "Post" },
        },
      ];
    }

    const postRes = await fetch("https://api.linkedin.com/v2/ugcPosts", {
      method: "POST",
      headers: {
        Authorization: `Bearer ${input.accessToken}`,
        "Content-Type": "application/json",
        "X-Restli-Protocol-Version": "2.0.0",
      },
      body: JSON.stringify({
        author: personUrn,
        lifecycleState: "PUBLISHED",
        specificContent: {
          "com.linkedin.ugc.ShareContent": shareContent,
        },
        visibility: {
          "com.linkedin.ugc.MemberNetworkVisibility": "PUBLIC",
        },
      }),
    });

    const postData = (await postRes.json()) as {
      id?: string;
      message?: string;
      status?: number;
    };

    if (!postRes.ok) {
      const errMsg =
        postData.message ??
        (typeof postData === "object" ? JSON.stringify(postData) : "LinkedIn post failed");
      return { success: false, error: errMsg, imageAttached };
    }

    const postUrn = postData.id;
    return {
      success: true,
      postUrn,
      permalink: postUrn
        ? `https://www.linkedin.com/feed/update/${encodeURIComponent(postUrn)}`
        : undefined,
      imageAttached,
    };
  } catch (error) {
    return {
      success: false,
      error: error instanceof Error ? error.message : "LinkedIn publish failed",
      imageAttached: false,
    };
  }
}
