import type { ApiSettings } from "../types";
import { apiFetch, apiPath } from "./client";

export type PrivacyRetentionPolicyFieldKey =
  | "store_raw_campaign_json"
  | "raw_campaign_json_retention_days"
  | "generated_eml_retention_days"
  | "stored_report_detail_retention_days"
  | "mock_mailbox_retention_days"
  | "audit_detail_retention_days"
  | "audit_detail_level";

export type PrivacyRetentionLimitPermissions = Record<PrivacyRetentionPolicyFieldKey, boolean>;
export type PrivacyRetentionLimitPermissionPatch = Partial<PrivacyRetentionLimitPermissions>;

export type PrivacyRetentionPolicy = {
  store_raw_campaign_json: boolean;
  raw_campaign_json_retention_days?: number | null;
  generated_eml_retention_days?: number | null;
  stored_report_detail_retention_days?: number | null;
  mock_mailbox_retention_days?: number | null;
  audit_detail_retention_days?: number | null;
  audit_detail_level: "full" | "redacted" | "minimal";
  allow_lower_level_limits: PrivacyRetentionLimitPermissions;
};

export type PrivacyRetentionPolicyPatch = Partial<Omit<PrivacyRetentionPolicy, "allow_lower_level_limits">> & {
  allow_lower_level_limits?: PrivacyRetentionLimitPermissionPatch;
};

export type PrivacyRetentionPolicyScope = "system" | "tenant" | "user" | "group" | "campaign";

export type PolicySourceStep = {
  scope_type: string;
  scope_id?: string | null;
  path: string;
  label: string;
  applied_fields?: string[];
  policy?: PrivacyRetentionPolicyPatch | PrivacyRetentionPolicy | null;
};

export type PolicyDecision = {
  allowed: boolean;
  reason?: string | null;
  source_path: PolicySourceStep[];
  requirements: string[];
  details?: Record<string, unknown>;
};

export type PrivacyRetentionPolicyScopeResponse = {
  scope_type: PrivacyRetentionPolicyScope;
  scope_id?: string | null;
  policy: PrivacyRetentionPolicyPatch;
  effective_policy: PrivacyRetentionPolicy;
  parent_policy?: PrivacyRetentionPolicy | null;
  effective_policy_sources?: PolicySourceStep[];
  parent_policy_sources?: PolicySourceStep[];
};

export type PrivacyRetentionPolicyExplainResponse = {
  scope_type: PrivacyRetentionPolicyScope;
  scope_id?: string | null;
  decision: PolicyDecision;
  effective_policy: PrivacyRetentionPolicy;
  parent_policy?: PrivacyRetentionPolicy | null;
  effective_policy_sources?: PolicySourceStep[];
  parent_policy_sources?: PolicySourceStep[];
  blocked_fields: PrivacyRetentionPolicyFieldKey[];
};

export type RetentionRunResponse = {
  result: {
    dry_run: boolean;
    policy: PrivacyRetentionPolicy;
    cutoffs: Record<string, string | null>;
    effective_policy_scope?: string;
    counts: Record<string, Record<string, number>>;
  };
};

export function getPrivacyRetentionPolicy(
  settings: ApiSettings,
  scope: PrivacyRetentionPolicyScope,
  scopeId?: string | null
): Promise<PrivacyRetentionPolicyScopeResponse> {
  return apiFetch(
    settings,
    apiPath(`/api/v1/admin/privacy-retention/policies/${encodeURIComponent(scope)}`, { scope_id: scopeId })
  );
}

export function explainPrivacyRetentionPolicy(
  settings: ApiSettings,
  scope: PrivacyRetentionPolicyScope,
  scopeId?: string | null
): Promise<PrivacyRetentionPolicyExplainResponse> {
  return apiFetch(
    settings,
    apiPath(`/api/v1/admin/privacy-retention/policies/${encodeURIComponent(scope)}/explain`, { scope_id: scopeId })
  );
}

export function updatePrivacyRetentionPolicy(
  settings: ApiSettings,
  scope: PrivacyRetentionPolicyScope,
  policy: PrivacyRetentionPolicyPatch,
  scopeId?: string | null,
  changeRequestId?: string | null
): Promise<PrivacyRetentionPolicyScopeResponse> {
  return apiFetch(
    settings,
    apiPath(`/api/v1/admin/privacy-retention/policies/${encodeURIComponent(scope)}`, { scope_id: scopeId }),
    { method: "PUT", body: JSON.stringify({ policy, change_request_id: changeRequestId ?? null }) }
  );
}

export function runRetentionPolicy(settings: ApiSettings, dryRun = true): Promise<RetentionRunResponse> {
  return apiFetch(settings, "/api/v1/admin/system/retention/run", {
    method: "POST",
    body: JSON.stringify({ dry_run: dryRun })
  });
}
