/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable camelcase */
/* eslint-disable no-console */

import axios from 'axios';
import crypto from 'crypto';
import { Types } from 'mongoose';

import config from '@/shared/config/config';
import { PageConnection } from './pageConnection.model';
import { CaptureLead } from '../captureLeads/captureLeads.model';
import { leadWebhookService } from '../webhook/webhook.service';
import { getObjectId } from '@/shared/utils/commonHelper';

export const isCompanyUserMetaConnected = async (
  userId: Types.ObjectId,
  companyId: Types.ObjectId,
): Promise<boolean> => {
  try {
    if (!userId || !companyId) return false;

    const exists = await PageConnection.exists({
      client: getObjectId(userId),
      companyId: getObjectId(companyId),
    });

    return !!exists;
  } catch (error) {
    console.error('Error checking meta connection:', error);
    return false;
  }
};
export const buildState = (userId, companyId) => ({
  userId,
  companyId,
  csrfToken: Math.random().toString(36).substring(2),
});

export const encodeState = (stateObj) =>
  encodeURIComponent(Buffer.from(JSON.stringify(stateObj)).toString('base64'));

const buildRedirectUri = () =>
  `${config.backendUrl}/api/v1/captureLeads/auth/meta/callback`;

const buildScopes = () =>
  [
    'pages_show_list',
    'leads_retrieval',
    // 'pages_manage_ads',
    // 'pages_manage_metadata',
    'pages_manage_metadata',
    'pages_read_engagement',
  ].join(',');

export const buildOAuthUrl = (state) =>
  `https://www.facebook.com/v16.0/dialog/oauth?client_id=${config.metaLeadAppId}&redirect_uri=${buildRedirectUri()}&scope=${buildScopes()}&state=${state}`;

export const getAccessToken = async (code) => {
  const res = await axios.get(`${config.metaApiPath}/oauth/access_token`, {
    params: {
      client_id: config.metaLeadAppId,
      client_secret: config.metaLeadSecretId,
      redirect_uri: buildRedirectUri(),
      code,
    },
  });
  return res.data?.access_token;
};

export const exchangeLongLiveToken = async (shortToken) => {
  const res = await axios.get(`${config.metaApiPath}/oauth/access_token`, {
    params: {
      grant_type: 'fb_exchange_token',
      client_id: config.metaLeadAppId,
      client_secret: config.metaLeadSecretId,
      fb_exchange_token: shortToken,
    },
  });
  return res.data?.access_token || shortToken;
};

export const getPages = async (userToken) => {
  const res = await axios.get(`${config.metaApiPath}/me/accounts`, {
    params: { access_token: userToken },
  });
  return Array.isArray(res.data?.data) ? res.data.data : [];
};

export const savePageConnection = async (
  page,
  userId,
  companyId,
  encryptFn,
) => {
  if (!page?.id) return null;
  const enc = await encryptFn(page.access_token);
  const result = await PageConnection.findOneAndUpdate(
    {
      client: getObjectId(userId),
      companyId: getObjectId(companyId),
      'metaPageIds.pageId': page.id,
    },
    {
      $set: {
        pageName: page.name,
        encryptedPageAccessToken: enc.data,
        iv: enc.iv,
        tag: enc.tag,
      },
    },
    { new: true },
  );

  if (!result)
    // If no doc matched (means pageId didn't exist), then add new element
    return await PageConnection.findOneAndUpdate(
      { client: getObjectId(userId), companyId: getObjectId(companyId) },
      {
        $addToSet: {
          metaPageIds: { pageId: page.id },
        },
        $set: {
          pageName: page.name,
          encryptedPageAccessToken: enc.data,
          iv: enc.iv,
          tag: enc.tag,
        },
      },
      { new: true, upsert: true },
    );

  return result;
};

const makeAppSecretProof = (accessToken) =>
  crypto
    .createHmac('sha256', config.metaLeadSecretId)
    .update(accessToken)
    .digest('hex');

export const subscribePageToLeadgen = async (pageId, pageAccessToken) => {
  const appsecret_proof = makeAppSecretProof(pageAccessToken);

  const url = `${config.metaApiPath}/${pageId}/subscribed_apps`;
  const params = {
    subscribed_fields: 'leadgen',
    access_token: pageAccessToken,
    appsecret_proof,
  };

  const resp = await axios.post(url, null, { params });
  return resp.data;
};

