/* eslint-disable @typescript-eslint/no-explicit-any */

type SupabaseLike = {
  from: (table: string) => any;
};

function normalizeText(value: unknown) {
  return String(value || "").trim();
}

function mapPaymentMethod(value: string | null | undefined) {
  const method = normalizeText(value).toLowerCase();
  if (method === "pix") return "pix";
  if (method === "cash") return "cash";
  if (method === "credit_card") return "credit_card";
  if (method === "debit_card") return "debit_card";
  return "transfer";
}

async function findExistingAppliedPayment(params: {
  admin: SupabaseLike;
  companyId: string;
  paymentLinkPaymentId: string;
}) {
  const marker = `payment_link_payment_id:${params.paymentLinkPaymentId}`;
  const { data: receivable } = await params.admin
    .from("accounts_receivable")
    .select("id")
    .eq("company_id", params.companyId)
    .ilike("notes", `%${marker}%`)
    .limit(1)
    .maybeSingle();

  if (!receivable?.id) {
    return {
      receivableId: null,
      receiptId: null,
    };
  }

  const { data: receipt } = await params.admin
    .from("receivable_receipts")
    .select("id")
    .eq("company_id", params.companyId)
    .eq("receivable_id", receivable.id)
    .order("created_at", { ascending: true })
    .limit(1)
    .maybeSingle();

  return {
    receivableId: String(receivable.id),
    receiptId: receipt?.id ? String(receipt.id) : null,
  };
}

async function insertCashFlow(params: {
  admin: SupabaseLike;
  companyId: string;
  bankAccountId: string | null;
  receiptId: string;
  amount: number;
  receivedAt: string;
  description: string;
}) {
  const { admin, companyId, bankAccountId, receiptId, amount, receivedAt, description } = params;

  const { data: existingFlow } = await admin
    .from("cash_flow")
    .select("id")
    .eq("company_id", companyId)
    .eq("reference_id", receiptId)
    .eq("type", "IN")
    .limit(1)
    .maybeSingle();

  if (existingFlow?.id) {
    return;
  }

  let { error } = await admin.from("cash_flow").insert({
    company_id: companyId,
    bank_account_id: bankAccountId,
    type: "IN",
    origin: "RECEBER",
    reference_id: receiptId,
    description,
    amount,
    date: receivedAt,
    created_at: new Date().toISOString(),
  });

  if (error?.code === "23514" || String(error?.message || "").toLowerCase().includes("origin")) {
    const fallback = await admin.from("cash_flow").insert({
      company_id: companyId,
      bank_account_id: bankAccountId,
      type: "IN",
      origin: "MANUAL",
      reference_id: receiptId,
      description: `[RECEBER] ${description}`,
      amount,
      date: receivedAt,
      created_at: new Date().toISOString(),
    });
    error = fallback.error ?? null;
  }

  if (error) {
    throw new Error(error.message || "Nao foi possivel registrar o fluxo de caixa do link de pagamento.");
  }
}

