import type { Metadata } from "next";
import { notFound } from "next/navigation";
import Image from "next/image";
import PaymentLinkCheckoutClient from "@/components/PaymentLinkCheckoutClient";
import { createAdminClient } from "@/lib/supabase-admin";
import { getMercadoPagoIntegration, resolveMercadoPagoPublicConfig } from "@/lib/mercado-pago";
import { mapPaymentLinkRecord, normalizeText, type PaymentLinkRecord } from "@/lib/payment-links";

export const dynamic = "force-dynamic";
export const revalidate = 0;

type ProfileRow = {
  slug?: string | null;
  catalog_name?: string | null;
  store_name?: string | null;
  catalog_logo_url?: string | null;
  logo_url?: string | null;
  primary_color?: string | null;
  catalog_header_color?: string | null;
  catalog_header_text_color?: string | null;
};

type CompanyRow = {
  id?: string | null;
  owner_id?: string | null;
  name?: string | null;
};

type LinkedClient = {
  id: string;
  name: string | null;
  company_name: string | null;
  email: string | null;
  document: string | null;
  phone: string | null;
};

type LinkedProduct = {
  id: string;
  name: string | null;
  price: number | null;
  image_url: string | null;
  price_on_request: boolean | null;
};

type LinkedItem = {
  productId: string;
  name: string;
  quantity: number;
  unitPrice: number | null;
  priceOnRequest: boolean;
  imageUrl: string;
};

function deriveLinkBrandValue(record: Record<string, unknown> | null | undefined, keys: string[]) {
  for (const key of keys) {
    const value = normalizeText(record?.[key]);
    if (value) return value;
  }
  return "";
}

function deriveProfileValue(rows: Array<ProfileRow | null | undefined>, keys: Array<keyof ProfileRow>) {
  for (const row of rows) {
    for (const key of keys) {
      const value = normalizeText(row?.[key]);
      if (value) return value;
    }
  }
  return "";
}

function formatClientTitle(name: string, company: string) {
  const normalizedName = normalizeText(name);
  const normalizedCompany = normalizeText(company);
  if (normalizedName && normalizedCompany && normalizedName.toLowerCase() !== normalizedCompany.toLowerCase()) {
    return `${normalizedName} (${normalizedCompany})`;
  }
  return normalizedName || normalizedCompany;
}

export async function generateMetadata(props: { params: Promise<{ code: string }> | { code: string } }): Promise<Metadata> {
  const params = await Promise.resolve(props.params as { code: string });
  const code = normalizeText(params?.code).toUpperCase();
  if (!code) return { title: "Link de pagamento" };

  try {
    const admin = createAdminClient();
    const { data: rawLink } = await admin.from("payment_links").select("*").eq("code", code).maybeSingle();
    if (!rawLink) return { title: "Link de pagamento" };

    const link = mapPaymentLinkRecord(rawLink as PaymentLinkRecord);
    const linkRow = rawLink as PaymentLinkRecord;
    const { data: companyRow } = linkRow.company_id
      ? await admin.from("companies").select("id,owner_id,name").eq("id", linkRow.company_id).maybeSingle()
      : { data: null };

    const metadataBrand = (link.metadata || {}) as Record<string, unknown>;
    const checkoutBrand = (link.checkoutConfig || {}) as Record<string, unknown>;
    const shareBrand = (link.shareConfig || {}) as Record<string, unknown>;

    const storeName =
      deriveLinkBrandValue(metadataBrand, ["store_name", "catalog_name", "brand_name"]) ||
      deriveLinkBrandValue(checkoutBrand, ["store_name", "catalog_name", "brand_name"]) ||
      deriveLinkBrandValue(shareBrand, ["store_name", "catalog_name", "brand_name"]) ||
      normalizeText((companyRow as CompanyRow | null)?.name) ||
      normalizeText(link.slug).replace(/-/g, " ") ||
      "Loja";

    const checkoutConfig =
      link.checkoutConfig && typeof link.checkoutConfig === "object" && !Array.isArray(link.checkoutConfig)
        ? (link.checkoutConfig as Record<string, unknown>)
        : {};
    const linkedClientId = typeof checkoutConfig.client_id === "string" ? normalizeText(checkoutConfig.client_id) : "";
    const { data: clientRow } = linkedClientId
      ? await admin.from("clients").select("id,name,company_name").eq("id", linkedClientId).maybeSingle()
      : { data: null };
    const clientName = clientRow
      ? formatClientTitle(String((clientRow as any).name || ""), String((clientRow as any).company_name || ""))
      : "";

    const titleText = clientName ? `Pagamento - ${clientName} | ${storeName}` : `Pagamento | ${storeName}`;
    const whatsappMessage =
      link.shareConfig && typeof link.shareConfig === "object" && !Array.isArray(link.shareConfig)
        ? normalizeText((link.shareConfig as any).whatsapp_message)
        : "";
    const description =
      whatsappMessage ||
      (clientName
        ? `Link de pagamento de ${storeName} para ${clientName}.`
        : `Link de pagamento de ${storeName}.`);

    return {
      title: { absolute: titleText },
      description,
      openGraph: {
        type: "website",
        siteName: storeName,
        title: titleText,
        description,
      },
      twitter: {
        title: titleText,
        description,
      },
    };
  } catch {
    return { title: "Link de pagamento" };
  }
}

