import client from "./client";

// ── Types ───────────────────────────────────────────────────────────

export interface CampaignTest {
  id: string;
  test_id: string;
  order_index: number;
  depends_on: string | null;
  phase: string | null;
  test_name: string | null;
  test_state: string | null;
  test_result: string | null;
  technique_mitre_id: string | null;
  technique_name: string | null;
  platform: string | null;
}

export interface CampaignProgress {
  total: number;
  by_state: Record<string, number>;
  completion_pct: number;
}

export interface Campaign {
  id: string;
  name: string;
  description: string | null;
  type: string;
  status: string;
  threat_actor_id: string | null;
  threat_actor_name: string | null;
  created_by: string | null;
  scheduled_at: string | null;
  completed_at: string | null;
  target_platform: string | null;
  tags: string[];
  created_at: string | null;
  is_recurring: boolean;
  recurrence_pattern: string | null;
  next_run_at: string | null;
  last_run_at: string | null;
  parent_campaign_id: string | null;
  tests: CampaignTest[];
  progress: CampaignProgress;
}

export interface CampaignSummary {
  id: string;
  name: string;
  description: string | null;
  type: string;
  status: string;
  threat_actor_id: string | null;
  threat_actor_name: string | null;
  target_platform: string | null;
  tags: string[];
  created_at: string | null;
  test_count: number;
  completion_pct: number;
}

export interface CampaignCreatePayload {
  name: string;
  description?: string;
  type?: string;
  threat_actor_id?: string;
  target_platform?: string;
  tags?: string[];
  scheduled_at?: string;
}

export interface AddTestPayload {
  test_id: string;
  order_index?: number;
  depends_on?: string;
  phase?: string;
}

// ── API Functions ───────────────────────────────────────────────────

/** List campaigns with optional filters. */
export async function listCampaigns(params?: {
  type?: string;
  status?: string;
  threat_actor_id?: string;
  search?: string;
  offset?: number;
  limit?: number;
}): Promise<{ total: number; items: CampaignSummary[] }> {
  const { data } = await client.get("/campaigns", { params });
  return data;
}

/** Get a campaign detail with tests and progress. */
export async function getCampaign(campaignId: string): Promise<Campaign> {
  const { data } = await client.get<Campaign>(`/campaigns/${campaignId}`);
  return data;
}

/** Create a new campaign. */
export async function createCampaign(payload: CampaignCreatePayload): Promise<Campaign> {
  const { data } = await client.post<Campaign>("/campaigns", payload);
  return data;
}

/** Update a campaign. */
export async function updateCampaign(
  campaignId: string,
  payload: Partial<CampaignCreatePayload>,
): Promise<Campaign> {
  const { data } = await client.patch<Campaign>(`/campaigns/${campaignId}`, payload);
  return data;
}

/** Add a test to a campaign. */
export async function addTestToCampaign(
  campaignId: string,
  payload: AddTestPayload,
): Promise<CampaignTest> {
  const { data } = await client.post<CampaignTest>(`/campaigns/${campaignId}/tests`, payload);
  return data;
}

/** Remove a test from a campaign. */
export async function removeTestFromCampaign(
  campaignId: string,
  campaignTestId: string,
): Promise<void> {
  await client.delete(`/campaigns/${campaignId}/tests/${campaignTestId}`);
}

/** Activate a campaign. */
export async function activateCampaign(campaignId: string): Promise<Campaign> {
  const { data } = await client.post<Campaign>(`/campaigns/${campaignId}/activate`);
  return data;
}

/** Mark a campaign as completed. */
export async function completeCampaign(campaignId: string): Promise<Campaign> {
  const { data } = await client.post<Campaign>(`/campaigns/${campaignId}/complete`);
  return data;
}

/** Get campaign progress. */
export async function getCampaignProgress(campaignId: string): Promise<CampaignProgress & {
  campaign_id: string;
  campaign_name: string;
}> {
  const { data } = await client.get(`/campaigns/${campaignId}/progress`);
  return data;
}

/** Generate a campaign from a threat actor. */
export async function generateCampaignFromThreatActor(actorId: string): Promise<Campaign> {
  const { data } = await client.post<Campaign>(`/campaigns/from-threat-actor/${actorId}`);
  return data;
}

// ── Scheduling ─────────────────────────────────────────────────────

export interface SchedulePayload {
  is_recurring: boolean;
  recurrence_pattern?: string;
  next_run_at?: string;
}

export interface CampaignHistoryEntry {
  id: string;
  name: string;
  status: string;
  test_count: number;
  completion_pct: number;
  created_at: string | null;
  completed_at: string | null;
}

/** Configure recurrence scheduling for a campaign. */
export async function scheduleCampaign(
  campaignId: string,
  payload: SchedulePayload,
): Promise<Campaign> {
  const { data } = await client.patch<Campaign>(`/campaigns/${campaignId}/schedule`, payload);
  return data;
}

/** Delete a campaign. Only draft campaigns can be deleted (admins can delete any). */
export async function deleteCampaign(
  campaignId: string,
  deleteTests: boolean = false,
): Promise<void> {
  await client.delete(`/campaigns/${campaignId}`, {
    params: { delete_tests: deleteTests },
  });
}

// ── Timing summary ─────────────────────────────────────────────────

export interface CampaignTimingBreakdown {
  test_id: string;
  test_name: string;
  state: string | null;
  red_execution_secs: number;
  blue_queue_secs: number;
  blue_evaluation_secs: number;
  total_secs: number;
  has_timing: boolean;
}

export interface CampaignTimingSummary {
  campaign_id: string;
  campaign_name: string;
  tests_total: number;
  tests_with_timing: number;
  red_execution_secs: number;
  blue_queue_secs: number;
  blue_evaluation_secs: number;
  total_secs: number;
  breakdown: CampaignTimingBreakdown[];
}

/** Get aggregated Red/Blue timing metrics for a campaign. */
export async function getCampaignTiming(campaignId: string): Promise<CampaignTimingSummary> {
  const { data } = await client.get<CampaignTimingSummary>(`/campaigns/${campaignId}/timing-summary`);
  return data;
}

/** Get execution history (child campaigns) for a recurring campaign. */
export async function getCampaignHistory(campaignId: string): Promise<{
  campaign_id: string;
  campaign_name: string;
  items: CampaignHistoryEntry[];
}> {
  const { data } = await client.get(`/campaigns/${campaignId}/history`);
  return data;
}
