<template>
  <div v-if="aberto" class="eli-tabela-modal-filtro__overlay" role="presentation" @click.self="emitFechar">
    <div class="eli-tabela-modal-filtro__modal" role="dialog" aria-modal="true" aria-label="Filtro avançado">
      <header class="eli-tabela-modal-filtro__header">
        <h3 class="eli-tabela-modal-filtro__titulo">Filtro avançado</h3>
        <button type="button" class="eli-tabela-modal-filtro__fechar" aria-label="Fechar" @click="emitFechar">
          ×
        </button>
      </header>

      <div class="eli-tabela-modal-filtro__conteudo">
        <div v-if="!filtrosBase.length" class="eli-tabela-modal-filtro__vazio">
          Nenhum filtro configurado na tabela.
        </div>

        <div v-else class="eli-tabela-modal-filtro__lista">
          <div v-for="(linha, idx) in linhas" :key="String(linha.coluna)" class="eli-tabela-modal-filtro__linha">
            <div class="eli-tabela-modal-filtro__entrada">
              <component
                :is="componenteEntrada(linha.entrada)"
                v-model:value="linha.valor"
                :opcoes="opcoesEntrada(linha.entrada)"
                density="compact"
              />
            </div>

            <button
              type="button"
              class="eli-tabela-modal-filtro__remover"
              title="Remover"
              aria-label="Remover"
              @click="remover(idx)"
            >
              ×
            </button>
          </div>
        </div>

        <div class="eli-tabela-modal-filtro__acoes">
          <select v-model="colunaParaAdicionar" class="eli-tabela-modal-filtro__select" :disabled="!opcoesParaAdicionar.length">
            <option disabled value="">Selecione um filtro…</option>
            <option v-for="o in opcoesParaAdicionar" :key="String(o.coluna)" :value="String(o.coluna)">
              {{ rotuloDoFiltro(o) }}
            </option>
          </select>
          <button
            type="button"
            class="eli-tabela-modal-filtro__botao"
            @click="adicionar"
            :disabled="!colunaParaAdicionar"
          >
            Adicionar
          </button>
        </div>
      </div>

      <footer class="eli-tabela-modal-filtro__footer">
        <button type="button" class="eli-tabela-modal-filtro__botao eli-tabela-modal-filtro__botao--sec" @click="emitLimpar">
          Limpar
        </button>
        <button type="button" class="eli-tabela-modal-filtro__botao eli-tabela-modal-filtro__botao--sec" @click="emitFechar">
          Cancelar
        </button>
        <button type="button" class="eli-tabela-modal-filtro__botao eli-tabela-modal-filtro__botao--prim" @click="emitSalvar">
          Aplicar
        </button>
      </footer>
    </div>
  </div>
</template>

<script lang="ts">
import { computed, defineComponent, PropType, ref, watch } from "vue";
import { EliEntradaTexto, EliEntradaNumero, EliEntradaDataHora } from "../EliEntrada";
import type { ComponenteEntrada, TipoEntrada } from "../EliEntrada/tiposEntradas";
import type { EliTabelaConsulta } from "./types-eli-tabela";

type FiltroBase<T> = NonNullable<EliTabelaConsulta<T>["filtroAvancado"]>[number];

type LinhaFiltro<T> = {
  coluna: keyof T;
  entrada: ComponenteEntrada;
  operador: string;
  valor: any;
};

function isTipoEntrada(v: unknown): v is TipoEntrada {
  return v === "texto" || v === "numero" || v === "dataHora";
}

function rotuloDoFiltro(f: FiltroBase<any>) {
  const rotulo = (f?.entrada?.[1] as any)?.rotulo;
  return rotulo ? String(rotulo) : String(f?.coluna ?? "Filtro");
}

