/**
 * DataForSEO Backlinks Client
 * ───────────────────────────
 * Calls DataForSEO Backlinks API v3 endpoints. Falls back to empty
 * results if credentials not configured.
 */

import { prisma } from "@/lib/prisma";

const DFSE_BASE = "https://api.dataforseo.com/v3/backlinks";

export function hasDataForSEO(): boolean {
  return !!(process.env.DATAFORSEO_LOGIN && process.env.DATAFORSEO_PASSWORD);
}

/** Strip protocol, www, trailing slashes — DataForSEO wants bare domain */
export function cleanDomain(url: string): string {
  try {
    const u = new URL(url.startsWith("http") ? url : `https://${url}`);
    return u.hostname.replace(/^www\./, "");
  } catch {
    return url.replace(/^https?:\/\//, "").replace(/^www\./, "").replace(/\/+$/, "");
  }
}

function authHeader(): string {
  return "Basic " + Buffer.from(`${process.env.DATAFORSEO_LOGIN}:${process.env.DATAFORSEO_PASSWORD}`).toString("base64");
}

async function dfsePost<T>(path: string, body: unknown[]): Promise<T | null> {
  const url = `${DFSE_BASE}${path}`;
  const bodyStr = JSON.stringify(body);
  console.log(`[backlinks:dfse] POST ${url}`);
  console.log(`[backlinks:dfse] Body: ${bodyStr.slice(0, 500)}`);

  try {
    const res = await fetch(url, {
      method: "POST",
      headers: { Authorization: authHeader(), "Content-Type": "application/json" },
      body: bodyStr,
      signal: AbortSignal.timeout(30000),
    });
    console.log(`[backlinks:dfse] HTTP status: ${res.status}`);

    const rawText = await res.text();
    console.log(`[backlinks:dfse] Response (first 1000): ${rawText.slice(0, 1000)}`);

    if (!res.ok) return null;

    const data = JSON.parse(rawText);

    // Log task-level status (DataForSEO errors come here, not as HTTP errors)
    const task = data.tasks?.[0];
    if (task) {
      console.log(`[backlinks:dfse] Task status: ${task.status_code} — ${task.status_message}`);
      if (task.status_code !== 20000) {
        console.log(`[backlinks:dfse] Task error: ${task.status_code} ${task.status_message}`);
        return null;
      }
    }

    // Log cost
    const cost = data.cost ?? 0;
    if (cost > 0) {
      prisma.aiUsageLog.create({ data: { provider: "dataforseo", model: `backlinks${path}`, feature: "backlinks", inputTokens: 0, outputTokens: 0, estimatedCost: cost } }).catch(() => {});
    }

    const result = task?.result?.[0] ?? null;
    console.log(`[backlinks:dfse] Result items: ${result?.items?.length ?? result?.total_count ?? "N/A"}`);
    return result;
  } catch (err) {
    console.log(`[backlinks:dfse] Fetch error:`, err instanceof Error ? err.message : err);
    return null;
  }
}

export interface DfseLinkItem {
  url_from: string; domain_from: string; url_to: string; anchor: string | null;
  type: string; domain_from_rank: number; first_seen: string | null; last_seen: string | null;
  is_new: boolean; is_lost: boolean; tld_from: string | null; domain_from_country: string | null;
}

export interface DfseSummary {
  backlinks: number; referring_domains: number; referring_ips: number;
  broken_backlinks: number; referring_domains_nofollow: number;
}

export interface DfseReferringDomain {
  domain: string; rank: number; backlinks: number; first_seen: string | null; last_seen: string | null;
}

export async function fetchSummary(domain: string): Promise<DfseSummary | null> {
  const d = cleanDomain(domain);
  return dfsePost<DfseSummary>("/summary/live", [{ target: d, include_subdomains: true }]);
}

export async function fetchBacklinks(domain: string, limit = 500): Promise<DfseLinkItem[]> {
  const d = cleanDomain(domain);
  const result = await dfsePost<{ items?: DfseLinkItem[] }>("/backlinks/live", [
    { target: d, limit, order_by: ["rank,desc"], include_subdomains: true },
  ]);
  return result?.items ?? [];
}

export async function fetchReferringDomains(domain: string, limit = 200): Promise<DfseReferringDomain[]> {
  const d = cleanDomain(domain);
  const result = await dfsePost<{ items?: DfseReferringDomain[] }>("/referring_domains/live", [
    { target: d, limit, order_by: ["rank,desc"], include_subdomains: true },
  ]);
  return result?.items ?? [];
}

export async function fetchHistory(domain: string, daysBack = 90): Promise<Array<{ date: string; new_backlinks: number; lost_backlinks: number }>> {
  const d = cleanDomain(domain);
  const dateFrom = new Date(Date.now() - daysBack * 86400000).toISOString().split("T")[0];
  const dateTo = new Date().toISOString().split("T")[0];
  const result = await dfsePost<{ items?: Array<{ date: string; new_backlinks: number; lost_backlinks: number }> }>("/history/live", [
    { target: d, date_from: dateFrom, date_to: dateTo },
  ]);
  return result?.items ?? [];
}

export async function fetchCompetitorGaps(brandDomain: string, competitorDomain: string): Promise<Array<{ domain: string; backlinks: number; rank: number }>> {
  const bd = cleanDomain(brandDomain);
  const cd = cleanDomain(competitorDomain);
  const result = await dfsePost<{ items?: Array<{ domain: string; backlinks: number; rank: number }> }>("/domain_intersection/live", [
    { targets: { 1: bd, 2: cd }, intersections: { 2: "all" }, exclude_intersections: { 1: "all" }, limit: 100, order_by: ["2_rank,desc"] },
  ]);
  return result?.items ?? [];
}

/** Map DataForSEO link type to our model */
export function mapLinkType(type: string): string {
  switch (type) { case "follow": return "dofollow"; case "nofollow": return "nofollow"; case "ugc": return "ugc"; case "sponsored": return "sponsored"; default: return "dofollow"; }
}
