﻿import * as kv from "./kv_store.tsx";
import { createClient } from "../../src/compat/supabase.js";
import { createLogger } from "./logger.tsx";

const logger = createLogger('Usuarios');

// ========== TIPOS ==========

export type NivelUsuario = "super_admin" | "admin_empresa" | "usuario";

// ? CORREÇÃO CRÍTICA: Importar permissões padrão do sistema de permissões
// Isso garante que novos usuários sejam criados com permissões inicializadas
interface Permissoes {
  concederPermissoes: boolean;
  visualizarLogs: boolean;
  gerenciarUsuarios: boolean;
  exportarSAFT: boolean;
  configurarEmpresa: boolean;
}

// Permissões padrão por nível (sincronizado com permissoes.tsx)
const PERMISSOES_SUPER_ADMIN: Permissoes = {
  concederPermissoes: true,
  visualizarLogs: true,
  gerenciarUsuarios: true,
  exportarSAFT: true,
  configurarEmpresa: true,
};

const PERMISSOES_ADMIN: Permissoes = {
  concederPermissoes: true,
  visualizarLogs: true,
  gerenciarUsuarios: true,
  exportarSAFT: true,
  configurarEmpresa: true,
};

const PERMISSOES_USUARIO: Permissoes = {
  concederPermissoes: false,
  visualizarLogs: false,
  gerenciarUsuarios: false,
  exportarSAFT: false,
  configurarEmpresa: false,
};

export interface Usuario {
  id: string;
  authUserId?: string;
  email: string;
  nome: string;
  empresaId: string;
  nivel: NivelUsuario;
  modulosPermitidos: string[]; // IDs dos módulos que o usuário pode acessar
  permissoes?: Permissoes; // ? NOVO: Permissões do sistema
  ativo: boolean;
  dataCriacao: string;
  ultimoAcesso?: string;
}


function normalizarCodigoSupervisor(codigo?: string): string | undefined {
  const valor = codigo?.trim().toUpperCase();
  return valor ? valor : undefined;
}

function supabaseAdminClient() {
  return createClient(
    Deno.env.get("SUPABASE_URL") ?? "",
    Deno.env.get("SUPABASE_SERVICE_ROLE_KEY") ?? ""
  );
}

async function buscarAuthUserPorEmail(email: string): Promise<any | null> {
  const supabase = supabaseAdminClient();
  const emailNormalizado = String(email || "").trim().toLowerCase();
  let page = 1;

  while (page <= 20) {
    const { data, error } = await supabase.auth.admin.listUsers({ page, perPage: 100 });
    if (error) {
      throw error;
    }

    const encontrado = data.users.find((user: any) =>
      String(user.email || "").trim().toLowerCase() === emailNormalizado
    );
    if (encontrado) {
      return encontrado;
    }

    if (!data.users.length || data.users.length < 100) {
      return null;
    }

    page += 1;
  }

  return null;
}

// ========== FUNÇÕES DE GESTÃO DE USUÁRIOS ==========

/**
 * Criar novo usuário vinculado a uma empresa
 */
