import e, { CookieOptions } from "express";
import * as helper from "../common/helper";
import { Document, Types } from "mongoose";

/**
 * Obtiene el valor de una variable de entorno.
 * @param {string} name
 * @param {?boolean} required
 * @param {?string} defaultValue
 * @returns {string}
 */

export const __env__ = (
  name: string,
  required?: boolean,
  defaultValue?: string,
) => {
  const value = process.env[name];
  if (required && !value) {
    throw new Error(`Environment variable ${name} is required`);
  }
  return value ? String(value) : defaultValue || "";
};

/**
 * Puerto del servidor. Por defecto 4002.
 *
 * @type {number}
 */
export const PORT = Number.parseInt(__env__("P_PORT", false, "4002"), 10);

/**
 * Indica si HTTPS está habilitado o no.
 *
 * @type {boolean}
 */
export const HTTPS = helper.StringToBoolean(__env__("P_HTTPS"));

/**
 * Ruta del archivo de clave privada SSL.
 *
 * @type {string}
 */
export const PRIVATE_KEY = __env__("P_PRIVATE_KEY", HTTPS);

/**
 * Ruta del archivo de certificado SSL.
 *
 * @type {string}
 */
export const CERTIFICATE = __env__("P_CERTIFICATE", HTTPS);

/**
 * Nombre de la cookie de autenticación del frontend.
 *
 * @type {"p-x-access-token-frontend"}
 */
export const FRONTEND_AUTH_COOKIE_NAME = "p-x-access-token-frontend";

/**
 * Nombre de la cookie de autenticación del backend.
 *
 * @type {"p-x-access-token-backend"}
 */
export const BACKEND_AUTH_COOKIE_NAME = "p-x-access-token-backend";

/**
 * Nombre del header de autenticación para la app móvil y pruebas unitarias.
 *
 * @type {"x-access-token"}
 */
export const X_ACCESS_TOKEN = "x-access-token";

/**
 * Secreto JWT. Debe tener al menos 32 caracteres; mientras más largo, mejor.
 *
 * @type {string}
 */
export const JWT_SECRET = __env__(
  "P_JWT_SECRET",
  true,
);

/**
 * Expiración del JWT en segundos. Por defecto 86400 segundos (1 día).
 *
 * @type {number}
 */
export const JWT_EXPIRE_AT = Number.parseInt(
  __env__("P_JWT_EXPIRE_AT", false, "86400"),
  10,
);

/**
 * Expiración del token de validación en segundos. Por defecto 86400 segundos (1 día).
 *
 * @type {number}
 */
export const TOKEN_EXPIRE_AT = Number.parseInt(
  __env__("P_TOKEN_EXPIRE_AT", false, "86400"),
  10,
);

/**
 * Expiración del token de Agile Check en segundos. Por defecto 3600 segundos (1 hora).
 *
 * @type {number}
 */
export const AGILE_CHECK_TOKEN_EXPIRE_AT = Number.parseInt(
  __env__("P_AGILE_CHECK_TOKEN_EXPIRE_AT", false, "3600"),
  10,
);

/**
 * Expiración de operación en segundos. Por defecto 3600 segundos (1 hora).
 *
 * @type {number}
 */
export const OPERATION_EXPIRE_AT = Number.parseInt(
  __env__("P_OPERATION_EXPIRE_AT", false, "3600"),
  10,
);

/**
 * Host del backend.
 *
 * @type {string}
 */
export const BACKEND_HOST = __env__("P_BACKEND_HOST", true);

/**
 * Dominio del frontend.
 *
 * @type {string}
 */
export const FRONTEND_DOMAIN = __env__("P_FRONTEND_DOMAIN", true);

/**
 * Secreto de la cookie. Debe tener al menos 32 caracteres; mientras más largo, mejor.
 *
 * @type {string}
 */
export const COOKIE_SECRET = __env__(
  "P_COOKIE_SECRET",
  false,
  "Per-Capital-API-Secret",
);

/**
 * Dominio de la cookie de autenticación. Por defecto localhost.
 *
 * @type {string}
 */
export const AUTH_COOKIE_DOMAIN = __env__(
  "P_AUTH_COOKIE_DOMAIN",
  false,
  "localhost",
);

/**
 * Indica si HTTPS del cliente está habilitado o no.
 *
 * @type {boolean}
 */
export const HTTPS_CLIENT = helper.StringToBoolean(__env__("P_HTTPS_CLIENT"));

/**
 * Indica si SSL de MongoDB está habilitado o no.
 *
 * @type {boolean}
 */
export const DB_SSL = helper.StringToBoolean(
  __env__("P_DB_SSL", false, "false"),
);

/**
 * Ruta del certificado SSL de MongoDB.
 *
 * @type {string}
 */
export const DB_SSL_CERT = __env__("P_DB_SSL_CERT", DB_SSL);

/**
 * Ruta del certificado CA de SSL de MongoDB.
 *
 * @type {string}
 */
export const DB_SSL_CA = __env__("P_DB_SSL_CA", DB_SSL);

/**
 * Indica si el modo debug de MongoDB está habilitado o no.
 *
 * @type {boolean}
 */
export const DB_DEBUG = helper.StringToBoolean(
  __env__("P_DB_DEBUG", false, "false"),
);

/**
 * URI de la base de datos MongoDB. Por defecto: mongodb://127.0.0.1:27017/pasta?authSource=admin&appName=pasta
 *
 * @type {string}
 */
