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

const FACEBOOK_API_BASE = 'https://graph.facebook.com/v19.0';

interface FacebookCredentials extends OAuthCredentials {
  pageId: string;
}

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

function getEnvPageId(account: string): string {
  return process.env[`FACEBOOK_${account.toUpperCase()}_PAGE_ID`] ?? '';
}

async function resolveCreds(
  args: { account?: string },
  customer?: Customer
): Promise<{ accessToken: string; pageId: string }> {
  if (customer) {
    const creds = await customer.getCredential<FacebookCredentials>('facebook');
    if (!creds) throw new Error('Facebook not connected for this account');
    return { accessToken: creds.accessToken, pageId: creds.pageId };
  }
  const account = args.account ?? 'default';
  const accessToken = getEnvToken(account);
  const pageId = getEnvPageId(account);
  if (!accessToken || !pageId) {
    throw new Error('Missing Facebook credentials. Set FACEBOOK_{ACCOUNT}_ACCESS_TOKEN and FACEBOOK_{ACCOUNT}_PAGE_ID');
  }
  return { accessToken, pageId };
}

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

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

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

  return res.json();
}

export async function getPage(
  args: { account?: string },
  customer?: Customer
): Promise<{
  id: string;
  name: string;
  category: string;
  about?: string;
  fan_count: number;
  followers_count: number;
  link?: string;
}> {
  const { accessToken, pageId } = await resolveCreds(args, customer);
  const data = await fbRequest(
    `/${pageId}?fields=id,name,category,about,fan_count,followers_count,link`,
    accessToken
  );
  return {
    id: data.id ?? '',
    name: data.name ?? '',
    category: data.category ?? '',
    about: data.about,
    fan_count: data.fan_count ?? 0,
    followers_count: data.followers_count ?? 0,
    link: data.link,
  };
}

export async function getPosts(
  args: { limit?: number; account?: string },
  customer?: Customer
): Promise<Array<{
  id: string;
  message?: string;
  story?: string;
  created_time: string;
  permalink_url?: string;
}>> {
  const { accessToken, pageId } = await resolveCreds(args, customer);
  const limit = args.limit ?? 10;
  const data = await fbRequest(
    `/${pageId}/published_posts?fields=id,message,story,created_time,permalink_url&limit=${limit}`,
    accessToken
  );
  return (data.data ?? []).map((p: Record<string, unknown>) => ({
    id: String(p.id ?? ''),
    message: p.message as string | undefined,
    story: p.story as string | undefined,
    created_time: String(p.created_time ?? ''),
    permalink_url: p.permalink_url as string | undefined,
  }));
}

export async function createPost(
  args: { message: string; link?: string; account?: string },
  customer?: Customer
): Promise<{ success: boolean; post_id: string }> {
  const audit = customer ? createToolAudit(customer.id, 'facebook:createPost') : null;
  const auditArgs = { message: args.message.slice(0, 80) };
  const { accessToken, pageId } = await resolveCreds(args, customer);

  try {
    const body: Record<string, unknown> = { message: args.message };
    if (args.link) body.link = args.link;

    const data = await fbRequest(`/${pageId}/feed`, accessToken, 'POST', body);
    const result = { success: true, post_id: String(data.id ?? '') };
    if (audit) await audit.success(auditArgs);
    return result;
  } catch (err) {
    if (audit) await audit.error(auditArgs, String(err));
    throw err;
  }
}

export async function createPhotoPost(
  args: { image_url: string; caption?: string; account?: string },
  customer?: Customer
): Promise<{ success: boolean; post_id: string; photo_id: string }> {
  const audit = customer ? createToolAudit(customer.id, 'facebook:createPhotoPost') : null;
  const auditArgs = { image_url: args.image_url };
  const { accessToken, pageId } = await resolveCreds(args, customer);

  try {
    const data = await fbRequest(`/${pageId}/photos`, accessToken, 'POST', {
      url: args.image_url,
      caption: args.caption ?? '',
    });
    const result = {
      success: true,
      post_id: String(data.post_id ?? data.id ?? ''),
      photo_id: String(data.id ?? ''),
    };
    if (audit) await audit.success(auditArgs);
    return result;
  } catch (err) {
    if (audit) await audit.error(auditArgs, String(err));
    throw err;
  }
}

export async function createVideoPost(
  args: { video_url: string; description?: string; account?: string },
  customer?: Customer
): Promise<{ success: boolean; video_id: string; post_id: string }> {
  const audit = customer ? createToolAudit(customer.id, 'facebook:createVideoPost') : null;
  const auditArgs = { video_url: args.video_url };
  const { accessToken, pageId } = await resolveCreds(args, customer);

  try {
    const body: Record<string, unknown> = {
      file_url: args.video_url,
    };
    if (args.description) body.description = args.description;

    const data = await fbRequest(`/${pageId}/videos`, accessToken, 'POST', body);
    const result = {
      success: true,
      video_id: String(data.id ?? ''),
      post_id: String(data.post_id ?? data.id ?? ''),
    };
    if (audit) await audit.success(auditArgs);
    return result;
  } catch (err) {
    if (audit) await audit.error(auditArgs, String(err));
    throw err;
  }
}
