const axios = require('axios');
const { CookieJar } = require('tough-cookie');

const tokenAppMap = {
  EAAAAU: '350685531728',
  EAAD: '256002347743983',
  EAAAAAY: '6628568379',
  EAADYP: '237759909591655',
  EAAD6V7: '275254692598279',
  EAAC2SPKT: '202805033077166',
  EAAGOfO: '200424423651082',
  EAAVB: '438142079694454',
  EAAC4: '1479723375646806',
  EAACW5F: '165907476854626',
  EAAB: '121876164619130',
  EAAQ: '1174099472704185',
  EAAGNO4: '436761779744620',
  EAAH: '522404077880990',
  EAAC: '184182168294603',
  EAAClA: '173847642670370',
  EAATK: '1348564698517390',
  EAAI7: '628551730674460',
};

const validateCookie = (cookie) => {
  if (!cookie || typeof cookie !== 'string') {
    return { isValid: false, error: 'Cookie is required and must be a string' };
  }

  const requiredCookies = ['c_user', 'xs'];
  const cookiePairs = cookie.split(';').map(pair => pair.trim().split('=')[0]);

  for (const required of requiredCookies) {
    if (cookiePairs.indexOf(required) === -1) {
      return { isValid: false, error: 'Missing required cookie: ' + required };
    }
  }

  if (cookie.length > 10000) {
    return { isValid: false, error: 'Cookie too long' };
  }

  const suspiciousPatterns = [
    /<script/i,
    /javascript:/i,
    /data:/i,
    /vbscript:/i,
    /onload=/i,
    /onerror=/i
  ];

  for (const pattern of suspiciousPatterns) {
    if (pattern.test(cookie)) {
      return { isValid: false, error: 'Invalid cookie format' };
    }
  }

  return { isValid: true };
};

const validateTokenType = (type) => {
  if (!type || typeof type !== 'string') {
    return { isValid: false, error: 'Token type is required' };
  }

  const validTypes = [
    'EAAAAU', 'EAAD', 'EAAAAAY', 'EAADYP', 'EAAD6V7',
    'EAAC2SPKT', 'EAAGOfO', 'EAAVB', 'EAAC4', 'EAACW5F',
    'EAAB', 'EAAQ', 'EAAGNO4', 'EAAH', 'EAAC',
    'EAAClA', 'EAATK', 'EAAI7'
  ];

  if (validTypes.indexOf(type.toUpperCase()) === -1) {
    return { isValid: false, error: 'Invalid token type' };
  }

  return { isValid: true };
};

const generateUUID = () =>
  'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) =>
    (c === 'x' ? Math.random() * 16 | 0 : (Math.random() * 4 | 8)).toString(16)
  );

const parseCookies = (cookieString) => {
  const cookies = {};
  cookieString.split(';').forEach((cookie) => {
    const [name, value] = cookie.trim().split('=');
    if (name && value) {
      cookies[name] = value;
    }
  });
  return cookies;
};

const extractUserID = (cookieString) => {
  const cookies = parseCookies(cookieString);
  return cookies['c_user'] || null;
};

const getFrom = (html, start, end) => {
  const startIndex = html.indexOf(start);
  if (startIndex === -1) return '';
  const valueStart = startIndex + start.length;
  const endIndex = html.indexOf(end, valueStart);
  if (endIndex === -1) return '';
  return html.substring(valueStart, endIndex);
};