export const DB_URI = __env__(
  "P_DB_URI",
  false,
  "mongodb://127.0.0.1:27017/pasta?authSource=admin&appName=pasta",
);

/**
 * Clave de encriptación.
 *
 * @type {string}
 */
export const ENCRYPTION_KEY = __env__("P_ENCRYPTION_KEY", false, "pasta");

/**
 * URL de verificación de Didit.
 *
 * @type {string}
 */
export const DIDIT_VERIFICATION_URL = __env__("P_DIDIT_VERIFICATION_URL", true);

/**
 * API Key de Didit.
 *
 * @type {string}
 */
export const DIDIT_API_KEY = __env__("P_DIDIT_API_KEY", true);

/**
 * ID del flujo de trabajo de Didit.
 *
 * @type {string}
 */
export const DIDIT_WORKFLOW_ID = __env__("P_DIDIT_WORKFLOW_ID", true);

/**
 * Clave secreta del webhook de Didit.
 *
 * @type {string}
 */
export const DIDIT_WEBHOOK_SECRET_KEY = __env__("P_DIDIT_WEBHOOK_SECRET", true);

/**
 * Versión actual de la API (ej: "v1").
 *
 * @type {string}
 */
export const API_VERSION = __env__("P_API_VERSION", true);

/**
 * Host del servidor SMTP.
 *
 * @type {string}
 */
export const SMTP_HOST = __env__("P_SMTP_HOST", true);

/**
 * Puerto del servidor SMTP.
 *
 * @type {number}
 */
export const SMTP_PORT = Number.parseInt(__env__("P_SMTP_PORT", true), 10);

/**
 * Usuario del servidor SMTP.
 *
 * @type {string}
 */
export const SMTP_USER = __env__("P_SMTP_USER", true);

/**
 * Contraseña del servidor SMTP.
 *
 * @type {string}
 */
export const SMTP_PASS = __env__("P_SMTP_PASS", true);

/**
 * Correo remitente del SMTP.
 *
 * @type {string}
 */
export const SMTP_FROM = __env__("P_SMTP_FROM", true);

/**
 * URL de la API.
 *
 * @type {string}
 */
export const API_URL = __env__("P_API_URL", true);

/**
 * SID de la cuenta de Twilio.
 *
 * @type {string}
 */
export const TWILIO_ACCOUNT_SID = __env__("P_TWILIO_ACCOUNT_SID", true);

/**
 * Token de autenticación de Twilio.
 *
 * @type {string}
 */
export const TWILIO_AUTH_TOKEN = __env__("P_TWILIO_AUTH_TOKEN", true);

/**
 * Número de teléfono de Twilio.
 *
 * @type {string}
 */
export const TWILIO_PHONE_NUMBER = __env__("P_TWILIO_PHONE_NUMBER", true);

/**
 * Número de WhatsApp de Twilio.
 *
 * @type {string}
 */
export const TWILIO_WHATSAPP_NUMBER = __env__("P_TWILIO_WHATSAPP_NUMBER", true);

/**
 * Configuración de Firebase Cloud Messaging (opcional).
 */
export const FCM_ENABLED = helper.StringToBoolean(
  __env__("FIREBASE_FCM_ENABLED", false, "false"),
);
export const FCM_PROJECT_ID = __env__("FIREBASE_PROJECT_ID", false);
export const FCM_CLIENT_EMAIL = __env__("FIREBASE_CLIENT_EMAIL", false);
export const FCM_PRIVATE_KEY = __env__("FIREBASE_PRIVATE_KEY", false);

/**
 * URL pública de la API.
 *
 * @type {string}
 */
export const PUBLIC_API_URL = __env__("P_PUBLIC_API_URL", true);

/**
 * URL del panel de administración.
 *
 * @type {string}
 */
export const ADMIN_URL = __env__("P_ADMIN_URL", true);

/**
 * Ruta del CDN para imágenes de usuarios.
 *
 * @type {string}
 */
export const CDN_USERS = __env__("P_CDN_USERS", true);

/**
 * Ruta del CDN para documentos.
 *
 * @type {string}
 */
export const CDN_DOCUMENTS = __env__("P_CDN_DOCUMENTS", true);

/**
 * Ruta de los términos y condiciones.
 *
 * @type {string}
 */
export const TERMS_AND_CONDITIONS_PATH = __env__(
  "P_TERMS_AND_CONDITIONS_PATH",
  true,
);

/**
 * URL de la API de Agile Check.
 *
 * @type {string}
 */
export const AGILE_CHECK_API_URL = __env__("P_AGILE_CHECK_API_URL", true);

/**
 * Usuario de la API de Agile Check.
 *
 * @type {string}
 */
export const AGILE_CHECK_API_USER = __env__("P_AGILE_CHECK_API_USER", true);

/**
 * Contraseña de la API de Agile Check.
 *
 * @type {string}
 */
export const AGILE_CHECK_API_PASSWORD = __env__(
  "P_AGILE_CHECK_API_PASSWORD",
  true,
);

/**
 * Validación de certificado de la API de Agile Check.
 *
 * @type {string}
 */
export const AGILE_CHECK_API_VALIDATE_CERT = __env__(
  "P_AGILE_CHECK_API_VALIDATE_CERT",
  true,
);

/**
 * Configuración de Banesco.
 * Variables opcionales para evitar errores al cargar. Incluye credenciales
 * y URLs para los servicios de Consulta, Vuelto P2P y Cargo en Cuenta.
 */
