import { createClient } from "../../src/compat/supabase.js";
import * as kv from "./kv_store.tsx";
import { createLogger } from "./logger.tsx";

const logger = createLogger('DocumentosColaborador');

const supabase = createClient(
  Deno.env.get("SUPABASE_URL") ?? "",
  Deno.env.get("SUPABASE_SERVICE_ROLE_KEY") ?? "",
);

// Bucket PRIVADO (ao contrario da foto de perfil) — segue exactamente o
// padrao ja usado em uploads.tsx para "documentos de suporte contabilistico"
// (make-7249dcd9-documentos-suporte): acesso so via signed URL, nunca URL
// publica directa, porque estes ficheiros podem conter dados pessoais
// sensiveis (BI, atestados medicos, etc.).
const BUCKET_NAME = "make-7249dcd9-rh-documentos";
const TAMANHO_MAXIMO_BYTES = 10 * 1024 * 1024; // 10MB
const TIPOS_MIME_PERMITIDOS = ["application/pdf", "image/jpeg", "image/jpg", "image/png", "image/webp"];

async function initBucket() {
  try {
    const { data: buckets } = await supabase.storage.listBuckets();
    const existe = buckets?.some((bucket) => bucket.name === BUCKET_NAME);

    if (!existe) {
      const { error } = await supabase.storage.createBucket(BUCKET_NAME, {
        public: false,
        fileSizeLimit: TAMANHO_MAXIMO_BYTES,
      });
      if (error && !error.message?.includes("already exists")) {
        throw error;
      }
    }
  } catch (error) {
    logger.error("Erro ao inicializar bucket de documentos de colaborador:", error);
  }
}

try {
  await initBucket();
} catch (_error) {
  // Silenciado - nao deve impedir o arranque do servidor
}

const sanitizeFileName = (name: string) =>
  String(name || "documento")
    .normalize("NFD")
    .replace(/[\u0300-\u036f]/g, "")
    .replace(/[^a-zA-Z0-9._-]+/g, "-")
    .replace(/-+/g, "-")
    .replace(/^-|-$/g, "")
    .slice(0, 80) || "documento";

// Cada tipo tem, opcionalmente, uma data de validade (BI, DIRE/visto, carta
// de conducao, atestado medico) — preparado para o motor de alertas de
// expiracao automatica (Grupo 3), sem o construir agora.
export type TipoDocumentoColaborador =
  | "bi_passaporte"
  | "dire_visto"
  | "certificado_habilitacoes"
  | "cv"
  | "contrato_trabalho"
  | "comprovativo_nuit"
  | "comprovativo_inss"
  | "atestado_medico"
  | "certificado_registo_criminal"
  | "carta_conducao"
  | "outro";

export interface DocumentoColaborador {
  id: string;
  empresaId: string;
  colaboradorId: string;
  tipo: TipoDocumentoColaborador;
  nomeFicheiro: string;
  storagePath: string;
  mimeType: string;
  tamanhoBytes: number;
  dataValidade?: string;
  observacoes?: string;
  uploadedPor?: string;
  dataCriacao: string;
  dataAtualizacao?: string;
}

const DOCUMENTO_PREFIX = "documento_colaborador:";

