import { apiJson } from "@/lib/services/api-client";
import type {
  KycClientConnectorPrivateRecord,
  KycScopedExportPackage,
} from "@/lib/services/one-kyc-client-zk-service";

export type OneKycWorkflowStatus =
  | "needs_client_connector"
  | "needs_scope"
  | "needs_documents"
  | "drafting"
  | "waiting_on_user"
  | "waiting_on_counterparty"
  | "completed"
  | "blocked";

export interface OneKycScopeCandidate {
  scope: string;
  domain: string;
  label?: string;
  description?: string;
  reason?: string;
  recommended?: boolean;
  sensitivity?: string;
  path?: string | null;
  wildcard?: boolean;
  source_kind?: string | null;
  visibility_posture?: "private" | "consent_required" | "default_available";
  default_projection_ready?: boolean;
  default_projection_updated_at?: string | null;
}

export interface OneKycConsentRequest {
  request_id: string;
  scope: string;
  status?: string;
  request_url?: string | null;
}

export interface OneKycWorkflow {
  workflow_id: string;
  user_id: string | null;
  status: OneKycWorkflowStatus;
  gmail_thread_id?: string | null;
  gmail_message_id?: string | null;
  sender_email?: string | null;
  sender_name?: string | null;
  participant_emails: string[];
  subject?: string | null;
  snippet?: string | null;
  counterparty_label?: string | null;
  required_fields: string[];
  requested_scope?: string | null;
  requested_scopes?: string[] | null;
  selected_scopes?: string[] | null;
  candidate_scopes?: OneKycScopeCandidate[] | null;
  consent_request_id?: string | null;
  consent_requests?: OneKycConsentRequest[] | null;
  consent_bundle_id?: string | null;
  consent_request_url?: string | null;
  workflow_url?: string | null;
  draft_subject?: string | null;
  draft_body?: string | null;
  draft_status?: "not_ready" | "ready" | "sent" | "rejected" | null;
  consent_export?: Record<string, unknown> | null;
  consent_exports?: Array<Record<string, unknown>> | null;
  send_status?: "not_started" | "sending" | "sent" | "failed" | null;
  sent_message_id?: string | null;
  sent_thread_id?: string | null;
  thread_match_status?: "matched" | "mismatched" | "unknown" | "not_applicable" | null;
  sent_at?: string | null;
  pkm_writeback_status?: "not_started" | "pending" | "succeeded" | "failed" | null;
  pkm_writeback_artifact_hash?: string | null;
  pkm_writeback_attempt_count?: number | null;
  pkm_writeback_last_error?: string | null;
  pkm_writeback_completed_at?: string | null;
  last_error_code?: string | null;
  last_error_message?: string | null;
  metadata?: Record<string, unknown>;
  created_at?: string | null;
  updated_at?: string | null;
}

export interface OneKycWorkflowListResponse {
  workflows: OneKycWorkflow[];
  limit?: number;
  has_more?: boolean;
  next_cursor?: string | null;
}

export interface OneKycRecentMailboxSyncResponse {
  accepted: boolean;
  scanned_count: number;
  processed_count: number;
  matched_count: number;
  workflows: OneKycWorkflow[];
}

export interface OneKycClientConnectorResponse {
  configured: boolean;
  connector: {
    connector_key_id: string;
    connector_public_key: string;
    connector_wrapping_alg: string;
    public_key_fingerprint?: string | null;
    status?: string | null;
  } | null;
}

export interface KycScopedExportPackageWithRequest extends KycScopedExportPackage {
  request_id?: string;
  scope?: string;
}

export interface OneKycWorkflowConsentExportsResponse {
  status: string;
  exports: KycScopedExportPackageWithRequest[];
}

type AuthInput = {
  userId: string;
  vaultOwnerToken: string;
};

function authHeaders(vaultOwnerToken: string): HeadersInit {
  return {
    Authorization: `Bearer ${vaultOwnerToken}`,
    "Content-Type": "application/json",
  };
}