export const BANESCO_VALIDATE_CERT = __env__("P_BANESCO_VALIDATE_CERT", false, "false");
export const BANESCO_CONSULTA_API_SSO = __env__("P_BANESCO_CONSULTA_API_SSO", false);
export const BANESCO_CONSULTA_API_CLIENT_ID = __env__("P_BANESCO_CONSULTA_API_CLIENT_ID", false);
export const BANESCO_CONSULTA_API_CLIENT_SECRET = __env__("P_BANESCO_CONSULTA_API_CLIENT_SECRET", false);
export const BANESCO_CONSULTA_API_USER = __env__("P_BANESCO_CONSULTA_API_USER", false);
export const BANESCO_CONSULTA_API_PASSWORD = __env__("P_BANESCO_CONSULTA_API_PASSWORD", false);
export const BANESCO_CONSULTA_API_URL = __env__("P_BANESCO_CONSULTA_API_URL", false);
export const BANESCO_VUELTO_API_SSO = __env__("P_BANESCO_VUELTO_API_SSO", false);
export const BANESCO_VUELTO_API_CLIENT_ID = __env__("P_BANESCO_VUELTO_API_CLIENT_ID", false);
export const BANESCO_VUELTO_API_CLIENT_SECRET = __env__("P_BANESCO_VUELTO_API_CLIENT_SECRET", false);
export const BANESCO_VUELTO_API_USER = __env__("P_BANESCO_VUELTO_API_USER", false);
export const BANESCO_VUELTO_API_PASSWORD = __env__("P_BANESCO_VUELTO_API_PASSWORD", false);
export const BANESCO_VUELTO_API_URL = __env__("P_BANESCO_VUELTO_API_URL", false);
export const BANESCO_CARGO_EN_CUENTA_API_PROXY_URL = __env__("P_BANESCO_CARGO_EN_CUENTA_API_PROXY_URL", false);
export const BANESCO_CARGO_EN_CUENTA_API_RESPONSE_TYPE = __env__("P_BANESCO_CARGO_EN_CUENTA_API_RESPONSE_TYPE", false);
export const BANESCO_CARGO_EN_CUENTA_API_CALLBACK_URL = __env__("P_BANESCO_CARGO_EN_CUENTA_API_CALLBACK_URL", false);
export const BANESCO_CARGO_EN_CUENTA_API_SCOPE = __env__("P_BANESCO_CARGO_EN_CUENTA_API_SCOPE", false);
export const BANESCO_CARGO_EN_CUENTA_API_SSO = __env__("P_BANESCO_CARGO_EN_CUENTA_API_SSO", false);
export const BANESCO_CARGO_EN_CUENTA_API_CLIENT_ID = __env__("P_BANESCO_CARGO_EN_CUENTA_API_CLIENT_ID", false);
export const BANESCO_CARGO_EN_CUENTA_API_CLIENT_SECRET = __env__("P_BANESCO_CARGO_EN_CUENTA_API_CLIENT_SECRET", false);
export const BANESCO_CARGO_EN_CUENTA_API_USER = __env__("P_BANESCO_CARGO_EN_CUENTA_API_USER", false);
export const BANESCO_CARGO_EN_CUENTA_API_PASSWORD = __env__("P_BANESCO_CARGO_EN_CUENTA_API_PASSWORD", false);
export const BANESCO_CARGO_EN_CUENTA_API_CONSULTA_DE_CUENTA_URL = __env__("P_BANESCO_CARGO_EN_CUENTA_API_CONSULTA_DE_CUENTA_URL", false);
export const BANESCO_CARGO_EN_CUENTA_API_CARGO_EN_CUENTA_PAGO_URL = __env__("P_BANESCO_CARGO_EN_CUENTA_API_CARGO_EN_CUENTA_PAGO_URL", false);
export const BANESCO_CARGO_EN_CUENTA_API_CONSULTA_DE_TRANSACCION_URL = __env__("P_BANESCO_CARGO_EN_CUENTA_API_CONSULTA_DE_TRANSACCION_URL", false);

/**
 * URL base del sitio web de la API (para generar páginas HTML de redirección).
 *
 * @type {string}
 */
export const API_WEBSITE_URL = __env__("P_API_WEBSITE_URL", true);

/**
 * Ruta del directorio donde se almacenan los archivos de domiciliación bancaria.
 *
 * @type {string}
 */
export const DOMICILIATION_FILE_PATH = __env__(
  "P_DOMICILIATION_FILE_PATH",
  true,
);

/**
 * URL base de la API de Sypago.
 *
 * @type {string}
 */
export const SYPAGO_API_URL = __env__("P_SYPAGO_API_URL", true);

/**
 * Client ID para autenticación con Sypago.
 *
 * @type {string}
 */
export const SYPAGO_CLIENT_ID = __env__("P_SYPAGO_CLIENT_ID", true);

/**
 * API Key (secret) para autenticación con Sypago.
 *
 * @type {string}
 */
export const SYPAGO_API_KEY = __env__("P_SYPAGO_API_KEY", true);

/**
 * Token de acceso estático de Sypago (opcional, evita autenticación dinámica).
 *
 * @type {string}
 */
export const SYPAGO_ACCESS_TOKEN = __env__("P_SYPAGO_ACCESS_TOKEN");

/**
 * Código del banco de la cuenta operativa en Sypago.
 *
 * @type {string}
 */