export async function criarUsuario(dados: {
  email: string;
  password: string; // NOVO: Senha obrigatória
  nome: string;
  empresaId: string;
  nivel: NivelUsuario;
  modulosPermitidos?: string[];
}): Promise<{ success: boolean; data?: Usuario; error?: string }> {
  try {
    const emailNormalizado = String(dados.email || "").trim().toLowerCase();

    // Validar dados obrigatórios
    if (!emailNormalizado || !dados.password || !dados.nome || !dados.empresaId || !dados.nivel) {
      return { success: false, error: "Dados obrigatórios faltando" };
    }

    // Validar senha
    if (dados.password.length < 6) {
      return { success: false, error: "Senha deve ter pelo menos 6 caracteres" };
    }

    // Verificar se usuário já existe
    const usuarioExistente = await buscarUsuarioPorEmail(emailNormalizado);
    if (usuarioExistente) {
      return { success: false, error: "Email já cadastrado no sistema" };
    }

    // Verificar se empresa existe
    const empresa = await kv.get(`empresa:${dados.empresaId}`);
    if (!empresa) {
      return { success: false, error: "Empresa não encontrada" };
    }

    // NOVO: Criar usuário no Supabase Auth
    const supabase = supabaseAdminClient();

    let { data: authData, error: authError } = await supabase.auth.admin.createUser({
      email: emailNormalizado,
      password: dados.password,
      email_confirm: true, // Confirmar automaticamente já que não temos servidor de email configurado
      user_metadata: {
        nome: dados.nome,
        empresaId: dados.empresaId,
        nivel: dados.nivel,
      },
    });

    if (authError) {
      const mensagem = String(authError.message || "").toLowerCase();
      if (!mensagem.includes("already") && !mensagem.includes("registered") && !mensagem.includes("exists")) {
        return { success: false, error: `Erro ao criar autenticacao: ${authError.message}` };
      }

      const authUserExistente = await buscarAuthUserPorEmail(emailNormalizado);
      if (!authUserExistente) {
        return { success: false, error: `Erro ao localizar autenticacao existente: ${authError.message}` };
      }

      const { data: authAtualizado, error: updateAuthError } = await supabase.auth.admin.updateUserById(
        authUserExistente.id,
        {
          email: emailNormalizado,
          password: dados.password,
          email_confirm: true,
          user_metadata: {
            nome: dados.nome,
            empresaId: dados.empresaId,
            nivel: dados.nivel,
          },
        },
      );

      if (updateAuthError) {
        return { success: false, error: `Erro ao actualizar autenticacao: ${updateAuthError.message}` };
      }

      authData = authAtualizado;
    }

    const usuarioId = authData.user.id; // Usar o ID do Supabase Auth
    
    // ? CORREÇÃO CRÍTICA: Inicializar permissões baseadas no nível
    let permissoesIniciais: Permissoes;
    switch (dados.nivel) {
      case 'super_admin':
        permissoesIniciais = { ...PERMISSOES_SUPER_ADMIN };
        break;
      case 'admin_empresa':
        permissoesIniciais = { ...PERMISSOES_ADMIN };
        break;
      case 'usuario':
      default:
        permissoesIniciais = { ...PERMISSOES_USUARIO };
        break;
    }
    
    const usuario: Usuario = {
      id: usuarioId,
      authUserId: usuarioId,
      email: emailNormalizado,
      nome: dados.nome,
      empresaId: dados.empresaId,
      nivel: dados.nivel,
      modulosPermitidos: dados.modulosPermitidos || [],
      permissoes: permissoesIniciais, // ? NOVO: Permissões inicializadas
      ativo: true,
      dataCriacao: new Date().toISOString(),
    };

    // Salvar usuário no KV
    await kv.set(`usuario:${usuarioId}`, usuario);
    
    // Indexar por email para busca rápida
    await kv.set(`usuario:email:${emailNormalizado}`, usuarioId);

    logger.info(`Usuário criado: ${emailNormalizado} (${dados.nivel}) - Empresa: ${dados.empresaId}`);
    logger.info(`Permissões inicializadas:`, permissoesIniciais);

    return { success: true, data: usuario };
  } catch (error) {
    // console.error("[Usuarios] Erro ao criar usuário:", error);
    return { success: false, error: error.message };
  }
}

/**
 * Buscar usuário por email
 */
export async function buscarUsuarioPorEmail(email: string): Promise<Usuario | null> {
  try {
    const emailNormalizado = String(email || "").trim().toLowerCase();
    if (!emailNormalizado) return null;

    let usuarioId = await kv.get(`usuario:email:${emailNormalizado}`);
    if (!usuarioId && email !== emailNormalizado) {
      usuarioId = await kv.get(`usuario:email:${email}`);
    }
    if (!usuarioId) return null;

    const usuario = await kv.get(`usuario:${usuarioId}`);
    return usuario as Usuario | null;
  } catch (error) {
    // console.error("[Usuarios] Erro ao buscar usuário por email:", error);
    return null;
  }
}

/**
 * Buscar usuário por ID
 */
export async function buscarUsuarioPorId(id: string): Promise<Usuario | null> {
  try {
    const usuario = await kv.get(`usuario:${id}`);
    return usuario as Usuario | null;
  } catch (error) {
    // console.error("[Usuarios] Erro ao buscar usuário por ID:", error);
    return null;
  }
}