export async function uploadDocumentoColaborador(params: {
  empresaId: string;
  colaboradorId: string;
  tipo: TipoDocumentoColaborador;
  file: File;
  dataValidade?: string;
  observacoes?: string;
  uploadedPor?: string;
}): Promise<{ success: boolean; data?: DocumentoColaborador; error?: string }> {
  try {
    const { empresaId, colaboradorId, tipo, file, dataValidade, observacoes, uploadedPor } = params;

    if (!empresaId || !colaboradorId || !tipo || !file) {
      return { success: false, error: "Empresa, colaborador, tipo e ficheiro são obrigatórios" };
    }

    if (file.size > TAMANHO_MAXIMO_BYTES) {
      return { success: false, error: "Ficheiro muito grande (máx 10MB)" };
    }

    if (!TIPOS_MIME_PERMITIDOS.includes(file.type)) {
      return { success: false, error: "Tipo de ficheiro inválido (use PDF, JPG, PNG ou WEBP)" };
    }

    const id = `documento_colaborador_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
    const nomeOriginal = sanitizeFileName(file.name);
    const storagePath = `${empresaId}/${colaboradorId}/${id}-${nomeOriginal}`;
    const buffer = new Uint8Array(await file.arrayBuffer());

    const { error: uploadError } = await supabase.storage
      .from(BUCKET_NAME)
      .upload(storagePath, buffer, {
        contentType: file.type,
        cacheControl: "3600",
        upsert: false,
      });

    if (uploadError) {
      return { success: false, error: uploadError.message };
    }

    const documento: DocumentoColaborador = {
      id,
      empresaId,
      colaboradorId,
      tipo,
      nomeFicheiro: file.name,
      storagePath,
      mimeType: file.type,
      tamanhoBytes: file.size,
      dataValidade,
      observacoes,
      uploadedPor,
      dataCriacao: new Date().toISOString(),
    };

    await kv.set(`${DOCUMENTO_PREFIX}${id}`, documento);
    logger.info(`Documento carregado: ${file.name} (colaborador ${colaboradorId})`);

    return { success: true, data: documento };
  } catch (error) {
    logger.error("Erro ao carregar documento de colaborador:", error);
    return { success: false, error: error.message };
  }
}

export async function buscarDocumentoColaboradorPorId(id: string): Promise<DocumentoColaborador | null> {
  try {
    return (await kv.get(`${DOCUMENTO_PREFIX}${id}`)) as DocumentoColaborador | null;
  } catch (error) {
    logger.error("Erro ao buscar documento de colaborador:", error);
    return null;
  }
}

export async function listarDocumentosColaborador(
  empresaId: string,
  colaboradorId: string,
): Promise<DocumentoColaborador[]> {
  try {
    const todos = await kv.getByPrefix<DocumentoColaborador>(DOCUMENTO_PREFIX);
    return todos
      .filter((item) => item && item.empresaId === empresaId && item.colaboradorId === colaboradorId)
      .sort((a, b) => b.dataCriacao.localeCompare(a.dataCriacao));
  } catch (error) {
    logger.error("Erro ao listar documentos de colaborador:", error);
    return [];
  }
}

export async function atualizarDocumentoColaborador(
  id: string,
  dados: Partial<Pick<DocumentoColaborador, "tipo" | "dataValidade" | "observacoes">>,
): Promise<{ success: boolean; data?: DocumentoColaborador; error?: string }> {
  try {
    const documento = await buscarDocumentoColaboradorPorId(id);
    if (!documento) {
      return { success: false, error: "Documento não encontrado" };
    }

    const documentoAtualizado: DocumentoColaborador = {
      ...documento,
      ...dados,
      id: documento.id,
      empresaId: documento.empresaId,
      colaboradorId: documento.colaboradorId,
      storagePath: documento.storagePath,
      dataCriacao: documento.dataCriacao,
      dataAtualizacao: new Date().toISOString(),
    };

    await kv.set(`${DOCUMENTO_PREFIX}${id}`, documentoAtualizado);
    logger.info(`Documento atualizado: ${id}`);

    return { success: true, data: documentoAtualizado };
  } catch (error) {
    logger.error("Erro ao atualizar documento de colaborador:", error);
    return { success: false, error: error.message };
  }
}

export async function gerarSignedUrlDocumentoColaborador(
  id: string,
  expiresIn = 600,
): Promise<{ success: boolean; signedUrl?: string; nomeFicheiro?: string; error?: string }> {
  try {
    const documento = await buscarDocumentoColaboradorPorId(id);
    if (!documento) {
      return { success: false, error: "Documento não encontrado" };
    }

    const expiracaoSegura = Math.min(Math.max(expiresIn, 60), 3600);
    const { data, error } = await supabase.storage
      .from(BUCKET_NAME)
      .createSignedUrl(documento.storagePath, expiracaoSegura);

    if (error) {
      return { success: false, error: error.message };
    }

    return { success: true, signedUrl: data.signedUrl, nomeFicheiro: documento.nomeFicheiro };
  } catch (error) {
    logger.error("Erro ao gerar link temporario de documento de colaborador:", error);
    return { success: false, error: error.message };
  }
}

export async function deletarDocumentoColaborador(id: string): Promise<{ success: boolean; error?: string }> {
  try {
    const documento = await buscarDocumentoColaboradorPorId(id);
    if (!documento) {
      return { success: false, error: "Documento não encontrado" };
    }

    const { error } = await supabase.storage.from(BUCKET_NAME).remove([documento.storagePath]);
    if (error) {
      return { success: false, error: error.message };
    }

    await kv.del(`${DOCUMENTO_PREFIX}${id}`);
    logger.info(`Documento eliminado: ${id}`);

    return { success: true };
  } catch (error) {
    logger.error("Erro ao eliminar documento de colaborador:", error);
    return { success: false, error: error.message };
  }
}

export async function contarDocumentosColaborador(empresaId: string, colaboradorId: string): Promise<number> {
  const lista = await listarDocumentosColaborador(empresaId, colaboradorId);
  return lista.length;
}