export const SYPAGO_BANK_ACCOUNT_CODE = __env__(
  "P_SYPAGO_BANK_ACCOUNT_CODE",
  true,
);

/**
 * Número de cuenta operativa en Sypago.
 *
 * @type {string}
 */
export const SYPAGO_BANK_ACCOUNT_NUMBER = __env__(
  "P_SYPAGO_BANK_ACCOUNT_NUMBER",
  true,
);

/**
 * URL del webhook para notificaciones de Sypago.
 *
 * @type {string}
 */
export const SYPAGO_WEBHOOK_URL = __env__("P_SYPAGO_WEBHOOK_URL", true);

/**
 * Token de autenticación para validar webhooks entrantes de Sypago.
 *
 * @type {string}
 */
export const SYPAGO_WEBHOOK_TOKEN = __env__("P_SYPAGO_WEBHOOK_TOKEN", true);

/**
 * IPs permitidas para recibir webhooks de Sypago. Default: 127.0.0.1.
 *
 * @type {string}
 */
export const SYPAGO_ALLOWED_IPS = __env__(
  "P_SYPAGO_ALLOWED_IPS",
  false,
  "127.0.0.1",
);

/**
 * ID del subproducto de crédito en Sypago.
 *
 * @type {string}
 */
export const SYPAGO_CREDIT_SUBPRODUCT_ID = __env__(
  "P_SYPAGO_CREDIT_SUBPRODUCT_ID",
  true,
);

/**
 * URL base de la API de Bancamiga.
 *
 * @type {string}
 */
export const BANCAMIGA_API_URL = __env__("P_BANCAMIGA_API_URL", true);

/**
 * Usuario de autenticación para la API de Bancamiga.
 *
 * @type {string}
 */
export const BANCAMIGA_USER = __env__("P_BANCAMIGA_USER", true);

/**
 * Contraseña de autenticación para la API de Bancamiga.
 *
 * @type {string}
 */
export const BANCAMIGA_PASSWORD = __env__("P_BANCAMIGA_PASSWORD", true);

/**
 * LA Sistemas API URL
 *
 * @type {string}
 */
export const LA_SISTEMAS_API_URL = __env__("P_LA_SISTEMAS_API_URL", true);

/**
 * LA Sistemas API Key
 *
 * @type {string}
 */
export const LA_SISTEMAS_API_KEY = __env__("P_LA_SISTEMAS_API_KEY", true);

/**
 * Indica si el entorno está en modo testing (omite ciertas validaciones de monto).
 *
 * @type {string}
 */
export const TESTING = __env__("P_TESTING", true);

/**
 * Indica si se debe crear la suscripción definitiva durante el registro (pre-suscripción, LA Sistemas, SubscriptionPayment).
 * Por defecto true para mantener el comportamiento actual.
 *
 * @type {boolean}
 */
export const ENABLE_SUBSCRIPTION_ON_REGISTER = helper.StringToBoolean(
  __env__("P_ENABLE_SUBSCRIPTION_ON_REGISTER", false, "true"),
);

/**
 * Hora del día (0-23) para ejecutar las notificaciones diarias de pagos. Default: 0.
 *
 * @type {string}
 */
export const DAILY_PAYMENT_NOTIFICATIONS_HOUR = __env__(
  "P_DAILY_PAYMENT_NOTIFICATIONS_HOUR",
  true,
  "0",
);

/**
 * Minuto (0-59) para ejecutar las notificaciones diarias de pagos. Default: 5.
 *
 * @type {string}
 */
export const DAILY_PAYMENT_NOTIFICATIONS_MINUTE = __env__(
  "P_DAILY_PAYMENT_NOTIFICATIONS_MINUTE",
  true,
  "5",
);

/**
 * Opciones de la cookie de autenticación.
 *
 * En producción, las cookies son httpOnly, firmadas, seguras y con sameSite estricto.
 * Esto previene ataques XSS al no permitir acceso a la cookie vía JavaScript,
 * ataques CSRF al no enviar la cookie en solicitudes cross-site,
 * y ataques MITM al solo enviar la cookie por HTTPS.
 * También se protege contra ataques XST deshabilitando el método HTTP TRACE
 * mediante el middleware allowedMethods.
 *
 * @type {CookieOptions}
 */
export const COOKIE_OPTIONS: CookieOptions = {
  httpOnly: true,
  secure: HTTPS_CLIENT,
  signed: true,
  sameSite: "strict",
  domain: AUTH_COOKIE_DOMAIN,
};

/**
 * Usuario del sistema. Contiene datos personales, financieros, de verificación,
 * configuración de notificaciones, tokens push y estado del usuario.
 *
 * @export
 * @interface User
 * @typedef {User}
 * @extends {Document}
 */