export async function applyApprovedPaymentLinkPayment(admin: SupabaseLike, paymentLinkPaymentId: string) {
  const { data: paymentRow, error: paymentError } = await admin
    .from("payment_link_payments")
    .select(
      "id,user_id,payment_link_id,status,payment_method,amount,approved_at,external_reference,provider_payment_id,metadata,description,payer_name,payer_email,payer_document"
    )
    .eq("id", paymentLinkPaymentId)
    .maybeSingle();

  if (paymentError || !paymentRow) {
    throw new Error(paymentError?.message || "Pagamento do link nao encontrado.");
  }

  const metadata =
    paymentRow.metadata && typeof paymentRow.metadata === "object" && !Array.isArray(paymentRow.metadata)
      ? (paymentRow.metadata as Record<string, unknown>)
      : {};

  if (paymentRow.status !== "approved") {
    return {
      receivableId: typeof metadata.accounts_receivable_id === "string" ? metadata.accounts_receivable_id : null,
      receiptId: typeof metadata.applied_receipt_id === "string" ? metadata.applied_receipt_id : null,
    };
  }

  if (typeof metadata.applied_receipt_id === "string" && metadata.applied_receipt_id.trim()) {
    return {
      receivableId: typeof metadata.accounts_receivable_id === "string" ? metadata.accounts_receivable_id : null,
      receiptId: metadata.applied_receipt_id.trim(),
    };
  }

  const { data: linkRow, error: linkError } = await admin
    .from("payment_links")
    .select("id,company_id,code,title")
    .eq("id", paymentRow.payment_link_id)
    .maybeSingle();

  if (linkError || !linkRow?.id) {
    throw new Error(linkError?.message || "Link de pagamento nao encontrado.");
  }

  const companyId = normalizeText(linkRow.company_id);
  if (!companyId) {
    throw new Error("O link de pagamento nao possui empresa vinculada para registrar no financeiro.");
  }

  const amount = Number(paymentRow.amount || 0);
  if (!Number.isFinite(amount) || amount <= 0) {
    throw new Error("Valor invalido para registrar o recebimento do link.");
  }

  const approvedAtIso = normalizeText(paymentRow.approved_at) || new Date().toISOString();
  const receivedAt = approvedAtIso.slice(0, 10);
  const bankAccountId =
    typeof metadata.bank_account_id === "string" && metadata.bank_account_id.trim() ? metadata.bank_account_id.trim() : null;
  const baseTitle = normalizeText(linkRow.title) || "Link de pagamento";
  const linkCode = normalizeText(linkRow.code);
  const receivableDescription = linkCode ? `${baseTitle} (${linkCode})` : baseTitle;
  const notes = [
    "Recebimento automatico via link de pagamento",
    `payment_link_payment_id:${paymentLinkPaymentId}`,
    paymentRow.provider_payment_id ? `payment_id:${paymentRow.provider_payment_id}` : "",
    paymentRow.external_reference ? `external_reference:${paymentRow.external_reference}` : "",
    paymentRow.payer_email ? `payer_email:${paymentRow.payer_email}` : "",
  ]
    .filter(Boolean)
    .join("\n");

  const existingApplied = await findExistingAppliedPayment({
    admin,
    companyId,
    paymentLinkPaymentId,
  });

  if (existingApplied.receivableId && existingApplied.receiptId) {
    await admin
      .from("payment_link_payments")
      .update({
        metadata: {
          ...metadata,
          accounts_receivable_id: existingApplied.receivableId,
          applied_receipt_id: existingApplied.receiptId,
        },
        updated_at: new Date().toISOString(),
      })
      .eq("id", paymentLinkPaymentId);

    await insertCashFlow({
      admin,
      companyId,
      bankAccountId,
      receiptId: existingApplied.receiptId,
      amount,
      receivedAt,
      description: `Recebimento link de pagamento: ${receivableDescription}`,
    });

    return existingApplied;
  }

  let receivableId = existingApplied.receivableId;
  if (!receivableId) {
    const { data: receivable, error: receivableError } = await admin
      .from("accounts_receivable")
      .insert({
        company_id: companyId,
        description: receivableDescription,
        client_name: normalizeText(paymentRow.payer_name) || null,
        client_company: null,
        total_amount: amount,
        due_date: receivedAt,
        status: "PENDING",
        bank_account_id: bankAccountId,
        notes,
        created_by: paymentRow.user_id,
        created_at: approvedAtIso,
        updated_at: approvedAtIso,
      })
      .select("id")
      .single();

    if (receivableError || !receivable?.id) {
      throw new Error(receivableError?.message || "Nao foi possivel criar a conta a receber do link.");
    }

    receivableId = String(receivable.id);
  }

  const { data: receipt, error: receiptError } = await admin
    .from("receivable_receipts")
    .insert({
      company_id: companyId,
      receivable_id: receivableId,
      amount,
      received_at: receivedAt,
      bank_account_id: bankAccountId,
      payment_method: mapPaymentMethod(paymentRow.payment_method),
      notes,
      created_by: paymentRow.user_id,
      created_at: approvedAtIso,
    })
    .select("id")
    .single();

  if (receiptError || !receipt?.id) {
    if (!existingApplied.receivableId) {
      await admin.from("accounts_receivable").delete().eq("id", receivableId).eq("company_id", companyId);
    }
    throw new Error(receiptError?.message || "Nao foi possivel criar o recebimento do link.");
  }

  try {
    await insertCashFlow({
      admin,
      companyId,
      bankAccountId,
      receiptId: String(receipt.id),
      amount,
      receivedAt,
      description: `Recebimento link de pagamento: ${receivableDescription}`,
    });
  } catch (error) {
    await admin.from("receivable_receipts").delete().eq("id", receipt.id).eq("company_id", companyId);
    if (!existingApplied.receivableId) {
      await admin.from("accounts_receivable").delete().eq("id", receivableId).eq("company_id", companyId);
    }
    throw error;
  }

  await admin
    .from("payment_link_payments")
    .update({
      metadata: {
        ...metadata,
        accounts_receivable_id: receivableId,
        applied_receipt_id: receipt.id,
      },
      updated_at: new Date().toISOString(),
    })
    .eq("id", paymentLinkPaymentId);

  return {
    receivableId,
    receiptId: String(receipt.id),
  };
}
