import axios from 'axios';
import { Model, Types } from 'mongoose';
import { ICompanyDoc } from '@/modules/company/company.interface';
import config from '@/shared/config/config';
import { getSuperAdminCompanyId } from '../fast2sms/fast2sms.helper';
import { Status, TriggerPoint } from '@/shared/constants/enum.constant';
import { getObjectId } from '@/shared/utils/commonHelper';
import { Company } from '@/modules/company/company.model';

export const getWhatsappCreds = async (
  companyId: string | Types.ObjectId,
  model,
) => {
  const company = await model
    .findById(companyId)
    .select('whatsapp whatsAppCredit ');

  const hasValidValues = Object.values(company.whatsapp).some(
    (value: string) => value && value.length > 0,
  );

  if (!company.whatsapp || !hasValidValues)
    return {
      whatsAppCredit: company.whatsAppCredit,
    };

  return { ...company.whatsapp, whatsAppCredit: company.whatsAppCredit };
};

const fetchWhatsappTemplates = async (token: string, businessId: string) => {
  const url = `${config.metaApiPath}/${businessId}/message_templates`;
  try {
    const res = await axios.get(url, {
      headers: { Authorization: `Bearer ${token}` },
    });
    const templates = res.data?.data ?? [];
    if (!templates.length) return;

    return res;
  } catch (_error) {
    return;
  }
};

export const refreshWhatsAppToken = async (
  companyModel: Model<ICompanyDoc>,
  companyId: string | Types.ObjectId,
  _fbAppId: string,
  _fbAppSecret: string,
  _accessToken: string,
): Promise<string | undefined> => {
  try {
    const creds = await getWhatsappCreds(companyId, companyModel);

    /* eslint-disable */
    const response = await axios.post(
      `${config.metaApiPath}/oauth/access_token`,
      new URLSearchParams({
        grant_type: 'fb_exchange_token',
        client_id: creds.fbAppId,
        client_secret: creds.fbSecretId,
        fb_exchange_token: creds.accessToken,
      }),
      {
        headers: {
          'Content-Type': 'application/x-www-form-urlencoded',
        },
      },
    );

    const newAccessToken: string = response.data.access_token;
    const expiresIn: number = response.data.expires_in;

    console.log(`New Access Token: ${newAccessToken}`);
    console.log(`Expires In: ${expiresIn} seconds`);

    await companyModel.findByIdAndUpdate(companyId, {
      $set: { 'whatsapp.accessToken': newAccessToken },
    });

    console.log('Company document updated with new access token.');
    return newAccessToken;
  } catch (error) {
    console.error(
      'Error refreshing token:',
      error.response?.data || error.message,
    );
    return undefined;
  }
};

// Seeder that should be run once for the superadmin company
export const seedSuperadminTemplates = async (model, superAdminId) => {
  let company = (await getSuperAdminCompanyId()) as ICompanyDoc;

  const isWhatsappEmpty =
    !company?.whatsapp ||
    Object.values(company.whatsapp || {}).every(
      (v) => v === null || v === undefined || v === '',
    );

  if (isWhatsappEmpty) {
    await Company.updateOne(
      { _id: company.id },
      {
        $set: {
          whatsapp: {
            accessToken: config.whatsappTemplate.accessToken,
            businessId: config.whatsappTemplate.businessId,
            phoneNumberId: config.whatsappTemplate.phoneNumberId,
            fbAppId: config.whatsappTemplate.fbAppId,
            fbSecretId: config.whatsappTemplate.fbSecretId,
          },
        },
      },
    );
  }

  const res = await fetchWhatsappTemplates(
    config.whatsappTemplate.accessToken,
    config.whatsappTemplate.businessId,
  );
  if (!res) return;
  const templates = res.data?.data ?? [];

  return await model.bulkWrite(
    templates
      .filter((t) => t.status === 'APPROVED' && t.name !== 'hello_world')
      .map((t) => {
        const headerComp = t.components?.find(
          (c) => c.type === 'HEADER' && c.text,
        );
        const bodyComp = t.components?.find((c) => c.type === 'BODY' && c.text);

        return {
          updateOne: {
            filter: { companyId: superAdminId, templateId: t.id },
            update: {
              $setOnInsert: {
                companyId: superAdminId,
                templateId: t.id,
                name: t.name,
                whatsappStatus: t.status ?? null,
                category: t.category ?? null,
                language: t.language ?? null,
                headerText: headerComp?.text ?? null,
                bodyText: bodyComp?.text ?? null,
                isDefault: true, // Important: true for superadmin seeds!
                status: 'active',
              },
            },
            upsert: true,
          },
        };
      }),
    { ordered: false },
  );
};