export interface User extends Document {
  _id: string;
  document: string;
  identificationType: string;
  name: string;
  lastname: string;
  gender: string;
  maritalStatus: string;
  birthDate: Date;
  address?: string;
  selfEmployed: boolean;
  enterprise?: {
    name: string;
    address: string;
    phone: string;
    position: string;
  };
  occupation?: string;
  dependents: number;
  seniority: number;
  income: number;
  otherIncome: number;
  education: string;
  email: string;
  phone: {
    countryCode: string;
    areaCode?: string;
    number: string;
  };
  sessionId: string;
  password: string;
  status: string;
  isVerified: boolean;
  verificationStatus: string;
  acceptedTermsAndConditions: [
    {
      acceptedAt: Date;
      version: string;
    },
  ];
  level: number;
  levelName: string;
  maxAmount: number;
  points: number;
  allowedFeeCount: number[];
  roles: string[];
  statusHistory: [
    {
      createdAt: Date;
      status: string;
      note: string;
    },
  ];
  notificationsConfig: {
    email: boolean;
    sms: boolean;
    push: boolean;
    promotions: boolean;
  };
  image: string;
  documentImages: [
    {
      documentType: string;
      image: string;
      dateOfIssue: Date;
      expirationDate: Date;
    },
  ];
  pushToken: string;
  pushTokens: string[];
  updatedAt: Date;
  achievements: [Types.ObjectId];
  agileCheckLists: [number];
  pep: boolean;
  pepInfo: {
    relationship: string;
    entity: string;
    name: string;
    occupation: string;
    identification: string;
    agileCheckLists: [number];
  };
  refreshTokens: string[];
  userAgent: string;
}

/**
 * Documento de token. Utilizado para tokens de validación, recuperación de
 * contraseña y verificación de email.
 *
 * @export
 * @interface Token
 * @typedef {Token}
 * @extends {Document}
 */
export interface Token extends Document {
  user?: Types.ObjectId;
  email?: string;
  token: string;
  type: string;
  expireAt?: Date;
}

/**
 * Cuenta bancaria del usuario. Incluye banco, tipo y número de cuenta.
 *
 * @interface Account
 * @typedef {Account}
 * @extends {Document}
 */
export interface Account extends Document {
  user: Types.ObjectId;
  bank: {
    name: string;
    code: string;
    laCode: string;
  };
  type: string;
  number: string;
}

/**
 * Cuenta administrativa. Cuenta operativa del sistema con moneda, banco y número.
 *
 * @interface AdminAccount
 * @typedef {AdminAccount}
 * @extends {Document}
 */
export interface AdminAccount extends Document {
  currency: string;
  bank: Types.ObjectId;
  type: string;
  number: string;
}

/**
 * Banco. Incluye nombre, código, código de LA Sistemas y moneda.
 *
 * @export
 * @interface Bank
 * @typedef {Bank}
 * @extends {Document}
 */
export interface Bank extends Document {
  name: string;
  code: string;
  laCode: string;
  currency: string;
}

/**
 * Notificación (v1). Contiene usuario, mensaje, tipo y estado de lectura.
 *
 * @export
 * @interface Notification
 * @typedef {Notification}
 * @extends {Document}
 */
export interface Notification extends Document {
  user: Types.ObjectId;
  message: string;
  type: string;
  isRead: boolean;
}

/**
 * Contador de notificaciones no leídas por usuario.
 *
 * @export
 * @interface NotificationCounter
 * @typedef {NotificationCounter}
 * @extends {Document}
 */
export interface NotificationCounter extends Document {
  user: Types.ObjectId;
  count: number;
}

/**
 * Operación de crédito. Contiene datos del usuario, montos (VEF/USD), tasa,
 * comisiones, plan de pagos, beneficiario, estado y referencias internas/externas.
 *
 * @export
 * @interface Operation
 * @typedef {Operation}
 * @extends {Document}
 */
export interface Operation extends Document {
  user: {
    name: string;
    lastname: string;
    email: string;
    identificationType: string;
    document: string;
  };
  currency: string;
  amountVef: number;
  rate: number;
  amountUsd: number;
  annualCommission: number;
  commissionAmount: number;
  settledAmount: number;
  feeCount: number;
  period: string;
  paymentPlan: Types.ObjectId[];
  comment: string;
  isThirdParty: boolean;
  beneficiary: {
    name: string;
    identificationType: string;
    identificationNumber: string;
    phone: string;
    bankCode: string;
  };
  status: string;
  expireAt: Date | undefined;
  reference: string;
  createdAt: Date;
  account: {
    bank: {
      name: string;
      code: string;
    };
    type: string;
    number: string;
  };
  banescoVuelto: Types.ObjectId;
  sypagoId: string;
  icon: string;
  laCopaso: string;
  laNumerots: string;
  userAgent: string;
  score: number;
  internalReference: string;
}

/**
 * Cuota de una operación de crédito. Incluye fecha, montos, tasa de interés,
 * estado, método de pago y referencias de LA Sistemas.
 *
 * @export
 * @interface OperationPayment
 * @typedef {OperationPayment}
 * @extends {Document}
 */
export interface OperationPayment extends Document {
  date: Date;
  amountUsd: number;
  amountUsdTotal: number;
  interestRate: number;
  interest: number;
  amountVef: number;
  rate: number;
  status: string;
  paymentMethod?: string;
  paidAt?: Date;
  user?: Types.ObjectId;
  operation?: Types.ObjectId;
  points: number;
  expireAt: Date | undefined;
  laCuota: string;
  laCopaso: string;
  laNupaso: string;
  createdAt: Date;
}

/**
 * Pago realizado por el usuario. Agrupa una o más cuotas de operación
 * con montos en VEF/USD, tipo de pago, puntos y cuenta debitora.
 *
 * @export
 * @interface Payment
 * @typedef {Payment}
 * @extends {Document}
 */