export class OneKycService {
  static syncRecentEmails({
    userId,
    vaultOwnerToken,
    maxResults = 12,
  }: AuthInput & {
    maxResults?: number;
  }): Promise<OneKycRecentMailboxSyncResponse> {
    return apiJson<OneKycRecentMailboxSyncResponse>("/api/one/email/sync/recent", {
      method: "POST",
      headers: authHeaders(vaultOwnerToken),
      body: JSON.stringify({
        user_id: userId,
        max_results: maxResults,
      }),
    });
  }

  static listWorkflows({
    userId,
    vaultOwnerToken,
    limit,
    cursor,
    status,
  }: AuthInput & {
    limit?: number;
    cursor?: string | null;
    status?: OneKycWorkflowStatus | null;
  }): Promise<OneKycWorkflowListResponse> {
    const query = new URLSearchParams({ user_id: userId });
    if (limit) query.set("limit", String(limit));
    if (cursor) query.set("cursor", cursor);
    if (status) query.set("status", status);
    return apiJson<OneKycWorkflowListResponse>(`/api/one/kyc/workflows?${query.toString()}`, {
      headers: authHeaders(vaultOwnerToken),
    });
  }

  static getWorkflow({
    userId,
    vaultOwnerToken,
    workflowId,
  }: AuthInput & { workflowId: string }): Promise<OneKycWorkflow> {
    const query = new URLSearchParams({ user_id: userId });
    return apiJson<OneKycWorkflow>(
      `/api/one/kyc/workflows/${encodeURIComponent(workflowId)}?${query.toString()}`,
      {
        headers: authHeaders(vaultOwnerToken),
      }
    );
  }

  static archiveWorkflow({
    userId,
    vaultOwnerToken,
    workflowId,
  }: AuthInput & { workflowId: string }): Promise<OneKycWorkflow> {
    const query = new URLSearchParams({ user_id: userId });
    return apiJson<OneKycWorkflow>(
      `/api/one/kyc/workflows/${encodeURIComponent(workflowId)}?${query.toString()}`,
      {
        method: "DELETE",
        headers: authHeaders(vaultOwnerToken),
      }
    );
  }

  static refreshWorkflow({
    userId,
    vaultOwnerToken,
    workflowId,
  }: AuthInput & { workflowId: string }): Promise<OneKycWorkflow> {
    return apiJson<OneKycWorkflow>(
      `/api/one/kyc/workflows/${encodeURIComponent(workflowId)}/refresh`,
      {
        method: "POST",
        headers: authHeaders(vaultOwnerToken),
        body: JSON.stringify({ user_id: userId }),
      }
    );
  }

  static selectScopes({
    userId,
    vaultOwnerToken,
    workflowId,
    selectedScopes,
  }: AuthInput & { workflowId: string; selectedScopes: string[] }): Promise<OneKycWorkflow> {
    return apiJson<OneKycWorkflow>(
      `/api/one/kyc/workflows/${encodeURIComponent(workflowId)}/scope-selection`,
      {
        method: "POST",
        headers: authHeaders(vaultOwnerToken),
        body: JSON.stringify({ user_id: userId, selected_scopes: selectedScopes }),
      }
    );
  }

  static sendApprovedReply({
    userId,
    vaultOwnerToken,
    workflowId,
    approvedSubject,
    approvedBody,
    approvedHtml,
    clientDraftHash,
    consentExportRevision,
    pkmWritebackArtifactHash,
  }: AuthInput & {
    workflowId: string;
    approvedSubject?: string | null;
    approvedBody: string;
    approvedHtml?: string | null;
    clientDraftHash?: string | null;
    consentExportRevision?: number | null;
    pkmWritebackArtifactHash: string;
  }): Promise<OneKycWorkflow> {
    return apiJson<OneKycWorkflow>(
      `/api/one/kyc/workflows/${encodeURIComponent(workflowId)}/send-approved-reply`,
      {
        method: "POST",
        headers: authHeaders(vaultOwnerToken),
        body: JSON.stringify({
          user_id: userId,
          approved_subject: approvedSubject,
          approved_body: approvedBody,
          approved_html: approvedHtml,
          client_draft_hash: clientDraftHash,
          consent_export_revision: consentExportRevision,
          pkm_writeback_artifact_hash: pkmWritebackArtifactHash,
        }),
      }
    );
  }