async function resolveAssetUrl(rawValue: string | null | undefined) {
  const value = normalizeText(rawValue);
  if (!value) return "";
  if (value.startsWith("data:")) return value;

  const parseStorageTarget = (input: string): { bucket: string; path: string } | null => {
    const normalized = input.replace(/^\/+/, "");

    if (/^https?:\/\//i.test(input)) {
      try {
        const parsed = new URL(input);
        const publicMarker = "/storage/v1/object/public/";
        const signMarker = "/storage/v1/object/sign/";
        const marker = parsed.pathname.includes(signMarker) ? signMarker : publicMarker;
        if (!parsed.pathname.includes(marker)) return null;
        const rest = parsed.pathname.slice(parsed.pathname.indexOf(marker) + marker.length);
        const [bucket, ...parts] = rest.split("/");
        return bucket && parts.length ? { bucket, path: parts.join("/") } : null;
      } catch {
        return null;
      }
    }

    const clean = normalized.replace(/^storage\/v1\/object\/public\//, "").replace(/^storage\/v1\/object\/sign\//, "");
    const [bucket, ...parts] = clean.split("/");
    return bucket && parts.length ? { bucket, path: parts.join("/") } : null;
  };

  const target = parseStorageTarget(value);
  if (!target) return value;

  try {
    const admin = createAdminClient();
    const { data: signedData, error: signedError } = await admin.storage
      .from(target.bucket)
      .createSignedUrl(target.path, 60 * 60 * 24 * 30);

    if (!signedError && signedData?.signedUrl) return signedData.signedUrl;

    const { data: publicData } = admin.storage.from(target.bucket).getPublicUrl(target.path);
    return publicData?.publicUrl || value;
  } catch {
    return value;
  }
}

function UnavailableState({
  title,
  description,
  logoUrl,
  storeName,
}: {
  title: string;
  description: string;
  logoUrl: string;
  storeName: string;
}) {
  return (
    <div className="min-h-screen bg-slate-50 px-4 py-10">
      <div className="mx-auto max-w-xl border border-slate-200 bg-white p-8 text-center">
        <div className="flex justify-center">
          {logoUrl ? (
            <Image src={logoUrl} alt={storeName} width={180} height={48} className="h-10 w-auto object-contain" unoptimized />
          ) : (
            <div className="text-xl font-semibold text-slate-900">{storeName}</div>
          )}
        </div>
        <h1 className="mt-8 text-2xl font-semibold tracking-[-0.04em] text-slate-950">{title}</h1>
        <p className="mt-3 text-sm leading-6 text-slate-500">{description}</p>
      </div>
    </div>
  );
}

export default async function PaymentLinkPage(props: {
  params: Promise<{ code: string }>;
}) {
  const params = await props.params;
  const code = normalizeText(params.code).toUpperCase();
  if (!code) {
    notFound();
  }

  const admin = createAdminClient();
  const { data: rawLink, error: linkError } = await admin
    .from("payment_links")
    .select("*")
    .eq("code", code)
    .maybeSingle();

  if (linkError || !rawLink) {
    notFound();
  }

  const link = mapPaymentLinkRecord(rawLink as PaymentLinkRecord);
  const linkRow = rawLink as PaymentLinkRecord;
  const { data: companyRow } = linkRow.company_id
    ? await admin
        .from("companies")
        .select("id,owner_id,name")
        .eq("id", linkRow.company_id)
        .maybeSingle()
    : { data: null };

  const [{ data: profile }, { data: profileBySlug }, { data: profileByCompanyOwner }, integration] = await Promise.all([
    admin
      .from("profiles")
      .select("*")
      .eq("id", link.userId)
      .maybeSingle(),
    admin
      .from("profiles")
      .select("*")
      .eq("slug", link.slug)
      .maybeSingle(),
    (companyRow as CompanyRow | null)?.owner_id
      ? admin
          .from("profiles")
          .select("*")
          .eq("id", (companyRow as CompanyRow).owner_id as string)
          .maybeSingle()
      : Promise.resolve({ data: null }),
    getMercadoPagoIntegration(admin as never, link.userId).catch(() => null),
  ]);

  const mercadoPagoConfig = resolveMercadoPagoPublicConfig(integration || null);
  const metadataBrand = (link.metadata || {}) as Record<string, unknown>;
  const checkoutBrand = (link.checkoutConfig || {}) as Record<string, unknown>;
  const shareBrand = (link.shareConfig || {}) as Record<string, unknown>;
  
  const fallbackStoreName =
    deriveLinkBrandValue(metadataBrand, ["store_name", "catalog_name", "brand_name"]) ||
    deriveLinkBrandValue(checkoutBrand, ["store_name", "catalog_name", "brand_name"]) ||
    deriveLinkBrandValue(shareBrand, ["store_name", "catalog_name", "brand_name"]) ||
    normalizeText((companyRow as CompanyRow | null)?.name) ||
    normalizeText(link.slug).replace(/-/g, " ");
  
  const fallbackLogoUrl =
    deriveLinkBrandValue(metadataBrand, ["catalog_logo_url", "logo_url"]) ||
    deriveLinkBrandValue(checkoutBrand, ["catalog_logo_url", "logo_url"]) ||
    deriveLinkBrandValue(shareBrand, ["catalog_logo_url", "logo_url"]);

  const mainProfile = profile as ProfileRow | null;
  const slugProfile = profileBySlug as ProfileRow | null;
  const companyOwnerProfile = profileByCompanyOwner as ProfileRow | null;

  const brandProfiles = [slugProfile, mainProfile, companyOwnerProfile];
  const storeName = deriveProfileValue(brandProfiles, ["catalog_name", "store_name"]) || fallbackStoreName || "Loja";
  const rawLogoUrl = deriveProfileValue(brandProfiles, ["catalog_logo_url", "logo_url"]) || fallbackLogoUrl;
  const logoUrl = await resolveAssetUrl(rawLogoUrl);
  const primaryColor = deriveProfileValue(brandProfiles, ["primary_color"]) || "#4425A7";
  const headerColor = deriveProfileValue(brandProfiles, ["catalog_header_color"]) || primaryColor;
  const headerTextColor = deriveProfileValue(brandProfiles, ["catalog_header_text_color"]) || "#ffffff";

  const checkoutConfig =
    link.checkoutConfig && typeof link.checkoutConfig === "object" && !Array.isArray(link.checkoutConfig)
      ? (link.checkoutConfig as Record<string, unknown>)
      : {};
  const linkedClientId = typeof checkoutConfig.client_id === "string" ? normalizeText(checkoutConfig.client_id) : "";
  const showCookieBanner = typeof checkoutConfig.show_cookie_banner === "boolean" ? checkoutConfig.show_cookie_banner : true;
  const linkedItemsRaw = Array.isArray(checkoutConfig.items) ? checkoutConfig.items : [];
  const linkedItemDrafts = linkedItemsRaw
    .map((value): { productId: string; quantity: number } | null => {
      if (!value || typeof value !== "object" || Array.isArray(value)) return null;
      const record = value as Record<string, unknown>;
      const productId = typeof record.product_id === "string" ? normalizeText(record.product_id) : "";
      if (!productId) return null;
      const quantity = Number(record.quantity);
      const normalizedQuantity = Number.isFinite(quantity) && quantity > 0 ? Math.round(quantity) : 1;
      return { productId, quantity: normalizedQuantity };
    })
    .filter(Boolean) as Array<{ productId: string; quantity: number }>;

  const linkedProductIds = Array.from(new Set(linkedItemDrafts.map((item) => item.productId))).filter(Boolean);

  const [{ data: linkedClientRow }, { data: linkedProductsRows }] = await Promise.all([
    linkedClientId
      ? admin
          .from("clients")
          .select("id,name,company_name,email,document,phone")
          .eq("id", linkedClientId)
          .maybeSingle()
      : Promise.resolve({ data: null }),
    linkedProductIds.length
      ? admin
          .from("products")
          .select("id,name,price,image_url,price_on_request")
          .in("id", linkedProductIds)
      : Promise.resolve({ data: null }),
  ]);

  const linkedClient =
    linkedClientRow && typeof linkedClientRow === "object" ? (linkedClientRow as LinkedClient) : null;

  const linkedProducts = (Array.isArray(linkedProductsRows) ? linkedProductsRows : []) as LinkedProduct[];
  const linkedProductById = new Map<string, LinkedProduct>();
  for (const product of linkedProducts) {
    if (product?.id) linkedProductById.set(product.id, product);
  }

  const linkedItems: LinkedItem[] = linkedItemDrafts
    .map((item) => {
      const product = linkedProductById.get(item.productId);
      if (!product) return null;
      const name = normalizeText(product.name) || "Produto";
      const priceOnRequest = Boolean(product.price_on_request);
      const unitPriceValue = priceOnRequest ? NaN : Number(product.price);
      const resolvedUnitPrice = Number.isFinite(unitPriceValue) ? Number(unitPriceValue.toFixed(2)) : null;
      return {
        productId: item.productId,
        name,
        quantity: item.quantity,
        unitPrice: resolvedUnitPrice,
        priceOnRequest,
        imageUrl: normalizeText(product.image_url),
      };
    })
    .filter(Boolean) as LinkedItem[];

  await admin
    .from("payment_links")
    .update({ last_opened_at: new Date().toISOString(), updated_at: new Date().toISOString() })
    .eq("id", link.id);

  if (link.status !== "active") {
    return (
      <UnavailableState
        title="Link indisponível"
        description="Este link de pagamento nao esta ativo no momento. Solicite um novo link ao emissor."
        logoUrl={logoUrl}
        storeName={storeName}
      />
    );
  }

  if (link.expiresAt && new Date(link.expiresAt).getTime() <= Date.now()) {
    return (
      <UnavailableState
        title="Link expirado"
        description="Este link de pagamento passou da validade e nao pode mais ser usado."
        logoUrl={logoUrl}
        storeName={storeName}
      />
    );
  }

  return (
    <PaymentLinkCheckoutClient
      storeName={storeName}
      logoUrl={logoUrl}
      primaryColor={primaryColor}
      headerColor={headerColor}
      headerTextColor={headerTextColor}
      link={link}
      linkedClient={linkedClient}
      linkedItems={linkedItems}
      showCookieBanner={showCookieBanner}
      gatewayName={mercadoPagoConfig ? "Mercado Pago" : ""}
      mercadoPagoConfig={
        mercadoPagoConfig
          ? {
              environment: mercadoPagoConfig.environment,
              publicKey: mercadoPagoConfig.publicKey,
            }
          : null
      }
    />
  );
}
