/* Copyright (c) 2026 RAVAPI Soluções. www.ravapi.com */

export class ErroDeNegocio extends Error {
  constructor(message: string, readonly codigo: string, readonly status = 400) {
    super(message);
    this.name = new.target.name;
  }
}

export class TenantAusente extends ErroDeNegocio {
  constructor() {
    super(
      'Nenhum tenant no contexto da requisição. Sem ele as políticas de RLS não ' +
        'casam com nada e a consulta voltaria vazia em silêncio — o que pareceria ' +
        '"não tem dados" em vez de erro.',
      'TENANT_AUSENTE',
      500,
    );
  }
}

export class SemPermissao extends ErroDeNegocio {
  constructor(acao: string, detalhe?: string) {
    super(detalhe ?? `Sem permissão para ${acao}.`, 'SEM_PERMISSAO', 403);
  }
}

export class LicencaBloqueada extends ErroDeNegocio {
  constructor() {
    super(
      'A licença está suspensa e a tolerância venceu, então não é possível selar ' +
        'recibo novo. Leitura, impressão, reimpressão e exportação continuam liberadas.',
      'LICENCA_BLOQUEADA',
      402,
    );
  }
}

export class LimiteDoPlano extends ErroDeNegocio {
  constructor(recurso: string, limite: number) {
    super(`O plano contratado permite ${limite} ${recurso}. Limite atingido.`, 'LIMITE_DO_PLANO', 402);
  }
}

export class NaoEncontrado extends ErroDeNegocio {
  constructor(o: string) { super(`${o} não encontrado neste tenant.`, 'NAO_ENCONTRADO', 404); }
}

export class DadosInvalidos extends ErroDeNegocio {
  constructor(m: string) { super(m, 'DADOS_INVALIDOS', 422); }
}

export class MuitasRequisicoes extends ErroDeNegocio {
  constructor() {
    super('Muitas verificações em pouco tempo. Tente novamente em instantes.', 'MUITAS_REQUISICOES', 429);
  }
}

export class CredenciaisInvalidas extends ErroDeNegocio {
  constructor() {
    // Mensagem genérica de propósito: não diz se o e-mail existe. Diferenciar
    // "senha errada" de "e-mail não cadastrado" é como se descobre quem tem
    // conta, um e-mail de cada vez.
    super('E-mail ou senha incorretos.', 'CREDENCIAIS_INVALIDAS', 401);
  }
}

export class SessaoInvalida extends ErroDeNegocio {
  constructor(motivo: 'assinatura' | 'expirada' | 'formato') {
    const msg = motivo === 'expirada'
      ? 'Sessão expirada. Entre novamente.'
      : 'Sessão inválida. Entre novamente.';
    super(msg, 'SESSAO_INVALIDA', 401);
  }
}
