export function normalizeHeader(value: unknown) {
  return String(value ?? "")
    .trim()
    .toLowerCase()
    .normalize("NFD")
    .replace(/[\u0300-\u036f]/g, "")
    .replace(/[\s-]+/g, "_")
    .replace(/[^a-z0-9_]/g, "")
    .replace(/_+/g, "_")
    .replace(/^_+|_+$/g, "");
}

export function isValidHttpUrl(value: unknown) {
  if (typeof value !== "string") return false;
  try {
    const url = new URL(value);
    return url.protocol === "http:" || url.protocol === "https:";
  } catch {
    return false;
  }
}

type ImageColumn = { index: number; order: number };

const MAX_IMAGE_BYTES = 10 * 1024 * 1024;
const IMAGE_TIMEOUT_MS = 15000;

function getImageColumnOrder(header: string) {
  const match = header.match(/^(imagem|image|foto)_?([0-9]+)?$/);
  if (!match) return null;
  const order = match[2] ? Number(match[2]) : 0;
  if (order === 0) return 0;
  if (order >= 1 && order <= 5) return order;
  return null;
}

function getImageColumns(normalizedHeaders: string[]) {
  const columns: ImageColumn[] = [];
  normalizedHeaders.forEach((header, index) => {
    const order = getImageColumnOrder(header);
    if (order === null) return;
    columns.push({ index, order });
  });
  return columns.sort((a, b) => (a.order - b.order) || (a.index - b.index));
}

function splitImageValues(value: unknown) {
  if (!value) return [];
  if (Array.isArray(value)) return value.map((v) => String(v).trim()).filter(Boolean);
  return String(value)
    .split(/[,;|\n]/g)
    .map((v) => v.trim())
    .filter(Boolean);
}

export function extractImageUrls(row: unknown[], normalizedHeaders: string[]) {
  const columns = getImageColumns(normalizedHeaders);
  const validUrls: string[] = [];
  const invalidUrls: string[] = [];
  const seen = new Set<string>();

  columns.forEach(({ index }) => {
    const raw = row[index];
    const values = splitImageValues(raw);
    values.forEach((value) => {
      if (seen.has(value)) return;
      seen.add(value);
      if (isValidHttpUrl(value)) {
        validUrls.push(value);
      } else {
        invalidUrls.push(value);
      }
    });
  });

  return { validUrls, invalidUrls };
}

function resolveExtension(contentType: string | null, url: string) {
  const normalized = contentType?.split(";")[0].trim().toLowerCase() ?? "";
  const map: Record<string, string> = {
    "image/jpeg": "jpg",
    "image/jpg": "jpg",
    "image/png": "png",
    "image/webp": "webp",
    "image/gif": "gif",
    "image/bmp": "bmp",
    "image/svg+xml": "svg",
    "image/avif": "avif",
  };
  if (normalized in map) return map[normalized];
  try {
    const parsed = new URL(url);
    const ext = parsed.pathname.split(".").pop()?.toLowerCase() ?? "";
    if (["jpg", "jpeg", "png", "webp", "gif", "bmp", "svg", "avif"].includes(ext)) {
      return ext === "jpeg" ? "jpg" : ext;
    }
  } catch {
    return "jpg";
  }
  return "jpg";
}

export async function downloadImage(url: string) {
  const response = await fetch(url, {
    redirect: "follow",
    headers: { "user-agent": "Ktalogu-Import/1.0" },
    signal: AbortSignal.timeout(IMAGE_TIMEOUT_MS),
  });

  if (!response.ok) {
    throw new Error(`Falha ao baixar imagem (${response.status})`);
  }

  const contentType = response.headers.get("content-type");
  if (!contentType || !contentType.toLowerCase().startsWith("image/")) {
    throw new Error("Content-Type inválido");
  }

  const contentLength = response.headers.get("content-length");
  if (contentLength) {
    const parsed = Number.parseInt(contentLength, 10);
    if (Number.isFinite(parsed) && parsed > MAX_IMAGE_BYTES) {
      throw new Error("Imagem excede tamanho máximo");
    }
  }

  const reader = response.body?.getReader();
  if (!reader) {
    throw new Error("Resposta sem corpo");
  }

  const chunks: Uint8Array[] = [];
  let received = 0;
  while (true) {
    const { done, value } = await reader.read();
    if (done) break;
    if (value) {
      received += value.byteLength;
      if (received > MAX_IMAGE_BYTES) {
        throw new Error("Imagem excede tamanho máximo");
      }
      chunks.push(value);
    }
  }

  const buffer = Buffer.concat(chunks.map((chunk) => Buffer.from(chunk)));
  const ext = resolveExtension(contentType, url);
  return { buffer, contentType, ext };
}

export async function uploadToStorage(
  tenantId: string,
  productId: string,
  buffer: Buffer,
  ext: string,
  contentType?: string | null
) {
  const { createAdminClient } = await import("@/lib/supabase-server");
  const { randomUUID } = await import("crypto");
  const supabase = createAdminClient();
  const hash = randomUUID();
  const path = `${tenantId}/products/${productId}/original/${hash}.${ext}`;
  const { error } = await supabase.storage
    .from("products")
    .upload(path, buffer, contentType ? { contentType } : undefined);
  if (error) throw error;
  const { data } = supabase.storage.from("products").getPublicUrl(path);
  return data.publicUrl;
}

export async function downloadAndUploadImage(url: string, tenantId: string, productId: string) {
  const { buffer, contentType, ext } = await downloadImage(url);
  return uploadToStorage(tenantId, productId, buffer, ext, contentType);
}
