import fetch from 'node-fetch';
import FormData from 'form-data';
import { promises as fs } from 'fs';
import path from 'path';
import mime from 'mime-types';
import { loadCredentials } from './credentials.js';

const BASE_URL = 'https://www.textnow.com';
const API_URL = `${BASE_URL}/api`;

/**
 * Get headers for API requests
 */
function getHeaders(credentials, extraHeaders = {}) {
  const headers = {
    'Accept': 'application/json',
    'Content-Type': 'application/json',
    'Cookie': credentials.cookies,
    'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
    'Referer': 'https://www.textnow.com/messaging',
    'Origin': 'https://www.textnow.com',
    ...extraHeaders,
  };
  
  // Add CSRF token if available
  if (credentials.authCookies?.xsrfToken) {
    headers['X-XSRF-TOKEN'] = decodeURIComponent(credentials.authCookies.xsrfToken);
  }
  
  return headers;
}

/**
 * Make an authenticated API request
 */
async function apiRequest(endpoint, options = {}) {
  const credentials = await loadCredentials();
  if (!credentials) {
    throw new Error('Not authenticated. Run `textnow auth` first.');
  }
  
  const url = endpoint.startsWith('http') ? endpoint : `${API_URL}${endpoint}`;
  const headers = getHeaders(credentials, options.headers);
  
  const response = await fetch(url, {
    ...options,
    headers,
  });
  
  if (!response.ok) {
    const text = await response.text();
    throw new Error(`API Error ${response.status}: ${text}`);
  }
  
  const contentType = response.headers.get('content-type');
  if (contentType?.includes('application/json')) {
    return response.json();
  }
  return response.text();
}

/**
 * Get user profile/account info
 */
export async function getUserProfile() {
  // Try multiple endpoints that might return user info
  try {
    // Primary user endpoint
    const user = await apiRequest('/users/me');
    return user;
  } catch (e) {
    // Try alternative endpoint
    try {
      const data = await apiRequest('/v3/users/me');
      return data;
    } catch (e2) {
      // Try session info
      const session = await apiRequest('/session');
      return session;
    }
  }
}

/**
 * Get the user's phone number
 */
export async function getPhoneNumber() {
  try {
    const data = await apiRequest('/users/me');
    return data.phone_number || data.phoneNumber || null;
  } catch {
    return null;
  }
}

/**
 * Normalize phone number to E.164 format
 */
function normalizePhone(phone) {
  // Remove all non-digits
  let digits = phone.replace(/\D/g, '');
  
  // Add country code if missing (assume US)
  if (digits.length === 10) {
    digits = '1' + digits;
  }
  
  return '+' + digits;
}

/**
 * Send an SMS message
 */
export async function sendMessage(to, message) {
  const credentials = await loadCredentials();
  if (!credentials) {
    throw new Error('Not authenticated. Run `textnow auth` first.');
  }
  
  const normalizedPhone = normalizePhone(to);
  
  // Get user's phone number for "from"
  const profile = await getUserProfile();
  const fromNumber = profile.phone_number || profile.phoneNumber;
  
  if (!fromNumber) {
    throw new Error('Could not determine your TextNow phone number');
  }
  
  // TextNow API for sending messages
  const response = await apiRequest('/v3/send_message', {
    method: 'POST',
    body: JSON.stringify({
      to_number: normalizedPhone,
      message: message,
      from_number: fromNumber,
      message_type: 'text',
    }),
  });
  
  return response;
}

/**
 * Send an image message
 */
export async function sendImage(to, imagePath, caption = '') {
  const credentials = await loadCredentials();
  if (!credentials) {
    throw new Error('Not authenticated. Run `textnow auth` first.');
  }
  
  const normalizedPhone = normalizePhone(to);
  const profile = await getUserProfile();
  const fromNumber = profile.phone_number || profile.phoneNumber;
  
  if (!fromNumber) {
    throw new Error('Could not determine your TextNow phone number');
  }
  
  // Read the image file
  const absolutePath = path.resolve(imagePath);
  const imageBuffer = await fs.readFile(absolutePath);
  const mimeType = mime.lookup(absolutePath) || 'image/jpeg';
  const filename = path.basename(absolutePath);
  
  // First, upload the image
  const form = new FormData();
  form.append('file', imageBuffer, {
    filename,
    contentType: mimeType,
  });
  
  const uploadHeaders = getHeaders(credentials, {});
  delete uploadHeaders['Content-Type']; // Let form-data set it
  
  const uploadResponse = await fetch(`${API_URL}/v3/upload_media`, {
    method: 'POST',
    headers: {
      ...uploadHeaders,
      ...form.getHeaders(),
    },
    body: form,
  });
  
  if (!uploadResponse.ok) {
    const text = await uploadResponse.text();
    throw new Error(`Upload failed ${uploadResponse.status}: ${text}`);
  }
  
  const uploadResult = await uploadResponse.json();
  const mediaUrl = uploadResult.url || uploadResult.media_url;
  
  // Now send the message with the media
  const response = await apiRequest('/v3/send_message', {
    method: 'POST',
    body: JSON.stringify({
      to_number: normalizedPhone,
      message: caption,
      from_number: fromNumber,
      message_type: 'image',
      media_url: mediaUrl,
    }),
  });
  
  return response;
}

/**
 * Get recent messages
 */
export async function getMessages(limit = 20) {
  // Try to get conversations first
  try {
    const conversations = await apiRequest(`/v3/conversations?page_size=${limit}`);
    return conversations;
  } catch {
    // Try alternative endpoint
    const messages = await apiRequest(`/messages?page_size=${limit}`);
    return messages;
  }
}

/**
 * Get messages from a specific conversation
 */
export async function getConversation(contactNumber, limit = 20) {
  const normalizedPhone = normalizePhone(contactNumber);
  const messages = await apiRequest(`/v3/conversations/${encodeURIComponent(normalizedPhone)}/messages?page_size=${limit}`);
  return messages;
}
