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

@Injectable()
export class LinkedinProvider {
  private readonly logger = new Logger(LinkedinProvider.name);
  private accessToken: string;
  private organizationId: string;

  constructor(private configService: ConfigService) {
    this.accessToken = this.configService.get<string>('LINKEDIN_ACCESS_TOKEN');
    this.organizationId = this.configService.get<string>('LINKEDIN_ORGANIZATION_ID');
  }

  async publishPost(content: string, imageUrl: string): Promise<string> {
    this.logger.log(`Publishing post to LinkedIn: ${content}`);
    try {
      // Verify that required config values exist
      if (!this.accessToken || !this.organizationId) {
        throw new Error('LinkedIn access token or organization ID is missing');
      }

      // Log organization ID to verify it's correct
      this.logger.log(`Using organization ID: ${this.organizationId}`);

      // 1. Register an upload
      const registerUploadResponse = await axios.post(
        'https://api.linkedin.com/v2/assets?action=registerUpload',
        {
          registerUploadRequest: {
            recipes: ['urn:li:digitalmediaRecipe:feedshare-image'],
            owner: `urn:li:organization:${this.organizationId}`,
            serviceRelationships: [
              {
                relationshipType: 'OWNER',
                identifier: 'urn:li:userGeneratedContent',
              },
            ],
          },
        },
        {
          headers: {
            Authorization: `Bearer ${this.accessToken}`,
            'Content-Type': 'application/json',
          },
        },
      );

      if (!registerUploadResponse || !registerUploadResponse.data) {
        this.logger.error('Failed to register upload, no response data received');
        throw new Error('Failed to register upload, no response data received');
      }

      const uploadUrl = registerUploadResponse.data.value.uploadMechanism['com.linkedin.digitalmedia.uploading.MediaUploadHttpRequest'].uploadUrl;
      const asset = registerUploadResponse.data.value.asset;

      this.logger.log(`Upload URL: ${uploadUrl}`);
      this.logger.log(`Asset: ${asset}`);

      // 2. Download image from our server
      const imageResponse = await axios.get(imageUrl, { responseType: 'arraybuffer' });

      if (!imageResponse || !imageResponse.data) {
        this.logger.error('Failed to download image, no response data received');
        throw new Error('Failed to download image, no response data received');
      }
      this.logger.log(`Image downloaded successfully`);

      // 3. Upload image to LinkedIn
      await axios.put(uploadUrl, imageResponse.data, {
        headers: {
          Authorization: `Bearer ${this.accessToken}`,
          'Content-Type': 'application/octet-stream',
        },
      });

      this.logger.log(`Image uploaded successfully`);

      this.logger.log(`Creating post with asset: ${asset}`);

      // 4. Post with the image - FIXED AUTHOR FIELD FORMAT
      const postData = {
        author: `urn:li:organization:${this.organizationId}`,
        lifecycleState: 'PUBLISHED',
        specificContent: {
          'com.linkedin.ugc.ShareContent': {
            shareCommentary: {
              text: content,
            },
            shareMediaCategory: 'IMAGE',
            media: [
              {
                status: 'READY',
                description: {
                  text: 'Cyber Alert',
                },
                media: asset,
              },
            ],
          },
        },
        visibility: {
          'com.linkedin.ugc.MemberNetworkVisibility': 'PUBLIC',
        },
      };

      // Log the post data for debugging
      this.logger.log(`Sending post data: ${JSON.stringify(postData)}`);

      const postResponse = await axios
        .post('https://api.linkedin.com/v2/ugcPosts', postData, {
          headers: {
            Authorization: `Bearer ${this.accessToken}`,
            'Content-Type': 'application/json',
          },
        })
        .catch(error => {
          const errorDetails = error.response?.data || error;
          this.logger.error(`Post creation failed: ${error.message}`, errorDetails);
          throw new Error(`Post creation failed: ${error.message} - ${JSON.stringify(errorDetails)}`);
        });

      if (!postResponse || !postResponse.data) {
        this.logger.error('Failed to create post, no response data received');
        throw new Error('Failed to create post, no response data received');
      }

      this.logger.log(`Post created successfully: ${postResponse.data.id}`);

      return postResponse.data.id;
    } catch (error) {
      this.logger.error(`LinkedIn post failed: ${error.message}`, error.stack);
      throw new Error(`Failed to publish to LinkedIn: ${error.message}`);
    }
  }

  // Helpful method to verify access token
  async verifyAccessToken(): Promise<boolean> {
    try {
      const response = await axios.get('https://api.linkedin.com/v2/me', {
        headers: { Authorization: `Bearer ${this.accessToken}` },
      });

      this.logger.log(`Access token is valid. User ID: ${response.data.id}`);
      return true;
    } catch (error) {
      this.logger.error(`Access token verification failed: ${error.message}`);
      return false;
    }
  }
}