export async function redefinirSenhaUsuarioPorEmail(
  email: string,
  password: string,
): Promise<{ success: boolean; data?: Usuario; error?: string }> {
  try {
    const emailNormalizado = String(email || "").trim().toLowerCase();
    if (!emailNormalizado || !password || password.length < 6) {
      return { success: false, error: "Email ou senha invalida" };
    }

    const usuario = await buscarUsuarioPorEmail(emailNormalizado);
    const authUser =
      (usuario?.authUserId || usuario?.id
        ? await buscarAuthUserPorEmail(emailNormalizado)
        : null) || await buscarAuthUserPorEmail(emailNormalizado);

    if (!authUser) {
      return { success: false, error: "Utilizador nao encontrado no Supabase Auth" };
    }

    const supabase = supabaseAdminClient();
    const { error } = await supabase.auth.admin.updateUserById(authUser.id, {
      password,
      email_confirm: true,
      user_metadata: {
        ...(authUser.user_metadata || {}),
        nome: usuario?.nome || authUser.user_metadata?.nome,
        empresaId: usuario?.empresaId || authUser.user_metadata?.empresaId,
        nivel: usuario?.nivel || authUser.user_metadata?.nivel,
      },
    });

    if (error) {
      return { success: false, error: `Erro ao actualizar senha: ${error.message}` };
    }

    if (usuario && usuario.authUserId !== authUser.id) {
      usuario.authUserId = authUser.id;
      usuario.id = authUser.id;
      usuario.email = emailNormalizado;
      await kv.set(`usuario:${authUser.id}`, usuario);
      await kv.set(`usuario:email:${emailNormalizado}`, authUser.id);
    }

    return { success: true, data: usuario || undefined };
  } catch (error: any) {
    return { success: false, error: error?.message || String(error) };
  }
}

/**
 * Listar usuários de uma empresa
 */
export async function listarUsuariosEmpresa(empresaId: string): Promise<Usuario[]> {
  try {
    const todosUsuarios = await kv.getByPrefixWithKeys("usuario:");
    
    const usuarios = todosUsuarios
      .filter((item) => {
        // Filtrar apenas chaves de usuários, não de email lookups
        const isEmailLookup = item.key.includes(":email:");
        
        if (isEmailLookup) {
          return false;
        }
        
        // ? CORREÇÃO CRÍTICA: Validação rigorosa de usuário válido
        const hasValue = item.value != null;
        const hasId = hasValue && typeof item.value.id === 'string' && item.value.id.trim().length > 0;
        const hasEmail = hasValue && typeof item.value.email === 'string' && item.value.email.trim().length > 0;
        const hasNome = hasValue && typeof item.value.nome === 'string' && item.value.nome.trim().length > 0;
        const hasEmpresaId = hasValue && typeof item.value.empresaId === 'string' && item.value.empresaId.trim().length > 0;
        
        const isValidUser = hasId && hasEmail && hasNome && hasEmpresaId;
        
        if (!isValidUser) {
          return false;
        }
        
        // Filtrar por empresaId
        return item.value.empresaId === empresaId;
      })
      .map((item) => ({
        ...item.value,
        id: item.key.replace('usuario:', ''), // ? CORRIGIDO: Remover prefixo "usuario:" da chave
      }))
      .sort((a, b) => new Date(b.dataCriacao).getTime() - new Date(a.dataCriacao).getTime());

    return usuarios;
  } catch (error) {
    // console.error("[Usuarios] Erro ao listar usuários:", error);
    return [];
  }
}

/**
 * Listar todos os usuários (apenas super admin)
 */