export interface Payment extends Document {
  user: Types.ObjectId;
  operationPayments: [Types.ObjectId];
  laCuotas: [String];
  amountUsd: number;
  amountVef: number;
  rate: number;
  paymentType: string;
  points: number;
  expireAt: Date | undefined;
  status: string;
  errorMessage?: string;
  reference?: string;
  internalReference?: string;
  debitorAccount?: {
    bankCode: string;
    identificationType: string;
    identificationNumber: string;
    phone: string;
  };
}

/**
 * Beneficiario de una operación. Datos de la persona que recibe el crédito
 * cuando es a nombre de un tercero.
 *
 * @export
 * @interface Beneficiary
 * @typedef {Beneficiary}
 * @extends {Document}
 */
export interface Beneficiary extends Document {
  name: string;
  identification: string;
  phone: string;
  bank: Types.ObjectId;
}

/**
 * Nivel del usuario. Define nombre, número de nivel, puntos requeridos,
 * límite de crédito y cantidad de cuotas permitidas.
 *
 * @export
 * @interface Level
 * @typedef {Level}
 * @extends {Document}
 */
export interface Level extends Document {
  name: string;
  level: number;
  pointsRequired: number;
  creditLimit: number;
  allowedFeeCount: [number];
}

/**
 * Historial de cambios de nivel. Registra el nivel anterior, nuevo nivel,
 * puntos al momento del cambio y fecha.
 *
 * @export
 * @interface LevelHistory
 * @typedef {LevelHistory}
 * @extends {Document}
 */
export interface LevelHistory extends Document {
  user: Types.ObjectId;
  oldLevel: number;
  newLevel: number;
  pointsAtChange: number;
  changedAt: Date;
}

/**
 * Suscripción del usuario. Incluye plan, fecha de inicio, número de contrato,
 * estado activo y datos de la transacción de pago.
 *
 * @export
 * @interface Subscription
 * @typedef {Subscription}
 * @extends {Document}
 */
export interface Subscription extends Document {
  user: {
    identificationType: string;
    document: string;
    _id: Types.ObjectId;
  };
  plan: string;
  startDate: Date;
  account: Types.ObjectId;
  contractNumber: string;
  active: boolean;
  transactionId: string;
  transactionRate: number;
  transactionAmount: number;
}

/**
 * Pre-suscripción. Registro previo al registro completo del usuario,
 * con datos bancarios, estado de transacción y flag de consumo.
 *
 * @export
 * @interface PreSubscription
 * @typedef {PreSubscription}
 * @extends {Document}
 */
export interface PreSubscription extends Document {
  identification: string;
  name: string;
  bankCode: string;
  accountNumber: string;
  transactionId: string;
  transactionStatus: string;
  transactionRate: number;
  transactionAmount: number;
  consumed: boolean;
  active: boolean;
}

/**
 * Pago de suscripción. Registro de un cobro de membresía con montos,
 * tasa, fecha de pago, estado y recibo.
 *
 * @export
 * @interface SubscriptionPayment
 * @typedef {SubscriptionPayment}
 * @extends {Document}
 */
export interface SubscriptionPayment extends Document {
  user: Types.ObjectId;
  amountVef: number;
  amountUsd: number;
  rate: number;
  paymentDate: Date;
  status: string;
  details: string;
  account: {
    bank: Types.ObjectId;
    type: string;
    number: string;
  };
  receiptId: string;
}

/**
 * Administrador del sistema. Incluye datos personales, credenciales,
 * roles con módulos asociados, estado y tokens push.
 *
 * @export
 * @interface Admin
 * @typedef {Admin}
 * @extends {Document}
 */
export interface Admin extends Document {
  name: string;
  lastname: string;
  email: string;
  password: string;
  phone: string;
  roles: [
    {
      code: string;
      name: string;
      modules: [
        {
          code: string;
          name: string;
        },
      ];
    },
  ];
  status: string;
  pushToken: string;
  pushTokens: string[];
}

/**
 * Configuración de score crediticio. Define factores con código, nombre,
 * peso (score) y sub-valores porcentuales para cada categoría.
 *
 * @export
 * @interface CreditScore
 * @extends {Document}
 */
export interface CreditScore extends Document {
  code: string;
  name: string;
  score: number;
  items: [
    {
      code: string;
      name: string;
      value: number;
    },
  ];
}

/**
 * Historial de tasas de cambio. Registra fecha, fecha de valor y tasas
 * para USD, RUB, TRY, CNY y EUR.
 *
 * @export
 * @interface RateHistory
 * @extends {Document}
 */
export interface RateHistory extends Document {
  date: Date;
  validDate: Date;
  usd: number;
  rub: number;
  try: number;
  cny: number;
  eur: number;
}

/**
 * Rol del sistema. Define nombre, descripción, código y módulos asociados.
 *
 * @export
 * @interface Role
 * @typedef {Role}
 * @extends {Document}
 */
export interface Role extends Document {
  name: string;
  description: string;
  code: string;
  modules: [
    {
      name: string;
      code: string;
    },
  ];
}

/**
 * Módulo del sistema. Unidad de funcionalidad con nombre y código.
 *
 * @export
 * @interface Module
 * @typedef {Module}
 * @extends {Document}
 */
export interface Module extends Document {
  name: string;
  code: string;
}

/**
 * Registro de balance. Movimiento financiero (ingreso/egreso) en la cuenta
 * operativa con monto, descripción, referencia y estado.
 *
 * @export
 * @interface Balance
 * @typedef {Balance}
 * @extends {Document}
 */