export default defineComponent({
  name: "EliTabelaModalFiltroAvancado",
  props: {
    aberto: { type: Boolean, required: true },
    filtrosBase: {
      type: Array as PropType<Array<FiltroBase<any>>>,
      required: true,
    },
    modelo: {
      type: Array as PropType<Array<any>>,
      required: true,
    },
  },
  emits: {
    fechar: () => true,
    limpar: () => true,
    salvar: (_linhas: any[]) => true,
  },
  setup(props, { emit }) {
    const linhas = ref<Array<LinhaFiltro<any>>>([]);

    const colunaParaAdicionar = ref<string>("");

    const colunasDisponiveis = computed(() => (props.filtrosBase ?? []).map((b) => String(b.coluna)));

    const opcoesParaAdicionar = computed(() => {
      const usadas = new Set(linhas.value.map((l) => String(l.coluna)));
      return (props.filtrosBase ?? []).filter((b) => !usadas.has(String(b.coluna)));
    });

    function componenteEntrada(entrada: ComponenteEntrada) {
      const tipo = entrada?.[0];
      if (tipo === "numero") return EliEntradaNumero;
      if (tipo === "dataHora") return EliEntradaDataHora;
      return EliEntradaTexto;
    }

    function opcoesEntrada(entrada: ComponenteEntrada) {
      // o rótulo vem do próprio componente (entrada[1].rotulo)
      return (entrada?.[1] as any) ?? { rotulo: "" };
    }

    function valorInicialPorEntrada(entrada: ComponenteEntrada) {
      const tipo = entrada?.[0];
      if (tipo === "numero") return null;
      return "";
    }

    function normalizarModelo() {
      const base = props.filtrosBase ?? [];
      const modelo = Array.isArray(props.modelo) ? props.modelo : [];
      linhas.value = modelo.map((m: any) => {
        // operador vem travado no base
        const baseItem = base.find((b) => String(b.coluna) === String(m.coluna)) ?? base[0];
        const entrada = (baseItem?.entrada ?? m.entrada) as ComponenteEntrada;
        const col = (baseItem?.coluna ?? m.coluna) as any;
        const op = String(baseItem?.operador ?? "=");
        const val = m.valor ?? valorInicialPorEntrada(entrada);

        return {
          coluna: col,
          operador: op,
          entrada,
          valor: val,
        } as LinhaFiltro<any>;
      });

      // se vazio e existe base, adiciona 1 linha default
      // não auto-adiciona; usuário escolhe quais filtros quer usar

      // se algum filtro mudou a coluna para valor inválido, ajusta
      for (const l of linhas.value) {
        if (!colunasDisponiveis.value.includes(String(l.coluna))) continue;
        l.operador = String((base.find((b) => String(b.coluna) === String(l.coluna))?.operador ?? "="));
        // sanity
        if (l.entrada && !isTipoEntrada(l.entrada[0])) {
          l.entrada = ["texto", { rotulo: "Valor" }] as any;
        }
      }
    }

    watch(
      () => [props.aberto, props.filtrosBase, props.modelo] as const,
      () => {
        if (props.aberto) normalizarModelo();
      },
      { deep: true, immediate: true }
    );

    function adicionar() {
      if (!colunaParaAdicionar.value) return;
      const b0 = (props.filtrosBase ?? []).find((b) => String(b.coluna) === String(colunaParaAdicionar.value));
      if (!b0) return;
      // evita repetição
      if (linhas.value.some((l) => String(l.coluna) === String(b0.coluna))) return;

      linhas.value.push({
        coluna: b0.coluna as any,
        entrada: b0.entrada,
        operador: String(b0.operador ?? "="),
        valor: valorInicialPorEntrada(b0.entrada),
      });

      colunaParaAdicionar.value = "";
    }

    function remover(idx: number) {
      linhas.value.splice(idx, 1);
    }

    function emitFechar() {
      emit("fechar");
    }

    function emitLimpar() {
      emit("limpar");
    }

    function emitSalvar() {
      emit(
        "salvar",
        linhas.value.map((l) => ({
          coluna: l.coluna,
          valor: l.valor,
        }))
      );
    }

    return {
      linhas,
      opcoesParaAdicionar,
      colunaParaAdicionar,
      componenteEntrada,
      opcoesEntrada,
      adicionar,
      remover,
      // exibimos operador fixo só como texto
      emitFechar,
      emitSalvar,
      emitLimpar,
      rotuloDoFiltro,
    };
  },
});
</script>

