import type { Customer } from '../billing/middleware.js';
import type { OAuthCredentials } from '../multitenancy/credential-store.js';
import { createToolAudit } from '../multitenancy/audit-log.js';

const INSTAGRAM_API_BASE = 'https://graph.facebook.com/v18.0';

interface InstagramCredentials extends OAuthCredentials {
  businessAccountId: string;
}

function getEnvToken(account: string): string {
  const envKey = `INSTAGRAM_${account.toUpperCase()}_ACCESS_TOKEN`;
  return process.env[envKey] ?? '';
}

function getEnvBusinessId(account: string): string {
  const envKey = `INSTAGRAM_${account.toUpperCase()}_BUSINESS_ACCOUNT_ID`;
  return process.env[envKey] ?? '';
}

async function resolveCreds(
  args: { account?: string },
  customer?: Customer
): Promise<{ accessToken: string; businessAccountId: string }> {
  if (customer) {
    const creds = await customer.getCredential<InstagramCredentials>('instagram');
    if (!creds) throw new Error('Instagram not connected for this account');
    return { accessToken: creds.accessToken, businessAccountId: creds.businessAccountId };
  }
  const account = args.account ?? 'default';
  const accessToken = getEnvToken(account);
  const businessAccountId = getEnvBusinessId(account);
  if (!accessToken || !businessAccountId) {
    throw new Error('Missing Instagram credentials. Set INSTAGRAM_{ACCOUNT}_ACCESS_TOKEN and INSTAGRAM_{ACCOUNT}_BUSINESS_ACCOUNT_ID');
  }
  return { accessToken, businessAccountId };
}

async function instagramRequest(
  endpoint: string,
  accessToken: string,
  method: 'GET' | 'POST' = 'GET',
  params?: Record<string, unknown>
) {
  const url = new URL(`${INSTAGRAM_API_BASE}${endpoint}`);
  url.searchParams.set('access_token', accessToken);

  const res = await fetch(url.toString(), {
    method,
    headers: params ? { 'Content-Type': 'application/json' } : undefined,
    body: params ? JSON.stringify(params) : undefined,
    signal: AbortSignal.timeout(15000),
  });

  if (!res.ok) {
    const error = await res.text();
    throw new Error(`Instagram API error (${res.status}): ${error}`);
  }

  return res.json();
}

export async function getProfile(
  args: { account?: string },
  customer?: Customer
): Promise<{
  id: string;
  username: string;
  name: string;
  followers_count: number;
  follows_count: number;
  media_count: number;
}> {
  const { accessToken, businessAccountId } = await resolveCreds(args, customer);

  const data = await instagramRequest(
    `/${businessAccountId}?fields=username,name,followers_count,follows_count,media_count`,
    accessToken
  );

  return {
    id: data.id,
    username: data.username ?? '',
    name: data.name ?? '',
    followers_count: data.followers_count ?? 0,
    follows_count: data.follows_count ?? 0,
    media_count: data.media_count ?? 0,
  };
}

export async function getMedia(
  args: { limit?: number; account?: string },
  customer?: Customer
): Promise<Array<{
  id: string;
  caption?: string;
  media_type: string;
  media_url?: string;
  permalink?: string;
  timestamp?: string;
}>> {
  const { accessToken, businessAccountId } = await resolveCreds(args, customer);
  const limit = args.limit ?? 10;
  const data = await instagramRequest(
    `/${businessAccountId}/media?fields=id,caption,media_type,media_url,permalink,timestamp&limit=${limit}`,
    accessToken
  );

  return (data.data ?? []).map((item: { id: string; caption?: string; media_type: string; media_url?: string; permalink?: string; timestamp?: string }) => ({
    id: item.id,
    caption: item.caption,
    media_type: item.media_type,
    media_url: item.media_url,
    permalink: item.permalink,
    timestamp: item.timestamp,
  }));
}

export async function createPost(
  args: { image_url: string; caption?: string; account?: string },
  customer?: Customer
): Promise<{ success: boolean; media_id: string }> {
  const audit = customer ? createToolAudit(customer.id, 'instagram:createPost') : null;
  const auditArgs = { image_url: args.image_url };
  const { accessToken, businessAccountId } = await resolveCreds(args, customer);

  try {
    const container = await instagramRequest(
      `/${businessAccountId}/media`,
      accessToken,
      'POST',
      { image_url: args.image_url, caption: args.caption, media_type: 'REELS' }
    );

    const creationId = container.id;
    if (!creationId) throw new Error('Failed to create Instagram media container');

    const publish = await instagramRequest(
      `/${businessAccountId}/media_publish`,
      accessToken,
      'POST',
      { creation_id: creationId }
    );

    const result = { success: true, media_id: publish.id };
    if (audit) await audit.success(auditArgs);
    return result;
  } catch (err) {
    if (audit) await audit.error(auditArgs, String(err));
    throw err;
  }
}