export interface Balance extends Document {
  account: Types.ObjectId;
  isIncome: boolean;
  amount: number;
  description: string;
  category: string;
  reference: string;
  status: "pending" | "confirmed" | "rejected";
  client: string;
}

/**
 * Token de Agile Check. Almacena el token de acceso, tipo, fecha de
 * expiración y duración en segundos.
 *
 * @export
 * @interface AgileCheckToken
 * @typedef {AgileCheckToken}
 * @extends {Document}
 */
export interface AgileCheckToken extends Document {
  accessToken: string;
  tokenType: string;
  expireAt: Date;
  expiresIn: number;
}

/**
 * Configuración del sistema. Almacena pares clave-valor genéricos con
 * descripción y tipo.
 *
 * @interface Config
 * @typedef {Config}
 * @extends {Document}
 */
export interface Config extends Document {
  key: string;
  description: string;
  value: any;
  type: string;
}

/**
 * Vuelto P2P de Banesco. Registra datos del dispositivo, información
 * de la transferencia P2P (cuentas, monto, concepto) y número de referencia.
 *
 * @interface BanescoVuelto
 * @typedef {BanescoVuelto}
 * @extends {Document}
 */
export interface BanescoVuelto extends Document {
  device: {
    type: string;
    description: string;
    ipAddress: string;
    sid: string;
  };
  p2p: {
    accountFrom: {
      accountId: string;
    };
    accountTo: {
      bankId: string;
      customerId: string;
      phoneNum: string;
    };
    amount: number;
    paymentId: string;
    concept: string;
    trnDate: string;
    trnTime: string;
  };
  referenceNumber: string;
}

/**
 * Cargo en Cuenta de Banesco. Representa una transacción de débito directo
 * con datos del dispositivo, información de pago y autorización de seguridad.
 *
 * @export
 * @interface BanescoCargoCuenta
 * @extends {Document}
 */
export interface BanescoCargoCuenta extends Document {
  device: {
    type: string;
    description: string;
    ipAddress: string;
  };
  payment: {
    customerId: string;
    accountDebit: string;
    accountType: string;
    amount: number;
    companyCode: string;
    companyId: string;
    concept: string;
    paymentId: string;
  };
  securityAuth: {
    sessionId: string;
  };
  referenceNumber: string;
}
/**
 * Empresa. Datos de la empresa incluyendo actividad comercial, RIF,
 * datos de contacto y lista de empleados.
 *
 * @export
 * @interface Enterprise
 * @typedef {Enterprise}
 * @extends {Document}
 */
export interface Enterprise extends Document {
  name: string;
  commercialActivity: string;
  website: string;
  email: string;
  rif: string;
  address: string;
  phone: string;
  contactDetails: {
    name: string;
    lastname: string;
    email: string;
    identification: string;
    phone: string;
  };
  employees: string[];
  status: string;
}

/**
 * Transacción de Banesco. Registra referencia, monto, cuenta, fecha/hora,
 * banco origen, concepto, beneficiario y tipo de transacción.
 *
 * @export
 * @interface BanescoTransaction
 * @typedef {BanescoTransaction}
 * @extends {Document}
 */
export interface BanescoTransaction extends Document {
  referenceNumber: string;
  amount: number;
  accountId: string;
  trnDate: string;
  trnTime: string;
  sourceBankId: string;
  concept: string;
  customerIdBen: string;
  trnType: string;
}

/**
 * Lista de Agile Check. Representa una lista de verificación con descripción y valor numérico.
 *
 * @export
 * @interface AgileCheckList
 */
export interface AgileCheckList {
  _id: string;
  description: string;
  value: number;
}

/**
 * Logro del usuario. Define un logro con código, nombre y descripción.
 *
 * @export
 * @interface Achievement
 */
export interface Achievement {
  _id: string;
  code: string;
  name: string;
  description: string;
}

/**
 * Registro de domiciliación de Banesco. Contiene la orden, archivo generado,
 * estado del procesamiento y los pagos asociados.
 *
 * @export
 * @interface BanescoDomiciliation
 */
export interface BanescoDomiciliation {
  orderId: string;
  fileName: string;
  status: string;
  payments: [Types.ObjectId];
}

/**
 * Pregunta frecuente. Contiene la pregunta, respuesta y orden de visualización.
 *
 * @export
 * @interface FrequentQuestion
 */
export interface FrequentQuestion {
  question: string;
  answer: string;
  order: number;
}

/**
 * Transacción de Sypago. Contiene IDs internos, datos del monto, información
 * del usuario receptor, estado y código de rechazo.
 *
 * @export
 * @interface SypagoTransaction
 */
export interface SypagoTransaction {
  internal_id: string;
  transaction_id: string;
  ref_ibp: string;
  group_id: string;
  operation_date: Date;
  amount: {
    type: string;
    amt: number;
    pay_amt: number;
    currency: string;
    rate: number;
  };
  receiving_user: {
    phone: {
      area_code: string;
      number: string;
    };
    email: string;
    otp: string;
    name: string;
    document_info: {
      type: string;
      number: string;
    };
    account: {
      bank_code: string;
      type: string;
      number: string;
    };
  };
  status: string;
  rejected_code: string;
}

/**
 * Pago Móvil de Bancamiga. Registra una transacción de pago móvil con datos
 * del origen, destino, monto, referencia y estado.
 *
 * @export
 * @interface BancamigaPagoMovil
 */