export const syncWhatsappTemplates = async (
  model: any,
  companyModel: any,
  companyId: string | Types.ObjectId,
  responseCode,
) => {
  try {
    if (!companyId) return;
    const companyObjectId = getObjectId(companyId);

    // --- 1. SEED MISSING TEMPLATES FROM SUPERADMIN ---
    const superAdmin = await getSuperAdminCompanyId();

    // Fetch valid templates from SuperAdmin
    const superadminTemplates = await model.find({
      companyId: superAdmin.id,
      whatsappStatus: 'APPROVED',
      name: { $ne: 'hello_world' },
      status: Status.ACTIVE, // Assuming Status.ACTIVE = 'ACTIVE'
    });

    if (superadminTemplates.length > 0) {
      // Get names of templates this company already has to ensure uniqueness
      const existingTemplateNames = await model.distinct('name', {
        companyId: companyObjectId,
      });

      const templatesToSeed = superadminTemplates
        .filter((t) => !existingTemplateNames.includes(t.name))
        .map((t) => {
          const doc = { ...t._doc };
          delete doc._id;
          delete doc.createdAt;
          delete doc.updatedAt;
          doc.companyId = companyObjectId;
          doc.isDefault = true; // Mark as seeded
          return doc;
        });

      if (templatesToSeed.length > 0) {
        console.log(
          `Seeding ${templatesToSeed.length} unique templates from SuperAdmin.`,
        );
        await model.insertMany(templatesToSeed, { ordered: false });
      }
    }

    // --- 2. SYNC FROM META API (IF CREDS EXIST) ---
    const creds = await getWhatsappCreds(companyId, companyModel);
    if (!creds?.whatsapp?.accessToken) {
      console.log('No Meta credentials found. Skipping API sync.');
      return;
    }

    let templates: any[] = [];
    let accessToken = creds.whatsapp.accessToken;

    try {
      const res = await fetchWhatsappTemplates(
        accessToken,
        creds.whatsapp.businessId,
      );
      templates = res.data?.data ?? [];
    } catch (error: any) {
      // Handle Token Expiry
      if (error.response?.status === 401) {
        const newToken = await refreshWhatsAppToken(
          companyModel,
          companyId,
          creds.fbAppId,
          creds.fbSecretId,
          creds.accessToken,
        );
        if (!newToken) return false;
        creds.accessToken = newToken;
        const retryRes = await fetchWhatsappTemplates(
          newToken,
          creds.businessId,
        );
        templates = retryRes.data?.data ?? [];
      } else {
        throw error;
      }
    }

    if (!templates.length) return creds;

    // --- 3. BULK UPDATE/INSERT FROM META DATA ---
    const bulkOps = templates
      .filter((t) => t.status === 'APPROVED' && t.name !== 'hello_world')
      .map((t) => {
        const headerComp = t.components?.find((c: any) => c.type === 'HEADER');
        const bodyComp = t.components?.find((c: any) => c.type === 'BODY');
        const bodyText = bodyComp?.text || '';

        return {
          updateOne: {
            filter: { companyId: companyObjectId, name: t.name }, // Match by name & company
            update: {
              $set: {
                templateId: t.id,
                whatsappStatus: t.status,
                headerText: headerComp?.text || t.name,
                bodyText: bodyText,
                isDefault: false, // API templates are live, not just default seeds
                // Example logic for trigger points
                ...(bodyText.toLowerCase().includes('verification')
                  ? { triggerPoint: TriggerPoint.OnLoginMobileApp }
                  : {}),
              },
              $setOnInsert: {
                companyId: companyObjectId,
                name: t.name,
              },
            },
            upsert: true,
          },
        };
      });

    if (bulkOps.length > 0) {
      await model.bulkWrite(bulkOps, { ordered: false });
    }

    return creds;
  } catch (error) {
    console.error('🚀 ~ syncWhatsappTemplates ~ error:', error);
  }
};

