export type TipoDato = "boolean" | "string" | "number" | "json";
export type Ambito = "tenant" | "tienda";
export type ComportamientoAnteFallo = "bloquear" | "permitir";

export interface CatalogoEntrada {
  ambito: Ambito;
  tipo: TipoDato;
  grupo: string;
  etiqueta: string;
  descripcion: string;
  sensible: boolean;
  default?: boolean | string | number;
  // Clave de otra entrada del catalogo, MISMO ambito, cuyo valor booleano
  // en true hace que esta clave sea obligatoria. Ver spec §4.4.
  requeridoSi?: string;
  // Solo relevante para claves booleanas que gatean una accion. Ver spec §4.5.
  comportamientoAnteFallo?: ComportamientoAnteFallo;
  // Encabezado dentro del grupo en la pantalla de configuracion: el grupo
  // "operacion" junta ~20 interruptores y sin subtitulos queda ilegible.
  seccion?: string;
}

export const TALLER_PARAMETROS_CATALOGO = {
  "facturacion.usa_facturacion": {
    ambito: "tenant",
    tipo: "boolean",
    default: false,
    grupo: "facturacion",
    etiqueta: "Usar facturación automática",
    descripcion:
      "Si está apagado, ninguna OT terminada intenta enviarse a POSTouch.",
    sensible: false,
    comportamientoAnteFallo: "bloquear",
  },
  "inventario.usa_validacion": {
    ambito: "tenant",
    tipo: "boolean",
    default: false,
    grupo: "inventario",
    etiqueta: "Validar existencias antes de facturar",
    descripcion:
      "Reservado — hoy no hay ninguna verificación de inventario en el código.",
    sensible: false,
  },
  "productos.permite_crear": {
    ambito: "tenant",
    tipo: "boolean",
    default: false,
    grupo: "productos",
    etiqueta: "Permitir crear productos desde el taller",
    descripcion: "Si está apagado, el catálogo local queda de solo lectura.",
    sensible: false,
    comportamientoAnteFallo: "permitir",
  },
  "tiendas.permite_crear": {
    ambito: "tenant",
    tipo: "boolean",
    default: false,
    grupo: "tiendas",
    etiqueta: "Permitir crear tiendas desde el taller",
    descripcion: "Para tenants sin ERP/POSTouch real detrás.",
    sensible: false,
    comportamientoAnteFallo: "bloquear",
  },
  "ot.usa_fotos": {
    ambito: "tenant",
    tipo: "boolean",
    default: false,
    grupo: "operacion",
    seccion: "Evidencia",
    etiqueta: "Usar fotos de la OT",
    descripcion:
      "Si está apagado, no se pueden agregar ni quitar fotos y se ocultan sus indicadores. Las fotos ya subidas no se borran.",
    sensible: false,
    comportamientoAnteFallo: "permitir",
  },
  "ot.usa_danos": {
    ambito: "tenant",
    tipo: "boolean",
    default: false,
    grupo: "operacion",
    seccion: "Evidencia",
    etiqueta: "Usar registro de daños",
    descripcion:
      "Si está apagado, no se pueden agregar ni quitar daños y se ocultan en listados e impresiones. Los daños ya registrados no se borran.",
    sensible: false,
    comportamientoAnteFallo: "permitir",
  },
  "ot.usa_pdf_escaner": {
    ambito: "tenant",
    tipo: "boolean",
    default: false,
    grupo: "operacion",
    seccion: "Evidencia",
    etiqueta: "Usar PDF de escáner",
    descripcion:
      "Si está apagado, no se puede adjuntar el PDF del escáner a la OT.",
    sensible: false,
    comportamientoAnteFallo: "permitir",
  },
  "ot.usa_cosas_trae": {
    ambito: "tenant",
    tipo: "boolean",
    default: false,
    grupo: "operacion",
    seccion: "Evidencia",
    etiqueta: "Usar campo Cosas que trae",
    descripcion:
      "Si está apagado, el campo de cosas que trae el vehículo no se pide ni se muestra en la recepción.",
    sensible: false,
    comportamientoAnteFallo: "permitir",
  },
  "ot.usa_mecanicos": {
    ambito: "tenant",
    tipo: "boolean",
    default: false,
    grupo: "operacion",
    seccion: "Equipo",
    etiqueta: "Usar mecánicos",
    descripcion:
      "Si está apagado, se oculta el módulo de mecánicos y no se asigna mecánico a la OT ni se menciona en los mensajes al cliente.",
    sensible: false,
    comportamientoAnteFallo: "permitir",
  },
  "ot.usa_firma_cliente": {
    ambito: "tenant",
    tipo: "boolean",
    default: false,
    grupo: "operacion",
    seccion: "Entrega",
    etiqueta: "Usar firma del cliente",
    descripcion:
      "Si está apagado, no se captura la firma del cliente, no se exige para entregar y no aparece en las impresiones.",
    sensible: false,
    comportamientoAnteFallo: "permitir",
  },
  "ot.usa_firma_recepcion": {
    ambito: "tenant",
    tipo: "boolean",
    default: false,
    grupo: "operacion",
    seccion: "Entrega",
    etiqueta: "Usar firma de recepción",
    descripcion:
      "Si está apagado, no se captura la firma de recepción, no se exige y no aparece en las impresiones.",
    sensible: false,
    comportamientoAnteFallo: "permitir",
  },
  "ot.exige_fecha_salida": {
    ambito: "tenant",
    tipo: "boolean",
    default: false,
    grupo: "operacion",
    seccion: "Entrega",
    etiqueta: "Exigir fecha de salida al entregar",
    descripcion:
      "Si está apagado, entregar la OT no pide fecha de salida y se registra la fecha y hora actuales.",
    sensible: false,
    comportamientoAnteFallo: "permitir",
  },
  "ot.una_ot_por_vehiculo": {
    ambito: "tenant",
    tipo: "boolean",
    default: false,
    grupo: "operacion",
    seccion: "Validaciones",
    etiqueta: "Una sola OT abierta por vehículo",
    descripcion:
      "Si está encendido, no se puede abrir una OT nueva para un vehículo que ya tiene una abierta.",
    sensible: false,
    comportamientoAnteFallo: "permitir",
  },
  "cotizacion.bloquea_venta_bajo_costo": {
    ambito: "tenant",
    tipo: "boolean",
    default: false,
    grupo: "operacion",
    seccion: "Validaciones",
    etiqueta: "Bloquear venta bajo costo",
    descripcion:
      "Si está encendido, no se permite guardar una línea de cotización con precio menor al costo.",
    sensible: false,
    comportamientoAnteFallo: "permitir",
  },
  "cotizacion.exige_motivo_cambio": {
    ambito: "tenant",
    tipo: "boolean",
    default: false,
    grupo: "operacion",
    seccion: "Validaciones",
    etiqueta: "Exigir motivo al cambiar cotización",
    descripcion:
      "Si está encendido, editar o borrar líneas de una cotización obliga a escribir el motivo. Apagado, el motivo es opcional.",
    sensible: false,
    comportamientoAnteFallo: "permitir",
  },
  "cotizacion.usa_link_publico": {
    ambito: "tenant",
    tipo: "boolean",
    default: false,
    grupo: "operacion",
    seccion: "Enlaces públicos",
    etiqueta: "Usar enlace público de cotización",
    descripcion:
      "Si está apagado, no se puede generar el enlace para que el cliente vea y apruebe la cotización, ni enviarla por WhatsApp; los enlaces ya enviados dejan de abrir.",
    sensible: false,
    comportamientoAnteFallo: "permitir",
  },
  "ot.usa_estado_publico": {
    ambito: "tenant",
    tipo: "boolean",
    default: false,
    grupo: "operacion",
    seccion: "Enlaces públicos",
    etiqueta: "Usar enlace público de estado",
    descripcion:
      "Si está apagado, el cliente no puede consultar el estado de su OT por enlace ni recibirlo por WhatsApp; los enlaces ya enviados dejan de abrir.",
    sensible: false,
    comportamientoAnteFallo: "permitir",
  },
  "modulos.usa_historial": {
    ambito: "tenant",
    tipo: "boolean",
    default: false,
    grupo: "operacion",
    seccion: "Módulos",
    etiqueta: "Usar módulo Historial",
    descripcion:
      "Si está apagado, se oculta el historial del menú y sus accesos.",
    sensible: false,
    comportamientoAnteFallo: "permitir",
  },
  "modulos.usa_reportes": {
    ambito: "tenant",
    tipo: "boolean",
    default: false,
    grupo: "operacion",
    seccion: "Módulos",
    etiqueta: "Usar módulo Reportes",
    descripcion:
      "Si está apagado, se ocultan los reportes del menú y del panel.",
    sensible: false,
    comportamientoAnteFallo: "permitir",
  },
  "modulos.usa_cargas_masivas": {
    ambito: "tenant",
    tipo: "boolean",
    default: false,
    grupo: "operacion",
    seccion: "Módulos",
    etiqueta: "Usar cargas masivas",
    descripcion:
      "Si está apagado, se ocultan las importaciones masivas y sus plantillas.",
    sensible: false,
    comportamientoAnteFallo: "permitir",
  },
  "modulos.usa_bitacora": {
    ambito: "tenant",
    tipo: "boolean",
    default: false,
    grupo: "operacion",
    seccion: "Módulos",
    etiqueta: "Mostrar bitácora de la OT",
    descripcion:
      "Si está apagado, se oculta la bitácora de cada OT. Los eventos se siguen registrando.",
    sensible: false,
    comportamientoAnteFallo: "permitir",
  },
  "impresion.recepcion": {
    ambito: "tenant",
    tipo: "boolean",
    default: false,
    grupo: "operacion",
    seccion: "Impresiones",
    etiqueta: "Imprimir hoja de recepción",
    descripcion:
      "Si está apagado, se ocultan los botones y la ruta de impresión de la recepción.",
    sensible: false,
    comportamientoAnteFallo: "permitir",
  },
  "impresion.cotizacion": {
    ambito: "tenant",
    tipo: "boolean",
    default: false,
    grupo: "operacion",
    seccion: "Impresiones",
    etiqueta: "Imprimir cotización",
    descripcion:
      "Si está apagado, se ocultan los botones y la ruta de impresión de la cotización.",
    sensible: false,
    comportamientoAnteFallo: "permitir",
  },
  "impresion.entrega": {
    ambito: "tenant",
    tipo: "boolean",
    default: false,
    grupo: "operacion",
    seccion: "Impresiones",
    etiqueta: "Imprimir comprobante de entrega",
    descripcion:
      "Si está apagado, se ocultan los botones y la ruta de impresión del comprobante de entrega.",
    sensible: false,
    comportamientoAnteFallo: "permitir",
  },
  "impresion.orden_interna": {
    ambito: "tenant",
    tipo: "boolean",
    default: false,
    grupo: "operacion",
    seccion: "Impresiones",
    etiqueta: "Imprimir orden interna",
    descripcion:
      "Si está apagado, se ocultan los botones y la ruta de impresión de la orden interna.",
    sensible: false,
    comportamientoAnteFallo: "permitir",
  },
  "facturacion.exige_pago_para_entrega": {
    ambito: "tenant",
    tipo: "boolean",
    default: true,
    grupo: "facturacion",
    etiqueta: "Exigir pago confirmado para entregar",
    descripcion:
      "Solo actúa si la facturación aplica a la OT: una OT facturada no se entrega hasta confirmar su pago.",
    sensible: false,
    comportamientoAnteFallo: "permitir",
  },
  "notificaciones.usa_whatsapp": {
    ambito: "tenant",
    tipo: "boolean",
    default: false,
    grupo: "notificaciones",
    etiqueta: "Enviar notificaciones por WhatsApp",
    descripcion:
      "Si está apagado, los demás campos de WhatsApp no se piden ni se muestran.",
    sensible: false,
    comportamientoAnteFallo: "bloquear",
  },
  "notificaciones.whatsapp_phone_number_id": {
    ambito: "tenant",
    tipo: "string",
    grupo: "notificaciones",
    sensible: false,
    etiqueta: "Phone Number ID",
    descripcion: "ID del número de WhatsApp Business en Meta.",
    requeridoSi: "notificaciones.usa_whatsapp",
  },
  "notificaciones.whatsapp_access_token": {
    ambito: "tenant",
    tipo: "string",
    grupo: "notificaciones",
    sensible: true,
    etiqueta: "Access Token",
    descripcion: "Token de acceso de la app de Meta. Se guarda cifrado.",
    requeridoSi: "notificaciones.usa_whatsapp",
  },
  "notificaciones.whatsapp_api_version": {
    ambito: "tenant",
    tipo: "string",
    grupo: "notificaciones",
    sensible: false,
    default: "v25.0",
    etiqueta: "Versión de API",
    descripcion: "Versión de Graph API de Meta a usar.",
  },
  "notificaciones.whatsapp_template_cotizacion": {
    ambito: "tenant",
    tipo: "string",
    grupo: "notificaciones",
    sensible: false,
    etiqueta: "Plantilla de cotización",
    descripcion:
      "Nombre de plantilla aprobada en Meta. Vacío = envía texto libre.",
  },
  "notificaciones.whatsapp_template_estado": {
    ambito: "tenant",
    tipo: "string",
    grupo: "notificaciones",
    sensible: false,
    etiqueta: "Plantilla de estado de OT",
    descripcion:
      "Nombre de plantilla aprobada en Meta. Vacío = envía texto libre.",
  },
  "notificaciones.whatsapp_template_language": {
    ambito: "tenant",
    tipo: "string",
    grupo: "notificaciones",
    sensible: false,
    default: "es_GT",
    etiqueta: "Idioma de plantilla",
    descripcion: "Código de idioma de las plantillas de Meta.",
  },
  "notificaciones.whatsapp_default_country_code": {
    ambito: "tenant",
    tipo: "string",
    grupo: "notificaciones",
    sensible: false,
    default: "502",
    etiqueta: "Código de país por defecto",
    descripcion: "Se antepone a números locales de 8 dígitos.",
  },
  "facturacion_pos.habilitada": {
    ambito: "tienda",
    tipo: "boolean",
    default: false,
    grupo: "facturacion",
    etiqueta: "Facturación POS habilitada",
    descripcion:
      "Envía automáticamente cada OT terminada de esta tienda a POSTouch.",
    sensible: false,
  },
  "facturacion_pos.url": {
    ambito: "tienda",
    tipo: "string",
    grupo: "facturacion",
    sensible: false,
    etiqueta: "URL de POSTouch",
    descripcion: "Endpoint create_ordenes_edngt de esta tienda.",
    requeridoSi: "facturacion_pos.habilitada",
  },
  "facturacion_pos.username": {
    ambito: "tienda",
    tipo: "string",
    grupo: "facturacion",
    sensible: false,
    etiqueta: "Usuario de servicio",
    descripcion: "Usuario de POSTouch para esta tienda.",
    requeridoSi: "facturacion_pos.habilitada",
  },
  "facturacion_pos.password": {
    ambito: "tienda",
    tipo: "string",
    grupo: "facturacion",
    sensible: true,
    etiqueta: "Contraseña de servicio",
    descripcion: "Se guarda cifrada. Vacío al guardar = no cambiar.",
    requeridoSi: "facturacion_pos.habilitada",
  },
  "facturacion_pos.computadora": {
    ambito: "tienda",
    tipo: "string",
    grupo: "facturacion",
    sensible: false,
    etiqueta: "Computadora",
    descripcion: "Identificador de tienda/caja en POSTouch.",
    requeridoSi: "facturacion_pos.habilitada",
  },
  "facturacion_pos.precio_incluye_iva": {
    ambito: "tienda",
    tipo: "boolean",
    default: true,
    grupo: "facturacion",
    sensible: false,
    etiqueta: "El precio enviado a POSTouch incluye IVA",
    descripcion:
      "Encendido: cada línea se envía con el precio final con IVA. Apagado: con el precio base sin IVA. Confirmar contra el sandbox de POSTouch.",
  },
  "facturacion_pos.plu_productos_taller": {
    ambito: "tienda",
    tipo: "string",
    grupo: "facturacion",
    sensible: false,
    default: "TALLER-PROD",
    etiqueta: "PLU genérico de productos del taller",
    descripcion:
      "PLU del ERP bajo el que se facturan los productos creados en el taller (TLLP-). Se crea solo al preparar el sitio. Si se deja vacío, una OT con productos creados en el taller no se puede facturar.",
  },
  "facturacion_pos.plu_servicios_taller": {
    ambito: "tienda",
    tipo: "string",
    grupo: "facturacion",
    sensible: false,
    default: "TALLER-SERV",
    etiqueta: "PLU genérico de servicios del taller",
    descripcion:
      "PLU del ERP bajo el que se facturan los servicios creados en el taller (MANUAL- y TLLP- de servicio). Se crea solo al preparar el sitio. Si se deja vacío, una OT con servicios creados en el taller no se puede facturar.",
  },
  "facturacion_pos.precio_decimales": {
    ambito: "tienda",
    tipo: "number",
    grupo: "facturacion",
    sensible: false,
    etiqueta: "Decimales de precio",
    descripcion:
      "Decimales de redondeo configurados en POSTouch para esta tienda (ParametrosGlobales).",
    requeridoSi: "facturacion_pos.habilitada",
  },
} as const satisfies Record<string, CatalogoEntrada>;