export interface BancamigaPagoMovil {
  ID: string;
  created_at: Date;
  Dni: string;
  PhoneDest: string;
  PhoneOrig: string;
  Amount: number;
  BancoOrig: string;
  NroReferenciaCorto: string;
  NroReferencia: string;
  HoraMovimiento: string;
  FechaMovimiento: string;
  Descripcion: string;
  Status: string;
  Refpk: string;
  Ref: number;
}

/**
 * Body para búsqueda de Pago Móvil en Bancamiga.
 * Incluye teléfono, banco, monto, fecha y referencia.
 *
 * @export
 * @interface BancamigaFindPaymentMobileBody
 */
export interface BancamigaFindPaymentMobileBody {
  phone: string;
  bank: string;
  amount: number;
  date: string;
  reference: string;
}

/**
 * Body para solicitud de OTP en Sypago.
 * Contiene cuentas del acreedor y deudor, documento del deudor y monto.
 *
 * @export
 * @interface SypagoRequestOtpBody
 */
export interface SypagoRequestOtpBody {
  creditor_account: {
    bank_code: string; // Código del banco (4 dígitos)
    type: string; // Tipo de cuenta (ej: CNTA, CELE)
    number: string; // Número de cuenta
  };
  debitor_document_info: {
    type: string; // Tipo de documento (V, E, J, etc.)
    number: string; // Número de documento
  };
  debitor_account: {
    bank_code: string; // Código del banco (4 dígitos)
    type: string; // Tipo de cuenta
    number: string; // Número de cuenta o teléfono
  };
  amount: {
    amt: number; // Monto
    currency: string; // Moneda (VES, USD, etc.)
  };
}

/**
 * Body para débito con OTP en Sypago.
 * Incluye ID interno, cuenta, monto, concepto, webhook y datos del beneficiario con OTP.
 *
 * @export
 * @interface SypagoDebitOtpBody
 */
export interface SypagoDebitOtpBody {
  internal_id: string; // ID interno de la transacción
  group_id?: string; // ID de grupo o lote
  account: {
    bank_code: string; // Código del banco (4 dígitos)
    type: string; // Tipo de cuenta (CNTA, CELE, etc.)
    number: string; // Número de cuenta
  };
  amount: {
    amt: number; // Monto
    currency: string; // Moneda (VES, USD, etc.)
  };
  concept: string; // Descripción o concepto del pago
  notification_urls: {
    web_hook_endpoint: string; // URL para notificaciones
  };
  receiving_user: {
    name: string; // Nombre del beneficiario
    otp: string; // Código OTP
    document_info: {
      type: string; // Tipo de documento (V, E, J, etc.)
      number: string; // Número de documento
    };
    account: {
      bank_code: string; // Código del banco
      type: string; // Tipo de cuenta
      number: string; // Número de cuenta o teléfono
    };
  };
}

/**
 * Body para transacción de domiciliación en Sypago.
 * Incluye ID interno, cuenta, monto, concepto, webhook, datos del beneficiario
 * y datos de domiciliación (contrato y facturas).
 *
 * @export
 * @interface SypagoDomiciliationBody
 */
export interface SypagoDomiciliationBody {
  internal_id: string; // ID interno de la transacción
  group_id?: string; // ID de grupo o lote
  account: {
    bank_code: string; // Código del banco (4 dígitos)
    type: string; // Tipo de cuenta (CNTA, CELE, etc.)
    number: string; // Número de cuenta
  };
  amount: {
    amt: number; // Monto
    currency: string; // Moneda (VES, USD, etc.)
  };
  concept: string; // Descripción o concepto del pago
  notification_urls: {
    web_hook_endpoint: string; // URL para notificaciones
  };
  receiving_user: {
    name: string; // Nombre del beneficiario
    document_info: {
      type: string; // Tipo de documento (V, E, J, etc.)
      number: string; // Número de documento
    };
    account: {
      bank_code: string; // Código del banco
      type: string; // Tipo de cuenta
      number: string; // Número de cuenta o teléfono
    };
  };
  domiciliation_data: {
    contract: {
      id: string;
      related_date: string;
    };
    invoices: [
      {
        id: string;
        related_date: string;
        rejection_date: string;
        amount: {
          amt: number;
          currency: string;
        };
      },
    ];
  };
}

/**
 * Ubicación geográfica (país, estado, municipio o parroquia).
 * Cada nivel referencia al nivel superior mediante `location`.
 *
 * @export
 * @interface Location
 */
export interface Location {
  name: string;
  type: string;
  code: string;
  location: string | Types.ObjectId;
}

/**
 * Dirección del usuario. Referencias a ubicaciones geográficas (país, estado,
 * municipio, parroquia) con descripción adicional opcional.
 *
 * @export
 * @interface Address
 */
export interface Address {
  country: Types.ObjectId;
  state?: Types.ObjectId;
  municipality?: Types.ObjectId;
  parish?: Types.ObjectId;
  description?: string;
}

/**
 * Ocupación del usuario. Incluye nombre y código de LA Sistemas.
 *
 * @export
 * @interface Ocupation
 * @extends {Document}
 */
export interface Ocupation extends Document {
  name: string;
  laCode: string;
}

/**
 * Modelo genérico de LA Sistemas. Representa entidades con nombre, tipo y código.
 *
 * @export
 * @interface LaModel
 * @extends {Document}
 */
export interface LaModel extends Document {
  name: string;
  type: string;
  code: string;
}
