import { Injectable, Logger } from "@nestjs/common";
import { ConfigService } from "@nestjs/config";
import axios from "axios";

@Injectable()
export class MetaService {
  private readonly logger = new Logger(MetaService.name);

  private readonly pageAccessToken: string;
  private readonly pageId: string;
  private readonly igUserId: string;
  private readonly isEnabled: boolean;
  private readonly graphApiBase: string;

  constructor(private readonly configService: ConfigService) {
    this.pageAccessToken =
      this.configService.get<string>("META_PAGE_ACCESS_TOKEN") || "";
    this.pageId = this.configService.get<string>("META_PAGE_ID") || "";
    this.igUserId = this.configService.get<string>("META_IG_USER_ID") || "";
    const graphVersion =
      this.configService.get<string>("META_GRAPH_API_VERSION") || "v25.0";
    this.graphApiBase = `https://graph.facebook.com/${graphVersion}`;

    this.isEnabled = !!(this.pageAccessToken && this.pageId);

    if (this.isEnabled) {
      this.logger.log("✅ Meta API client initialized");
    } else {
      this.logger.warn(
        "⚠️ Meta API not configured. Set META_PAGE_ACCESS_TOKEN, META_PAGE_ID, META_IG_USER_ID",
      );
    }
  }

  get facebookAvailable(): boolean {
    return this.isEnabled;
  }

  get instagramAvailable(): boolean {
    return this.isEnabled && !!this.igUserId;
  }

  // ═══════════════════════════════════════════════════════════════════════════
  // FACEBOOK
  // ═══════════════════════════════════════════════════════════════════════════

  /**
   * Post a photo to a Facebook Page.
   *
   * @param message - Post caption
   * @param imageUrl - Publicly accessible image URL
   * @returns Facebook post ID
   */
  async postToFacebook(
    message: string,
    imageUrl: string,
  ): Promise<string | null> {
    if (!this.facebookAvailable) {
      this.logger.warn("Facebook not available, skipping post");
      return null;
    }

    try {
      const response = await axios.post(
        `${this.graphApiBase}/${this.pageId}/photos`,
        {
          url: imageUrl,
          message,
          published: true,
          access_token: this.pageAccessToken,
        },
      );

      const postId = response.data?.post_id || response.data?.id;
      this.logger.log(`✅ Facebook post published: ${postId}`);
      return postId || null;
    } catch (error) {
      this.logger.error(
        `❌ Facebook post failed: ${error.response?.data?.error?.message || error.message}`,
      );
      return null;
    }
  }

  // ═══════════════════════════════════════════════════════════════════════════
  // INSTAGRAM
  // ═══════════════════════════════════════════════════════════════════════════

  /**
   * Post a photo to Instagram Business/Creator account.
   *
   * Two-step process:
   *   1. Create media container with image_url
   *   2. Publish the container
   *
   * @param caption - Post caption (max 2200 chars)
   * @param imageUrl - Publicly accessible JPEG image URL
   * @returns Instagram media ID
   */
  async postToInstagram(
    caption: string,
    imageUrl: string,
  ): Promise<string | null> {
    if (!this.instagramAvailable) {
      this.logger.warn("Instagram not available, skipping post");
      return null;
    }

    try {
      // Step 1: Create media container
      const containerResponse = await axios.post(
        `${this.graphApiBase}/${this.igUserId}/media`,
        {
          image_url: imageUrl,
          caption,
          alt_text: this.buildAltText(caption),
          access_token: this.pageAccessToken,
        },
      );

      const containerId = containerResponse.data?.id;
      if (!containerId) {
        throw new Error("No container ID returned");
      }

      // Wait for container processing (IG needs a few seconds)
      await this.waitForContainerReady(containerId);

      // Step 2: Publish
      const publishResponse = await axios.post(
        `${this.graphApiBase}/${this.igUserId}/media_publish`,
        {
          creation_id: containerId,
          access_token: this.pageAccessToken,
        },
      );

      const mediaId = publishResponse.data?.id;
      this.logger.log(`✅ Instagram post published: ${mediaId}`);
      return mediaId || null;
    } catch (error) {
      this.logger.error(
        `❌ Instagram post failed: ${error.response?.data?.error?.message || error.message}`,
      );
      return null;
    }
  }

  /**
   * Wait for Instagram container to be ready for publishing.
   */
  private async waitForContainerReady(
    containerId: string,
    maxWaitMs = 30000,
  ): Promise<void> {
    const startTime = Date.now();

    while (Date.now() - startTime < maxWaitMs) {
      try {
        const response = await axios.get(
          `${this.graphApiBase}/${containerId}`,
          {
            params: {
              fields: "status_code,status",
              access_token: this.pageAccessToken,
            },
          },
        );

        const status = response.data?.status_code;
        if (status === "FINISHED") return;
        if (status === "ERROR") {
          throw new Error("Container processing failed");
        }
      } catch (error) {
        if (error.message === "Container processing failed") throw error;
      }

      // Wait 2 seconds before checking again
      await new Promise((resolve) => setTimeout(resolve, 2000));
    }

    this.logger.warn("Container wait timed out, attempting publish anyway");
  }

  private buildAltText(caption: string): string {
    return caption
      .replace(/#[^\s#]+/g, "")
      .replace(/\s+/g, " ")
      .trim()
      .slice(0, 900);
  }
}