<style scoped>
.eli-tabela-modal-filtro__overlay {
  position: fixed;
  inset: 0;
  background: rgba(15, 23, 42, 0.35);
  z-index: 4000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
}

.eli-tabela-modal-filtro__modal {
  width: min(980px, 100%);
  background: #fff;
  border-radius: 14px;
  border: 1px solid rgba(15, 23, 42, 0.1);
  box-shadow: 0 18px 60px rgba(15, 23, 42, 0.25);
  overflow: hidden;
}

.eli-tabela-modal-filtro__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 16px;
  border-bottom: 1px solid rgba(15, 23, 42, 0.08);
}

.eli-tabela-modal-filtro__titulo {
  font-size: 1rem;
  margin: 0;
}

.eli-tabela-modal-filtro__fechar {
  width: 34px;
  height: 34px;
  border-radius: 10px;
  border: none;
  background: transparent;
  cursor: pointer;
  font-size: 22px;
  line-height: 1;
  color: rgba(15, 23, 42, 0.8);
}

.eli-tabela-modal-filtro__fechar:hover,
.eli-tabela-modal-filtro__fechar:focus-visible {
  background: rgba(15, 23, 42, 0.06);
}

.eli-tabela-modal-filtro__conteudo {
  padding: 16px;
}

.eli-tabela-modal-filtro__vazio {
  opacity: 0.75;
  font-size: 0.9rem;
}

.eli-tabela-modal-filtro__lista {
  display: grid;
  gap: 10px;
}

.eli-tabela-modal-filtro__linha {
  display: grid;
  grid-template-columns: 1fr 34px;
  gap: 10px;
  align-items: center;
}

.eli-tabela-modal-filtro__select {
  height: 34px;
  border-radius: 10px;
  border: 1px solid rgba(15, 23, 42, 0.12);
  padding: 0 10px;
  background: #fff;
}

.eli-tabela-modal-filtro__entrada {
  min-width: 0;
}

.eli-tabela-modal-filtro__remover {
  width: 34px;
  height: 34px;
  border-radius: 10px;
  border: 1px solid rgba(15, 23, 42, 0.12);
  background: #fff;
  cursor: pointer;
  font-size: 18px;
  line-height: 1;
  color: rgba(15, 23, 42, 0.8);
}

.eli-tabela-modal-filtro__remover:hover,
.eli-tabela-modal-filtro__remover:focus-visible {
  background: rgba(15, 23, 42, 0.06);
}

.eli-tabela-modal-filtro__acoes {
  margin-top: 12px;
}

.eli-tabela-modal-filtro__footer {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  padding: 14px 16px;
  border-top: 1px solid rgba(15, 23, 42, 0.08);
}

.eli-tabela-modal-filtro__botao {
  height: 34px;
  padding: 0 14px;
  border-radius: 10px;
  border: 1px solid rgba(15, 23, 42, 0.12);
  background: #fff;
  cursor: pointer;
  font-size: 0.9rem;
}

.eli-tabela-modal-filtro__botao:disabled {
  opacity: 0.55;
  cursor: not-allowed;
}

.eli-tabela-modal-filtro__botao--sec:hover,
.eli-tabela-modal-filtro__botao--sec:focus-visible {
  background: rgba(15, 23, 42, 0.06);
}

.eli-tabela-modal-filtro__botao--prim {
  border: none;
  background: rgba(37, 99, 235, 0.95);
  color: #fff;
}

.eli-tabela-modal-filtro__botao--prim:hover,
.eli-tabela-modal-filtro__botao--prim:focus-visible {
  background: rgba(37, 99, 235, 1);
}

@media (max-width: 880px) {
  .eli-tabela-modal-filtro__linha {
    grid-template-columns: 1fr;
  }
}
</style>