  static rejectDraft({
    userId,
    vaultOwnerToken,
    workflowId,
    reason,
  }: AuthInput & { workflowId: string; reason?: string }): Promise<OneKycWorkflow> {
    return apiJson<OneKycWorkflow>(
      `/api/one/kyc/workflows/${encodeURIComponent(workflowId)}/reject-draft`,
      {
        method: "POST",
        headers: authHeaders(vaultOwnerToken),
        body: JSON.stringify({ user_id: userId, reason }),
      }
    );
  }

  static redraft({
    userId,
    vaultOwnerToken,
    workflowId,
    instructions,
    source = "text",
  }: AuthInput & {
    workflowId: string;
    instructions: string;
    source?: "text" | "voice";
  }): Promise<OneKycWorkflow> {
    return apiJson<OneKycWorkflow>(
      `/api/one/kyc/workflows/${encodeURIComponent(workflowId)}/redraft`,
      {
        method: "POST",
        headers: authHeaders(vaultOwnerToken),
        body: JSON.stringify({ user_id: userId, instructions, source }),
      }
    );
  }

  static getClientConnector({
    userId,
    vaultOwnerToken,
  }: AuthInput): Promise<OneKycClientConnectorResponse> {
    const query = new URLSearchParams({ user_id: userId });
    return apiJson<OneKycClientConnectorResponse>(
      `/api/one/kyc/client-connector?${query.toString()}`,
      { headers: authHeaders(vaultOwnerToken) }
    );
  }

  static registerClientConnector({
    userId,
    vaultOwnerToken,
    connector,
  }: AuthInput & { connector: KycClientConnectorPrivateRecord }): Promise<OneKycClientConnectorResponse> {
    return apiJson<OneKycClientConnectorResponse>("/api/one/kyc/client-connector", {
      method: "POST",
      headers: authHeaders(vaultOwnerToken),
      body: JSON.stringify({
        user_id: userId,
        connector_public_key: connector.connector_public_key,
        connector_key_id: connector.connector_key_id,
        connector_wrapping_alg: connector.connector_wrapping_alg,
        public_key_fingerprint: connector.public_key_fingerprint,
      }),
    });
  }

  static getWorkflowConsentExport({
    userId,
    vaultOwnerToken,
    workflowId,
  }: AuthInput & { workflowId: string }): Promise<KycScopedExportPackage> {
    const query = new URLSearchParams({ user_id: userId });
    return apiJson<KycScopedExportPackage>(
      `/api/one/kyc/workflows/${encodeURIComponent(workflowId)}/consent-export?${query.toString()}`,
      {
        headers: authHeaders(vaultOwnerToken),
      }
    );
  }

  static getWorkflowConsentExports({
    userId,
    vaultOwnerToken,
    workflowId,
  }: AuthInput & { workflowId: string }): Promise<OneKycWorkflowConsentExportsResponse> {
    const query = new URLSearchParams({ user_id: userId });
    return apiJson<OneKycWorkflowConsentExportsResponse>(
      `/api/one/kyc/workflows/${encodeURIComponent(workflowId)}/consent-exports?${query.toString()}`,
      {
        headers: authHeaders(vaultOwnerToken),
      }
    );
  }

  static writebackComplete({
    userId,
    vaultOwnerToken,
    workflowId,
    artifactHash,
    status = "succeeded",
    errorMessage,
  }: AuthInput & {
    workflowId: string;
    artifactHash: string;
    status?: "succeeded" | "failed";
    errorMessage?: string | null;
  }): Promise<OneKycWorkflow> {
    return apiJson<OneKycWorkflow>(
      `/api/one/kyc/workflows/${encodeURIComponent(workflowId)}/writeback-complete`,
      {
        method: "POST",
        headers: authHeaders(vaultOwnerToken),
        body: JSON.stringify({
          user_id: userId,
          artifact_hash: artifactHash,
          status,
          error_message: errorMessage,
        }),
      }
    );
  }
}
