/**
 * LangGraph Client
 * TypeScript client for communicating with the LangGraph SEO Service
 */

// LangGraph service URL
const LANGGRAPH_URL = process.env.LANGGRAPH_URL || 'http://127.0.0.1:8001';

// Campaign templates
export type CampaignTemplate =
  | 'zero_click_authority'  // Focus on SERP features and AI Overviews
  | 'link_building'         // Safe link acquisition with human approval
  | 'full_campaign';        // Complete SEO workflow

// Campaign status
export type CampaignStatus =
  | 'started'
  | 'running'
  | 'awaiting_approval'
  | 'completed'
  | 'failed';

// Link opportunity for approval
export interface LinkOpportunity {
  id: string;
  target_url: string;
  source_domain: string;
  domain_authority: number;
  monthly_traffic?: number;
  relevance_score: number;
  opportunity_type: string;
  status: string;
  pitch_draft: string;
  pitch_approved?: string;
  contact_email?: string;
  contact_name?: string;
  discovered_at: string;
  notes?: string;
}

// Campaign state response
export interface CampaignState {
  campaign_id: string;
  site_id: string;
  campaign_type: string;
  current_phase: string;
  status: CampaignStatus;
  pending_approvals: LinkOpportunity[];
  requires_human_review: boolean;
  metrics: {
    pages_generated: number;
    pages_optimized: number;
    snippets_captured: number;
    links_approved: number;
    links_acquired: number;
    errors: number;
    warnings: number;
  };
  started_at: string;
  updated_at: string;
}

// Start campaign response
export interface StartCampaignResponse {
  campaign_id: string;
  site_id: string;
  status: string;
  current_phase: string;
  message: string;
}

// Resume campaign response
export interface ResumeCampaignResponse {
  campaign_id: string;
  status: string;
  current_phase: string;
  message: string;
}

// Approval response
export interface ApprovalResponse {
  opportunity_id: string;
  status: string;
  message: string;
}

// Campaign list item
export interface CampaignListItem {
  campaign_id: string;
  site_id: string;
  campaign_type: string;
  current_phase: string;
  status: CampaignStatus;
  pending_approvals: number;
  started_at: string;
  updated_at: string;
}

/**
 * Check if LangGraph service is healthy
 */
export async function checkHealth(): Promise<boolean> {
  try {
    const res = await fetch(`${LANGGRAPH_URL}/health`);
    const data = await res.json();
    return data.status === 'healthy';
  } catch {
    return false;
  }
}

/**
 * Start a new SEO campaign
 */
export async function startCampaign(
  siteId: string,
  template: CampaignTemplate = 'zero_click_authority',
  config?: Record<string, unknown>
): Promise<StartCampaignResponse> {
  const res = await fetch(`${LANGGRAPH_URL}/api/campaigns/start`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      site_id: siteId,
      template,
      config,
    }),
  });

  if (!res.ok) {
    throw new Error(`Failed to start campaign: ${res.statusText}`);
  }

  return res.json();
}

/**
 * Get current campaign state
 */
export async function getCampaignState(campaignId: string): Promise<CampaignState> {
  const res = await fetch(`${LANGGRAPH_URL}/api/campaigns/${campaignId}/state`);

  if (!res.ok) {
    throw new Error(`Failed to get campaign state: ${res.statusText}`);
  }

  return res.json();
}

/**
 * Resume a paused campaign after human approval
 */
export async function resumeCampaign(campaignId: string): Promise<ResumeCampaignResponse> {
  const res = await fetch(`${LANGGRAPH_URL}/api/campaigns/${campaignId}/resume`, {
    method: 'POST',
  });

  if (!res.ok) {
    throw new Error(`Failed to resume campaign: ${res.statusText}`);
  }

  return res.json();
}

/**
 * List all campaigns
 */
export async function listCampaigns(
  status?: CampaignStatus,
  siteId?: string
): Promise<{ campaigns: CampaignListItem[] }> {
  const params = new URLSearchParams();
  if (status) params.set('status', status);
  if (siteId) params.set('site_id', siteId);

  const res = await fetch(`${LANGGRAPH_URL}/api/campaigns?${params}`);

  if (!res.ok) {
    throw new Error(`Failed to list campaigns: ${res.statusText}`);
  }

  return res.json();
}

/**
 * Approve a link opportunity
 */
export async function approveLink(
  opportunityId: string,
  editedPitch?: string
): Promise<ApprovalResponse> {
  const res = await fetch(`${LANGGRAPH_URL}/api/approvals/${opportunityId}/approve`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ edited_pitch: editedPitch }),
  });

  if (!res.ok) {
    throw new Error(`Failed to approve link: ${res.statusText}`);
  }

  return res.json();
}

/**
 * Reject a link opportunity
 */
export async function rejectLink(
  opportunityId: string,
  reason: string
): Promise<ApprovalResponse> {
  const res = await fetch(`${LANGGRAPH_URL}/api/approvals/${opportunityId}/reject`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ reason }),
  });

  if (!res.ok) {
    throw new Error(`Failed to reject link: ${res.statusText}`);
  }

  return res.json();
}

/**
 * Get all pending approvals across campaigns
 */
export async function getPendingApprovals(): Promise<{
  pending_approvals: Array<LinkOpportunity & { campaign_id: string; site_id: string }>;
  total: number;
}> {
  const res = await fetch(`${LANGGRAPH_URL}/api/approvals/pending`);

  if (!res.ok) {
    throw new Error(`Failed to get pending approvals: ${res.statusText}`);
  }

  return res.json();
}

/**
 * Poll campaign until completion or approval needed
 */
export async function pollCampaign(
  campaignId: string,
  options: {
    intervalMs?: number;
    maxAttempts?: number;
    onUpdate?: (state: CampaignState) => void;
  } = {}
): Promise<CampaignState> {
  const {
    intervalMs = 5000,
    maxAttempts = 60,  // 5 minutes with 5s interval
    onUpdate,
  } = options;

  let attempts = 0;

  while (attempts < maxAttempts) {
    const state = await getCampaignState(campaignId);

    if (onUpdate) {
      onUpdate(state);
    }

    // Stop polling if completed, failed, or awaiting approval
    if (
      state.status === 'completed' ||
      state.status === 'failed' ||
      state.status === 'awaiting_approval'
    ) {
      return state;
    }

    // Wait before next poll
    await new Promise(resolve => setTimeout(resolve, intervalMs));
    attempts++;
  }

  // Return final state after max attempts
  return getCampaignState(campaignId);
}

// Export default client object for convenience
export const langGraphClient = {
  checkHealth,
  startCampaign,
  getCampaignState,
  resumeCampaign,
  listCampaigns,
  approveLink,
  rejectLink,
  getPendingApprovals,
  pollCampaign,
};

export default langGraphClient;