export type TallerParametroClave = keyof typeof TALLER_PARAMETROS_CATALOGO;

// Flag camelCase que consume el frontend -> clave del catalogo. Unica fuente
// para getFlags() y su tipo: agregar un interruptor es una linea aqui y no
// una linea mas en cada capa. Los 4 primeros existian antes del grupo
// "operacion".
export const FLAGS_UI = {
  usaFacturacion: "facturacion.usa_facturacion",
  permiteTiendas: "tiendas.permite_crear",
  permiteProductosPropios: "productos.permite_crear",
  usaWhatsapp: "notificaciones.usa_whatsapp",
  usaFotos: "ot.usa_fotos",
  usaDanos: "ot.usa_danos",
  usaPdfEscaner: "ot.usa_pdf_escaner",
  usaCosasTrae: "ot.usa_cosas_trae",
  usaMecanicos: "ot.usa_mecanicos",
  usaFirmaCliente: "ot.usa_firma_cliente",
  usaFirmaRecepcion: "ot.usa_firma_recepcion",
  exigeFechaSalida: "ot.exige_fecha_salida",
  unaOtPorVehiculo: "ot.una_ot_por_vehiculo",
  bloqueaVentaBajoCosto: "cotizacion.bloquea_venta_bajo_costo",
  exigeMotivoCambio: "cotizacion.exige_motivo_cambio",
  usaLinkPublicoCotizacion: "cotizacion.usa_link_publico",
  usaEstadoPublico: "ot.usa_estado_publico",
  usaHistorial: "modulos.usa_historial",
  usaReportes: "modulos.usa_reportes",
  usaCargasMasivas: "modulos.usa_cargas_masivas",
  usaBitacora: "modulos.usa_bitacora",
  imprimeRecepcion: "impresion.recepcion",
  imprimeCotizacion: "impresion.cotizacion",
  imprimeEntrega: "impresion.entrega",
  imprimeOrdenInterna: "impresion.orden_interna",
  exigePagoParaEntrega: "facturacion.exige_pago_para_entrega",
} as const satisfies Record<string, TallerParametroClave>;

export type FlagUI = keyof typeof FLAGS_UI;

type TipoTS<T extends TipoDato> = T extends "boolean"
  ? boolean
  : T extends "number"
    ? number
    : T extends "json"
      ? Record<string, unknown>
      : string;

export type ValorDe<K extends TallerParametroClave> = TipoTS<
  (typeof TALLER_PARAMETROS_CATALOGO)[K]["tipo"]
>;

export function entradaDe(clave: TallerParametroClave): CatalogoEntrada {
  return TALLER_PARAMETROS_CATALOGO[clave];
}

export function clavesDelCatalogo(): TallerParametroClave[] {
  return Object.keys(TALLER_PARAMETROS_CATALOGO) as TallerParametroClave[];
}

export function clavesPorAmbito(ambito: Ambito): TallerParametroClave[] {
  return clavesDelCatalogo().filter(
    (c) => TALLER_PARAMETROS_CATALOGO[c].ambito === ambito,
  );
}