const extractFacebookParams = (html, userID) => {
  const fb_dtsg = getFrom(html, '"DTSGInitData",[],{"token":"', '"');
  const jazoest = html.match(/&jazoest=([^"]+)/)?.[1] || '';
  const revision = getFrom(html, 'revision":', ',');
  const __hs = getFrom(html, '"haste_session":"', '"');
  const lsd = getFrom(html, '["LSD",[],{"token":"', '"}');
  const hsi = getFrom(html, '"hsi":"', '",');
  let reqCounter = 1;

  const mergeWithDefaults = (obj = {}) => {
    const base = {
      __aaid: 0,
      av: userID,
      __user: userID,
      __req: (reqCounter++).toString(36),
      __rev: revision,
      __a: 1,
      __hs,
      dpr: 1,
      lsd,
      hsi,
      fb_dtsg,
      jazoest,
      __comet_req: 15,
      __spin_r: revision,
      __spin_t: Math.floor(Date.now() / 1000),
      __spin_b: 'trunk',
    };
    return { ...base, ...obj };
  };

  return { fb_dtsg, jazoest, revision, __hs, lsd, hsi, mergeWithDefaults };
};

const createAxiosWithCookies = (cookieString) => {
  const jar = new CookieJar();
  const cookies = parseCookies(cookieString);
  Object.entries(cookies).forEach(([name, value]) => {
    try {
      jar.setCookieSync(`${name}=${value}`, 'https://www.facebook.com');
    } catch (error) {
      console.warn(`Failed to set cookie ${name}:`, error);
    }
  });

  const instance = axios.create({
    timeout: 30000,
    headers: {
      authority: 'www.facebook.com',
      method: 'GET',
      path: '/',
      scheme: 'https',
      Accept:
        'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
      'Accept-Encoding': 'gzip, deflate, br',
      'Accept-Language': 'vi,en-US;q=0.9,en;q=0.8,fr-FR;q=0.7,fr;q=0.6',
      dpr: '1',
      Priority: 'u=0, i',
      'Sec-Ch-Prefers-Color-Scheme': 'dark',
      'Sec-Ch-Ua': '"Chromium";v="136", "Google Chrome";v="136", "Not.A/Brand";v="99"',
      'Sec-Ch-Ua-Full-Version-List':
        '"Chromium";v="136.0.7103.154", "Google Chrome";v="136.0.7103.154", "Not.A/Brand";v="99.0.0.0"',
      'Sec-Ch-Ua-Mobile': '?0',
      'Sec-Ch-Ua-Model': '""',
      'Sec-Ch-Ua-Platform': '"Windows"',
      'Sec-Ch-Ua-Platform-Version': '"19.0.0"',
      'Sec-Fetch-Dest': 'document',
      'Sec-Fetch-Mode': 'navigate',
      'Sec-Fetch-Site': 'none',
      'Sec-Fetch-User': '?1',
      'Upgrade-Insecure-Requests': '1',
      'User-Agent':
        'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
      'Viewport-Width': '1104',
      'x-fb-lsd': '',
      'x-response-format': 'JSONStream',
      'x-asbd-id': '129477',
    },
  });

  instance.interceptors.request.use((config) => {
    const cookieHeader = jar.getCookieStringSync('https://www.facebook.com');
    if (cookieHeader) {
      config.headers['Cookie'] = cookieHeader;
    }
    return config;
  });

  return instance;
};

async function convertCookieToToken(cookie, type) {
  try {
    // Xác thực cookie
    const cookieValidation = validateCookie(cookie);
    if (!cookieValidation.isValid) {
      throw new Error(cookieValidation.error);
    }

    // Xác thực token type
    const typeValidation = validateTokenType(type);
    if (!typeValidation.isValid) {
      throw new Error(typeValidation.error);
    }

    const tokenType = type.toUpperCase();
    const appID = tokenAppMap[tokenType];

    // Lấy userID từ cookie
    const userID = extractUserID(cookie);
    if (!userID) {
      throw new Error('Invalid cookie: c_user not found');
    }

    // Tạo instance axios với cookie
    const axiosInstance = createAxiosWithCookies(cookie);
    console.log('Fetching Facebook home page...');
    const homeResponse = await axiosInstance.get('https://www.facebook.com/');
    const homeHtml = homeResponse.data;

    // Trích xuất tham số Facebook
    const fbParams = extractFacebookParams(homeHtml, userID);
    if (!fbParams.fb_dtsg || !fbParams.lsd) {
      throw new Error('Failed to extract required Facebook parameters');
    }

    // Chuẩn bị dữ liệu cho yêu cầu GraphQL
    const formData = fbParams.mergeWithDefaults({
      doc_id: '6494107973937368',
      variables: JSON.stringify({
        input: {
          client_mutation_id: Math.round(Math.random() * 19).toString(),
          actor_id: userID,
          config_enum: 'GDP_CONFIRM',
          device_id: null,
          experience_id: generateUUID(),
          extra_params_json: JSON.stringify({
            app_id: '350685531728',
            kid_directed_site: 'false',
            logger_id: `"${generateUUID()}"`,
            next: '"confirm"',
            redirect_uri: '"https://www.facebook.com/connect/login_success.html"',
            response_type: '"token"',
            return_scopes: 'false',
            scope: '["ads_management","pages_show_list","business_management","publish_to_groups","public_profile"]',
            steps: '{}',
            tp: '"unspecified"',
            cui_gk: '"[PASS]:""',
            is_limited_login_shim: 'false',
          }),
          flow_name: 'GDP',
          flow_step_type: 'STANDALONE',
          outcome: 'APPROVED',
          source: 'gdp_delegated',
          surface: 'FACEBOOK_COMET',
        },
      }),
      server_timestamps: 'true',
    });

    console.log('Making GraphQL request...');
    const response = await axiosInstance.post(
      'https://www.facebook.com/api/graphql/',
      new URLSearchParams(
        Object.fromEntries(Object.entries(formData).map(([key, value]) => [key, String(value)]))
      ).toString(),
      {
        headers: {
          'Content-Type': 'application/x-www-form-urlencoded',
          'X-FB-Friendly-Name': 'RunPostFlowActionMutation',
          'X-FB-LSD': fbParams.lsd,
          'X-FB-IRISSEQID': '1',
        },
      }
    );

    const responseData = response.data;
    console.log('GraphQL response received');

    // Trích xuất URI và token
    const uri = responseData?.data?.run_post_flow_action?.uri;
    if (!uri) {
      console.error('No URI in response:', responseData);
      throw new Error('Failed to get authorization URI from Facebook');
    }

    const queryString = uri.split('?')[1];
    const closeUri = queryString && new URLSearchParams(queryString).get('close_uri');
    const fullToken = closeUri?.includes('#access_token=')
      ? new URLSearchParams(closeUri.split('#')[1]).get('access_token')
      : null;

    if (!fullToken) {
      console.error('Failed to extract token from URI:', uri);
      throw new Error('Failed to extract EAAAAU token');
    }

    console.log('Token extracted successfully');

    // Nếu type là EAAAAU, trả về token ngay
    if (tokenType === 'EAAAAU') {
      return {
        success: true,
        token: fullToken,
        type: tokenType,
      };
    }

    // Chuyển đổi token sang loại khác
    console.log('Converting token to', tokenType);
    const convertURL = `https://api.facebook.com/method/auth.getSessionforApp?format=json&access_token=${fullToken}&new_app_id=${appID}`;
    const convertResponse = await axiosInstance.get(convertURL);
    const convertData = convertResponse.data;

    if (convertData?.access_token) {
      console.log('Token conversion successful');
      return {
        success: true,
        token: convertData.access_token,
        type: tokenType,
      };
    } else {
      console.error('Token conversion failed:', convertData);
      throw new Error('Failed to convert token');
    }
  } catch (error) {
    console.error('ConvertCookieToToken Error:', error.message);
    return {
      success: false,
      error: error.message || 'Internal server error',
    };
  }
}

// Export chỉ hàm convertCookieToToken
module.exports = {
  convertCookieToToken
};