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

const TWITTER_API_BASE = 'https://api.twitter.com/2';

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

async function resolveToken(args: { account?: string }, customer?: Customer): Promise<string> {
  if (customer) {
    const creds = await customer.getCredential<OAuthCredentials>('twitter');
    if (!creds) throw new Error('Twitter not connected for this account');
    return creds.accessToken;
  }
  const token = getEnvToken(args.account ?? 'default');
  if (!token) throw new Error('Missing Twitter credentials. Set TWITTER_{ACCOUNT}_BEARER_TOKEN');
  return token;
}

async function twitterRequest(
  endpoint: string,
  bearerToken: string,
  params?: Record<string, string>
) {
  const url = new URL(`${TWITTER_API_BASE}${endpoint}`);
  if (params) {
    Object.entries(params).forEach(([key, value]) => {
      if (value) url.searchParams.append(key, value);
    });
  }

  const res = await fetch(url.toString(), {
    headers: { 'Authorization': `Bearer ${bearerToken}` },
    signal: AbortSignal.timeout(15000),
  });

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

  return res.json();
}

export async function searchTweets(
  args: { query: string; max_results?: number; account?: string },
  customer?: Customer
): Promise<Array<{ id: string; text: string; author_id?: string; created_at?: string }>> {
  const bearerToken = await resolveToken(args, customer);

  const data = await twitterRequest('/tweets/search/recent', bearerToken, {
    query: args.query,
    max_results: String(Math.min(args.max_results ?? 10, 100)),
    'tweet.fields': 'created_at,author_id',
  });

  return (data.data ?? []) as Array<{ id: string; text: string; author_id?: string; created_at?: string }>;
}

export async function getUserProfile(
  args: { username: string; account?: string },
  customer?: Customer
): Promise<{
  id: string;
  name: string;
  username: string;
  description?: string;
  followers_count?: number;
  following_count?: number;
  tweet_count?: number;
}> {
  const bearerToken = await resolveToken(args, customer);

  const data = await twitterRequest(`/users/by/username/${args.username}`, bearerToken, {
    'user.fields': 'description,public_metrics',
  });

  const user = data.data as { id: string; name: string; username: string; description?: string; public_metrics?: { followers_count?: number; following_count?: number; tweet_count?: number } };

  return {
    id: user.id,
    name: user.name,
    username: user.username,
    description: user.description,
    followers_count: user.public_metrics?.followers_count,
    following_count: user.public_metrics?.following_count,
    tweet_count: user.public_metrics?.tweet_count,
  };
}

export async function getUserTweets(
  args: { username: string; max_results?: number; account?: string },
  customer?: Customer
): Promise<Array<{ id: string; text: string; created_at?: string }>> {
  const bearerToken = await resolveToken(args, customer);

  const userData = await twitterRequest(`/users/by/username/${args.username}`, bearerToken);
  const userId = userData.data?.id;
  if (!userId) throw new Error(`User @${args.username} not found`);

  const data = await twitterRequest(`/users/${userId}/tweets`, bearerToken, {
    max_results: String(Math.min(args.max_results ?? 10, 100)),
    'tweet.fields': 'created_at',
  });

  return (data.data ?? []) as Array<{ id: string; text: string; created_at?: string }>;
}

export async function createTweet(
  args: { text: string; account?: string },
  _customer?: Customer
): Promise<{ message: string }> {
  throw new Error(
    'Twitter/X posting requires a paid API tier. ' +
    'The free tier is read-only (500 tweets/month). ' +
    'Upgrade to Basic ($100/month) or Pro ($5,000/month) at https://developer.twitter.com/en/portal/products'
  );
}