export async function listarTodosUsuarios(): Promise<Usuario[]> {
  try {
    // ? CORREÇÃO: Buscar QUALQUER chave que comece com "usuario" para pegar ambos os formatos:
    // - usuario:id (formato antigo)
    // - usuario:empresaId:id (formato novo do sistema de permissões)
    const todosUsuarios = await kv.getByPrefixWithKeys<Usuario>("usuario");
    
    logger.info(`Total de chaves encontradas: ${todosUsuarios.length}`);
    
    const usuarios = todosUsuarios
      .filter((item) => {
        // ? Filtrar apenas chaves de usuários, não de email lookups
        const isEmailLookup = item.key.includes(":email:");
        
        if (isEmailLookup) {
          logger.info(`Pulando chave de lookup: ${item.key}`);
          return false;
        }
        
        // ? CORREÇÃO CRÍTICA: Validação rigorosa de usuário válido
        const hasValue = item.value != null;
        const hasId = hasValue && typeof item.value.id === 'string' && item.value.id.trim().length > 0;
        const hasEmail = hasValue && typeof item.value.email === 'string' && item.value.email.trim().length > 0;
        const hasNome = hasValue && typeof item.value.nome === 'string' && item.value.nome.trim().length > 0;
        const hasEmpresaId = hasValue && typeof item.value.empresaId === 'string' && item.value.empresaId.trim().length > 0;
        
        const isValidUser = hasId && hasEmail && hasNome && hasEmpresaId;
        
        if (!isValidUser) {
          logger.warn(`??? Ignorando usuário inválido em ${item.key}:`, {
            hasValue,
            hasId,
            hasEmail,
            hasNome,
            hasEmpresaId,
            email: item.value?.email,
            nome: item.value?.nome
          });
          return false;
        }
        
        return true;
      })
      .map((item) => ({
        ...item.value,
        id: item.key.replace('usuario:', ''), // ? CORRIGIDO: Remover prefixo "usuario:" da chave
      }))
      .sort((a, b) => new Date(b.dataCriacao).getTime() - new Date(a.dataCriacao).getTime());

    logger.info(`${usuarios.length} usuários válidos encontrados`);
    usuarios.forEach(u => logger.info(`   - ${u.nome} (${u.email}) - Empresa: ${u.empresaId} - ID: ${u.id}`));

    return usuarios;
  } catch (error) {
    logger.error("Erro ao listar todos usuários:", error);
    return [];
  }
}

/**
 * Atualizar usuário
 */
export async function atualizarUsuario(
  id: string,
  dados: Partial<Usuario> & { password?: string } // NOVO: Permitir atualizar senha
): Promise<{ success: boolean; data?: Usuario; error?: string }> {
  try {
    const usuario = await buscarUsuarioPorId(id);
    
    if (!usuario) {
      return { success: false, error: "Usuário não encontrado" };
    }

    // NOVO: Se está alterando a senha, atualizar no Supabase Auth
    if (dados.password) {
      const supabase = createClient(
        Deno.env.get("SUPABASE_URL") ?? "",
        Deno.env.get("SUPABASE_SERVICE_ROLE_KEY") ?? ""
      );

      const { error: authError } = await supabase.auth.admin.updateUserById(id, {
        password: dados.password,
      });

      if (authError) {
        // console.error("[Usuarios] Erro ao atualizar senha no Supabase Auth:", authError);
        return { success: false, error: `Erro ao atualizar senha: ${authError.message}` };
      }

      // console.log(`[Usuarios] ? Senha atualizada para usuário: ${id}`);
    }

    // NOVO: Se está alterando o email, atualizar no Supabase Auth também
    if (dados.email && dados.email !== usuario.email) {
      const emailExiste = await buscarUsuarioPorEmail(dados.email);
      if (emailExiste) {
        return { success: false, error: "Email já está em uso" };
      }

      const supabase = createClient(
        Deno.env.get("SUPABASE_URL") ?? "",
        Deno.env.get("SUPABASE_SERVICE_ROLE_KEY") ?? ""
      );

      const { error: authError } = await supabase.auth.admin.updateUserById(id, {
        email: dados.email,
      });

      if (authError) {
        // console.error("[Usuarios] Erro ao atualizar email no Supabase Auth:", authError);
        return { success: false, error: `Erro ao atualizar email: ${authError.message}` };
      }
      
      // Remover índice antigo e criar novo
      await kv.del(`usuario:email:${usuario.email}`);
      await kv.set(`usuario:email:${dados.email}`, id);
    }

    // ✅ Desactivar um utilizador so marcava ativo:false no KV — a sessao
    // Supabase Auth ja emitida continuava valida ate expirar sozinha. O ban
    // impede novos logins/refresh imediatamente; ao reactivar, o ban e
    // levantado.
    if (typeof dados.ativo === "boolean" && dados.ativo !== usuario.ativo) {
      const supabaseBan = createClient(
        Deno.env.get("SUPABASE_URL") ?? "",
        Deno.env.get("SUPABASE_SERVICE_ROLE_KEY") ?? ""
      );
      await supabaseBan.auth.admin.updateUserById(id, {
        ban_duration: dados.ativo ? "none" : "876000h",
      }).catch((error: any) => {
        console.error("[Usuarios] Erro ao atualizar ban no Supabase Auth:", error);
      });
    }

    // Remover password dos dados antes de salvar no KV (não deve ser armazenado)
    const { password, ...dadosSemSenha } = dados;

    const usuarioAtualizado = {
      ...usuario,
      ...dadosSemSenha,
      id: usuario.id, // Garantir que ID não mude
      dataCriacao: usuario.dataCriacao, // Garantir que data de criação não mude
    };

    await kv.set(`usuario:${id}`, usuarioAtualizado);

    // console.log(`[Usuarios] ? Usuário atualizado: ${id}`);

    return { success: true, data: usuarioAtualizado };
  } catch (error) {
    // console.error("[Usuarios] Erro ao atualizar usuário:", error);
    return { success: false, error: error.message };
  }
}

