import { NextRequest, NextResponse } from "next/server";

export const runtime = "edge";

type ProdutoCatalogoDocument = {
  $id: string;
  nome: string;
  descricao?: string;
  codigo_ean?: string;
  codigo_interno?: string;
  categoria?: string;
  laboratorio?: string;
  preco_base?: number;
  [key: string]: unknown;
};

type AppwriteConfig = {
  endpoint?: string;
  projectId?: string;
  databaseId?: string;
  collectionId?: string;
  apiKey?: string;
};

const FALLBACK_PRODUCTS: ProdutoCatalogoDocument[] = [
  {
    $id: "catalogo-fallback-vitamina-c",
    nome: "Vitamina C 500mg",
    descricao: "Produto de demonstracao para cadastro",
    codigo_ean: "0000000000001",
    codigo_interno: "0000000000001",
    categoria: "Vitaminas",
    laboratorio: "Laboratorio EMS",
    preco_base: 19.9,
  },
  {
    $id: "catalogo-fallback-analgesico",
    nome: "Analgesico A",
    descricao: "Demonstracao de analgesico",
    codigo_ean: "0000000000002",
    codigo_interno: "0000000000002",
    categoria: "Analgesicos",
    laboratorio: "Laboratorio Eurofarma",
    preco_base: 14.5,
  },
];

function normalizar(valor: string | null) {
  return (valor ?? "").trim().toLowerCase();
}

function respondWithFallback(codigo: string, termo: string, reason: string) {
  const codigoNormalizado = normalizar(codigo);
  const termoNormalizado = normalizar(termo);

  const documentosEncontrados = FALLBACK_PRODUCTS.filter((produto) => {
    const codigoProduto = normalizar(produto.codigo_ean ?? produto.codigo_interno ?? "");
    const nomeProduto = normalizar(produto.nome);
    const descricaoProduto = normalizar(produto.descricao ?? "");

    const codigoCompativel = codigoNormalizado ? codigoProduto === codigoNormalizado : true;
    const termoCompativel = termoNormalizado
      ? nomeProduto.includes(termoNormalizado) || descricaoProduto.includes(termoNormalizado)
      : true;

    return codigoCompativel && termoCompativel;
  });

  console.warn("[produtos-catalogo][GET] Respondendo com fallback:", reason);

  return NextResponse.json(
    {
      success: true,
      documents: documentosEncontrados,
      total: documentosEncontrados.length,
      found: documentosEncontrados.length > 0,
      fallback: true,
      source: "produtos-catalogo-fallback",
      error: reason,
    },
    { status: 200 }
  );
}

function readAppwriteConfig(): AppwriteConfig {
  return {
    endpoint: process.env.APPWRITE_ENDPOINT || process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT,
    projectId: process.env.APPWRITE_PROJECT_ID || process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID,
    databaseId: process.env.APPWRITE_DATABASE_ID || process.env.NEXT_PUBLIC_APPWRITE_DATABASE_ID,
    collectionId:
      process.env.APPWRITE_COLLECTION_PRODUTOS_CATALOGO_ID ||
      process.env.NEXT_PUBLIC_APPWRITE_COLLECTION_PRODUTOS_CATALOGO_ID,
    apiKey: process.env.APPWRITE_API_KEY,
  };
}

function ensureConfig(config: AppwriteConfig) {
  const missing = Object.entries(config)
    .filter(([_, value]) => !value)
    .map(([key]) => key);

  return {
    ok: missing.length === 0,
    missing,
  } as const;
}

type ResolvedAppwriteConfig = {
  endpoint: string;
  projectId: string;
  databaseId: string;
  collectionId: string;
  apiKey: string;
};

function normalizeEndpoint(endpoint: string) {
  return endpoint.endsWith("/") ? endpoint.slice(0, -1) : endpoint;
}

function buildAppwriteHeaders(config: ResolvedAppwriteConfig) {
  return {
    "X-Appwrite-Project": config.projectId,
    "X-Appwrite-Key": config.apiKey,
    Accept: "application/json",
  };
}

function escapeQueryValue(value: string) {
  return value.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
}

function buildEqualQuery(attribute: string, value: string) {
  return `equal("${attribute}", ["${escapeQueryValue(value)}"])`;
}

function buildSearchQuery(attribute: string, value: string) {
  return `search("${attribute}", "${escapeQueryValue(value)}")`;
}

async function buildAppwriteError(response: Response) {
  let message = `Appwrite responded with status ${response.status}`;
  let payload: unknown;

  try {
    payload = await response.json();
    if (
      payload &&
      typeof payload === "object" &&
      "message" in payload &&
      typeof (payload as any).message === "string"
    ) {
      message = (payload as any).message;
    }
  } catch {
    // ignore json parse errors
  }

  const error = new Error(message);
  (error as any).status = response.status;
  (error as any).payload = payload;
  return error;
}

async function appwriteListDocuments(
  config: ResolvedAppwriteConfig,
  queries: string[]
): Promise<{ documents: ProdutoCatalogoDocument[]; total: number }> {
  const endpoint = normalizeEndpoint(config.endpoint);
  const url = new URL(
    `${endpoint}/databases/${config.databaseId}/collections/${config.collectionId}/documents`
  );
  for (const query of queries) {
    url.searchParams.append("queries[]", query);
  }

  const response = await fetch(url.toString(), {
    method: "GET",
    headers: buildAppwriteHeaders(config),
  });

  if (!response.ok) {
    throw await buildAppwriteError(response);
  }

  return (await response.json()) as { documents: ProdutoCatalogoDocument[]; total: number };
}

export async function GET(request: NextRequest) {
  const { searchParams } = request.nextUrl;
  const codigoParam =
    searchParams.get("codigo") ||
    searchParams.get("codigoBarras") ||
    searchParams.get("codigo_barras") ||
    searchParams.get("ean") ||
    "";
  const termo = (searchParams.get("termo") || "").trim();

  const config = readAppwriteConfig();
  const { ok, missing } = ensureConfig(config);

  if (!config.apiKey || !ok) {
    const reason = !config.apiKey
      ? "APPWRITE_API_KEY ausente"
      : `Variaveis Appwrite ausentes: ${missing.join(", ")}`;
    return respondWithFallback(codigoParam, termo, reason);
  }

  const resolved: ResolvedAppwriteConfig = {
    endpoint: config.endpoint as string,
    projectId: config.projectId as string,
    databaseId: config.databaseId as string,
    collectionId: config.collectionId as string,
    apiKey: config.apiKey as string,
  };

  const trimmedCodigo = codigoParam.trim();
  const queries: string[] = [];

  if (trimmedCodigo) {
    queries.push(buildEqualQuery("codigo_ean", trimmedCodigo));
  }

  if (termo) {
    queries.push(buildSearchQuery("nome", termo));
  }

  if (!queries.length) {
    queries.push("limit(10)");
  } else {
    queries.push("limit(5)");
  }

  try {
    const response = await appwriteListDocuments(resolved, queries);

    return NextResponse.json({
      success: true,
      documents: response.documents,
      total: response.total,
      found: response.total > 0,
    });
  } catch (error) {
    console.error("[produtos-catalogo][GET] Erro ao consultar Appwrite", error);
    const reason =
      error instanceof Error ? error.message : "Erro ao consultar produtos por codigo";
    return respondWithFallback(codigoParam, termo, reason);
  }
}
