export type SuperAdminUser = {
  id: number;
  email: string;
  name: string;
  role: string;
  user_type: string;
  tenant_id: number;
  is_superadmin: boolean;
};

export type MobileLoginUserPayload = {
  id: number;
  email: string;
  name: string;
  role: string;
  user_type: string;
  tenant_id: number;
  is_superadmin: number;
};

// Réponse de POST /api/mobile/login.php. Depuis 2026-05-11 le backend peut
// renvoyer 2 shapes : flow classique avec access_token, OU un challenge TOTP
// si le user est super-admin avec `totp_enabled=1` (cf handoff Q5 + thread
// MCP #90 pour le 2FA).
export type MobileLoginResponse = {
  success: boolean;
  data?:
    | {
        access_token: string;
        token_type: string;
        expires_in: number;
        refresh_token: string;
        refresh_expires_in: number;
        user: MobileLoginUserPayload;
        requires_totp?: false;
      }
    | {
        requires_totp: true;
        challenge_token: string;
      };
  message?: string;
};

// Réponse de POST /api/mobile/totp/challenge.php — même shape que login.php
// quand le code TOTP est valide (émet les tokens + user).
export type TotpChallengeResponse = {
  success: boolean;
  data?: {
    access_token: string;
    token_type: string;
    expires_in: number;
    refresh_token: string;
    refresh_expires_in: number;
    user: MobileLoginUserPayload;
  };
  message?: string;
};

// Réponse de POST /api/mobile/totp/setup.php — secret base32 + URI otpauth
// pour QR code / saisie manuelle dans l'authenticator.
export type TotpSetupResponse = {
  success: boolean;
  data?: {
    secret_base32: string;
    otpauth_uri: string;
  };
  message?: string;
};

export type TenantStatus = "pending" | "active" | "suspended" | "cancelled";

export type Tenant = {
  id: number;
  slug: string;
  name: string;
  status: TenantStatus;
  plan_code: string | null;
  created_at: string;
};

// --- report_templates : contrats des endpoints diff + apply ---
// Source backend : public/api/report_templates_{diff,apply}.php
// Cf handoff Q4 — 2026-05-08 soir.

export type PairCategory =
  | "common"
  | "common_divergent"
  | "rename"
  | "xlsx_only"
  | "db_only_volontaire"
  | "db_only_orphan";

export type DiffPair = {
  pair_uid: string;
  category: PairCategory;
  diff_fields: string[];
  xlsx: Record<string, unknown> | null;
  db: Record<string, unknown> | null;
  children: DiffPair[];
};

export type DiffPhase = {
  index: number;
  xlsx_name: string;
  db_name: string;
  pairs: DiffPair[];
};

export type DiffStats = {
  common: number;
  common_divergent: number;
  rename: number;
  xlsx_only: number;
  db_only_volontaire: number;
  db_only_orphan: number;
};

export type DiffTemplate = {
  sheet_name: string;
  machine_type_value: string | null;
  db_template_id: number | null;
  db_name: string | null;
  xlsx_sha256: string;
  // Optionnels : absents quand le backend renvoie le cas erreur
  // "machine_type non détectable" (cf. handoff Q4) ou tout autre cas
  // dégénéré. À garder optionnels pour ne pas crasher au render.
  phases?: DiffPhase[];
  stats?: DiffStats;
  // Présent quand le machine_type n'a pas été détecté
  error?: string;
};

export type DiffResponse = {
  success: boolean;
  data: { templates: DiffTemplate[] };
  message?: string;
};

export type ApplySummary = {
  steps_inserted: number;
  steps_soft_deleted: number;
  options_inserted: number;
  options_soft_deleted: number;
  pairs_processed: number;
  pairs_noop: number;
};

export type ApplyOperation = {
  operation: string;
  step_id: number | null;
  option_id: number | null;
  old_state: Record<string, unknown> | null;
  new_state: Record<string, unknown> | null;
};

export type ApplyComparison = {
  xlsx: Array<Record<string, unknown>>;
  db_before: Array<Record<string, unknown>>;
  db_after: Array<Record<string, unknown>>;
};

export type ApplyResponse = {
  success: boolean;
  data: {
    apply_run_id: string;
    dry_run: 0 | 1;
    summary: ApplySummary;
    operations: ApplyOperation[];
    new_version_label: string;
    comparison: ApplyComparison;
  };
};

// Erreurs métier renvoyées par /apply (cf. mapApplyErrorToHttpCode côté backend).
export type ApplyErrorCode =
  | "TEMPLATE_NOT_FOUND"
  | "WORKFLOWS_IN_PROGRESS"
  | "CROSS_TEMPLATE_PARENT"
  | "MIGRATION_ID_LOCKED"
  | "SHA256_MISMATCH"
  | "INVALID_SELECTION_PAIR"
  | "PAYLOAD_INVALID";

export type ApiErrorBody = {
  success: false;
  message: string;
  error?: string;
  error_code?: ApplyErrorCode;
  // contexte additionnel selon le code (blocking_workflows, cross_template_links, etc.)
  [k: string]: unknown;
};