/**
 * Atribuir módulos a um usuário
 */
export async function atribuirModulos(
  usuarioId: string,
  modulosPermitidos: string[]
): Promise<{ success: boolean; error?: string }> {
  try {
    const usuario = await buscarUsuarioPorId(usuarioId);
    
    if (!usuario) {
      return { success: false, error: "Usuário não encontrado" };
    }

    const resultado = await atualizarUsuario(usuarioId, { modulosPermitidos });
    
    if (!resultado.success) {
      return { success: false, error: resultado.error };
    }

    // console.log(`[Usuarios] ? Módulos atribuídos ao usuário ${usuarioId}:`, modulosPermitidos);

    return { success: true };
  } catch (error) {
    // console.error("[Usuarios] Erro ao atribuir módulos:", error);
    return { success: false, error: error.message };
  }
}

/**
 * Ativar/Desativar usuário
 */
export async function toggleUsuario(
  id: string,
  ativo: boolean
): Promise<{ success: boolean; error?: string }> {
  try {
    const resultado = await atualizarUsuario(id, { ativo });
    
    if (!resultado.success) {
      return { success: false, error: resultado.error };
    }

    // console.log(`[Usuarios] ? Usuário ${ativo ? "ativado" : "desativado"}: ${id}`);

    return { success: true };
  } catch (error) {
    // console.error("[Usuarios] Erro ao alternar status do usuário:", error);
    return { success: false, error: error.message };
  }
}

/**
 * Deletar usuário
 */
export async function deletarUsuario(id: string): Promise<{ success: boolean; error?: string }> {
  try {
    const usuario = await buscarUsuarioPorId(id);
    
    if (!usuario) {
      return { success: false, error: "Usuário não encontrado" };
    }

    // Super admin não pode ser deletado
    if (usuario.nivel === "super_admin") {
      return { success: false, error: "Super Admin não pode ser removido" };
    }

    // ✅ Impede que a sessao Supabase Auth ja emitida continue valida apos o
    // registo do utilizador ser removido do KV.
    const supabaseBanDelete = createClient(
      Deno.env.get("SUPABASE_URL") ?? "",
      Deno.env.get("SUPABASE_SERVICE_ROLE_KEY") ?? ""
    );
    await supabaseBanDelete.auth.admin.updateUserById(id, { ban_duration: "876000h" }).catch((error: any) => {
      console.error("[Usuarios] Erro ao banir utilizador no Supabase Auth antes de eliminar:", error);
    });

    // Remover usuário e índice de email
    await kv.del(`usuario:${id}`);
    await kv.del(`usuario:email:${usuario.email}`);

    // console.log(`[Usuarios] ? Usuário deletado: ${id}`);

    return { success: true };
  } catch (error) {
    // console.error("[Usuarios] Erro ao deletar usuário:", error);
    return { success: false, error: error.message };
  }
}

/**
 * Atualizar último acesso
 */
export async function atualizarUltimoAcesso(usuarioId: string): Promise<void> {
  try {
    await atualizarUsuario(usuarioId, {
      ultimoAcesso: new Date().toISOString(),
    });
  } catch (error) {
    // console.error("[Usuarios] Erro ao atualizar último acesso:", error);
  }
}

/**
 * Verificar se usuário tem permissão para um módulo
 */
export function temPermissaoModulo(usuario: Usuario, moduloId: string): boolean {
  // Super admin tem acesso a tudo
  if (usuario.nivel === "super_admin") {
    return true;
  }

  // Admin da empresa tem acesso a todos os módulos da empresa
  if (usuario.nivel === "admin_empresa") {
    return true;
  }

  // Usuário normal só tem acesso aos módulos permitidos
  return usuario.modulosPermitidos.includes(moduloId);
}