export const buildSuccessHtml = (payload, clientUrl) => `
<!doctype html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>Auth complete</title>
    <meta name="viewport" content="width=device-width,initial-scale=1" />
    <style>
      html,body{height:100%;margin:0;font-family:Inter,system-ui,Segoe UI,Roboto,-apple-system,Helvetica,Arial;}
      .center {height:100%;display:flex;align-items:center;justify-content:center;flex-direction:column;color:#222;}
      .muted {color:#666;font-size:13px;margin-top:8px;}
      a {color:#0b66ff}
    </style>
  </head>
  <body>
    <div class="center">
      <div>Authentication complete.</div>
      <div class="muted">You can safely close this tab — returning you to the application.</div>
    </div>
    <script>
      (function(){
        try {
          if (window.opener && !window.opener.closed) {
            setTimeout(function() {
              window.opener.postMessage({ type: "makanify_meta_auth", payload: ${JSON.stringify(payload)} }, '${clientUrl}');
              window.close();
            }, 1000);
          }
        } catch(e) { console.error('postMessage error:', e); }
      })();
    </script>
  </body>
</html>
`;

export const buildErrorHtml = (errorUrl) => `
<!doctype html>
<html>
  <head>
    <meta charset="utf-8"/>
    <title>Auth failed</title>
  </head>
  <body>
    <div style="font-family:Inter,system-ui,Arial;padding:24px">
      <h2>Authentication failed</h2>
      <p>Unable to complete authentication. You will be redirected back to the application.</p>
      <p><a href="${errorUrl}">Continue to App</a></p>
    </div>
    <script>setTimeout(function(){ window.location.href = "${errorUrl}"; }, 700);</script>
  </body>
</html>
`;

// Extract leads data from field_data array
export function extractLeadData(
  fields: Array<{ name: string; values: any[] }>,
) {
  let firstName = '';
  let lastName = '';
  let phone = '';
  let email = '';

  for (const f of fields) {
    const key = (f.name || '').toLowerCase();
    const val = Array.isArray(f.values) ? f.values[0] : f.values;
    if (!val) continue;

    if (key.includes('phone') && typeof val === 'string') {
      phone = val;
    } else if (key.includes('email') && typeof val === 'string') {
      email = val;
    } else if (key.includes('full') && typeof val === 'string') {
      const nameParts = val.trim().split(/\s+/);
      if (nameParts.length > 0) {
        firstName = nameParts[0];
        lastName = nameParts.slice(1).join(' ');
      }
    }
  }

  return {
    firstName: firstName || 'Meta Lead',
    lastName: lastName || '',
    phone: phone || '',
    email: email || '',
  };
}

// Find integration by page id
export async function findIntegrationByPageId(page_id: string) {
  try {
    return await PageConnection.findOne({
      metaPageIds: { $elemMatch: { pageId: page_id } },
    }).lean();
  } catch (err) {
    console.error('Failed to find integration for page:', page_id, err);
    throw err;
  }
}

// Fetch leadgen details from Meta Graph API
export async function fetchLeadDetails(
  leadgen_id: string,
  access_token: string,
) {
  try {
    const response = await axios.get(`${config.metaApiPath}/${leadgen_id}`, {
      params: { access_token },
    });
    return response.data;
  } catch (err) {
    console.error('Graph API fetch error for leadgen:', leadgen_id, err);
    throw err;
  }
}

// Find active captureLead for company
export async function findActiveCaptureLead(integration: any, pageId: string) {
  try {
    const metaPageObj = integration.metaPageIds.find(
      (p) => p.pageId === pageId,
    );

    if (!metaPageObj || !metaPageObj.captureLead) {
      console.warn('No captureLead found for this pageId:', pageId);
      return null;
    }

    const captureLeadId = metaPageObj.captureLead;

    let captureLead = captureLeadId
      ? await CaptureLead.findById(captureLeadId).lean()
      : await CaptureLead.findOne({
          company: integration.companyId,
          platform: 'meta',
          isDeleted: { $ne: true },
        }).lean();

    if (!captureLead || captureLead.isActive === false) return null;
    return captureLead;
  } catch (err) {
    console.error('Failed to find active captureLead:', err);
    throw err;
  }
}

// Import leads via service
export async function importLeads(
  companyId: string,
  captureLead: any,
  leads: any[],
  isCheckCustomFields?: boolean,
) {
  try {
    await leadWebhookService.bulkImportLeads({
      companyId,
      captureLead,
      leads,
      isCheckCustomFields,
    });
  } catch (err) {
    console.error('bulkImportLeads failed:', err, { companyId });
    throw err;
  }
}
