import type { FreeProxyItem, FreeProxySyncResult, FreeProxyProvider } from "./types";
import { isPrivateHost } from "@/shared/network/outboundUrlGuard";

const DEFAULT_API_URL = "https://1proxy-api.aitradepulse.com/api/v1/proxies/advanced";
const DEFAULT_MAX = 500;
const DEFAULT_MIN_QUALITY = 50;
const DEFAULT_PAGE_SIZE = 100;
const MAX_CONSECUTIVE_FAILURES = 5;

type OneProxyApiProxy = {
  ip: string;
  port: number;
  protocol: string;
  country_code: string;
  latency_ms: number;
  anonymity: string;
  quality_score: number;
  last_validated: string;
};

type OneProxyApiResponse = {
  total: number;
  count: number;
  offset: number;
  proxies: OneProxyApiProxy[];
};

export class OneproxyProvider implements FreeProxyProvider {
  readonly id = "1proxy" as const;
  readonly name = "1proxy";

  private consecutiveFailures = 0;

  isEnabled(): boolean {
    return process.env.FREE_PROXY_1PROXY_ENABLED !== "false";
  }

  private getConfig() {
    return {
      apiUrl: process.env.FREE_PROXY_1PROXY_API_URL || DEFAULT_API_URL,
      maxProxies: parseInt(process.env.FREE_PROXY_1PROXY_MAX || "", 10) || DEFAULT_MAX,
      minQuality:
        parseInt(process.env.FREE_PROXY_1PROXY_MIN_QUALITY || "", 10) || DEFAULT_MIN_QUALITY,
    };
  }

  async sync(): Promise<FreeProxySyncResult> {
    if (!this.isEnabled()) {
      return { fetched: 0, added: 0, updated: 0, errors: ["1proxy provider disabled"] };
    }
    if (this.consecutiveFailures >= MAX_CONSECUTIVE_FAILURES) {
      return {
        fetched: 0,
        added: 0,
        updated: 0,
        errors: [`Circuit breaker open: ${this.consecutiveFailures} consecutive failures`],
      };
    }

    const { upsertFreeProxy } = await import("../db/freeProxies");
    const { apiUrl, maxProxies, minQuality } = this.getConfig();
    const errors: string[] = [];
    let added = 0;
    let updated = 0;
    let fetched = 0;
    let offset = 0;

    try {
      while (fetched < maxProxies) {
        const limit = Math.min(DEFAULT_PAGE_SIZE, maxProxies - fetched);
        const url = `${apiUrl}?offset=${offset}&limit=${limit}&min_quality_score=${minQuality}`;
        const res = await fetch(url, { signal: AbortSignal.timeout(15000) });

        if (!res.ok) {
          const text = await res.text().catch(() => "");
          errors.push(`HTTP ${res.status}: ${text.slice(0, 100)}`);
          this.consecutiveFailures++;
          break;
        }

        const json = (await res.json()) as OneProxyApiResponse;
        if (!Array.isArray(json.proxies) || json.proxies.length === 0) break;

        for (const p of json.proxies) {
          if (!p.ip || isPrivateHost(p.ip)) {
            errors.push(`1proxy: skipped private/loopback host ${p.ip}`);
            continue;
          }
          const item: FreeProxyItem = {
            source: "1proxy",
            host: p.ip,
            port: p.port,
            type: (p.protocol?.toLowerCase() as FreeProxyItem["type"]) || "http",
            countryCode: p.country_code || null,
            qualityScore: p.quality_score ?? null,
            latencyMs: p.latency_ms ?? null,
            anonymity: p.anonymity || null,
            lastValidated: p.last_validated || new Date().toISOString(),
          };
          const result = await upsertFreeProxy(item);
          if (result.action === "created") added++;
          else updated++;
        }

        fetched += json.proxies.length;
        offset += json.proxies.length;
        if (json.proxies.length < limit) break;
      }
      this.consecutiveFailures = 0;
    } catch (err) {
      this.consecutiveFailures++;
      errors.push(err instanceof Error ? err.message : String(err));
    }

    return { fetched, added, updated, errors };
  }

  async list(filters: {
    protocol?: string;
    country?: string;
    minQuality?: number;
    limit?: number;
  }): Promise<FreeProxyItem[]> {
    const { listFreeProxiesBySource } = await import("../db/freeProxies");
    return listFreeProxiesBySource("1proxy", filters);
  }
}
