"use server";

import { headers } from "next/headers";
import { redirect } from "next/navigation";
import { ID, Query } from "node-appwrite";

import { DATABASE_ID, TABLES, type TenantPlan, type PlanPeriod, type PaymentEvent } from "./schema";
import { createAdminClient } from "./server";
import { requireRole, requireTenant } from "./tenant-guard";
import { getEffectivePlan } from "./plan-limits";
import { PLAN_CATALOG, PLAN_RANK, planPrice, validateDiscountCode } from "./subscription-types";
import { getShopierPlanUrl, isShopierEnabled } from "../payments/shopier";
import { createPolarCheckout, isPolarEnabled } from "../payments/polar";
import { getPayTRToken } from "../payments/paytr";

function generateOrderId(): string {
  const t = Date.now().toString(36);
  const r = Math.random().toString(36).slice(2, 10);
  return `ord_${t}_${r}`;
}

// Webhook handler'larından da çağrılabilir — provider "polar" | "shopier" | "paytr" | "mock"
export async function activatePlanInDb(
  tenantId: string,
  plan: TenantPlan,
  provider: string,
  period: PlanPeriod = "monthly",
  opts?: { amount?: number; orderId?: string; discountCode?: string },
): Promise<void> {
  const { tablesDB } = createAdminClient();

  const result = await tablesDB.listRows({
    databaseId: DATABASE_ID,
    tableId: TABLES.tenantSettings,
    queries: [Query.equal("tenantId", tenantId), Query.limit(1)],
  });
  const row = result.rows[0];
  if (!row) throw new Error(`tenant_settings bulunamadı: ${tenantId}`);

  const validityDays = period === "yearly" ? 365 : 30;
  const now = new Date();
  const expires = new Date(now.getTime() + validityDays * 24 * 60 * 60 * 1000);

  await tablesDB.updateRow(DATABASE_ID, TABLES.tenantSettings, row.$id, {
    plan,
    planPeriod: period,
    planExpiresAt: expires.toISOString(),
    planProvider: provider,
  });

  // Ödeme geçmişi kaydı
  if (plan !== "free" && opts?.amount != null) {
    try {
      const eventData: Record<string, unknown> = {
        tenantId,
        plan,
        period,
        amount: opts.amount,
        provider,
      };
      if (opts.orderId) eventData.orderId = opts.orderId;
      if (opts.discountCode) eventData.discountCode = opts.discountCode;
      await tablesDB.createRow(DATABASE_ID, TABLES.paymentEvents, ID.unique(), eventData);
    } catch {
      // best-effort — ödeme aktivasyonunu bloke etme
    }
  }
}

export async function deactivatePlanInDb(tenantId: string): Promise<void> {
  const { tablesDB } = createAdminClient();
  const result = await tablesDB.listRows({
    databaseId: DATABASE_ID,
    tableId: TABLES.tenantSettings,
    queries: [Query.equal("tenantId", tenantId), Query.limit(1)],
  });
  const row = result.rows[0];
  if (!row) return;
  await tablesDB.updateRow(DATABASE_ID, TABLES.tenantSettings, row.$id, {
    plan: "free",
    planExpiresAt: null,
    planProvider: null,
  });
}

function assertUpgrade(currentPlan: TenantPlan, targetPlan: TenantPlan) {
  if (PLAN_RANK[targetPlan] <= PLAN_RANK[currentPlan]) {
    throw new Error("Yalnızca daha üst bir plana geçiş yapabilirsiniz.");
  }
}

/** Returns prorated price to charge when upgrading mid-cycle. Min 1 TRY. */
function calculateProration(
  currentPlan: TenantPlan,
  currentPeriod: PlanPeriod,
  planExpiresAt: string | undefined | null,
  newPlanPrice: number,
): number {
  if (!planExpiresAt || currentPlan === "free") return newPlanPrice;
  const currentEntry = PLAN_CATALOG[currentPlan as Exclude<TenantPlan, "free">];
  if (!currentEntry) return newPlanPrice;

  const periodDays = currentPeriod === "yearly" ? 365 : 30;
  const msRemaining = new Date(planExpiresAt).getTime() - Date.now();
  const daysRemaining = Math.max(0, msRemaining / (1000 * 60 * 60 * 24));
  const unusedFraction = Math.min(1, daysRemaining / periodDays);
  const credit = planPrice(currentEntry, currentPeriod) * unusedFraction;
  return Math.max(1, Math.round(newPlanPrice - credit));
}

// ── Mock checkout (geliştirme ortamı) ─────────────────────────────────────────

export async function startMockCheckoutAction(formData: FormData): Promise<void> {
  const plan = String(formData.get("plan") ?? "") as TenantPlan;
  if (!["starter", "pro", "enterprise"].includes(plan)) throw new Error("Geçersiz plan.");

  const ctx = await requireTenant();
  requireRole(ctx, ["owner"]);
  assertUpgrade(getEffectivePlan(ctx), plan as TenantPlan);

  const catalog = PLAN_CATALOG[plan as Exclude<TenantPlan, "free">];
  const period = String(formData.get("period") ?? "monthly") as PlanPeriod;
  const amount = planPrice(catalog, period);
  await activatePlanInDb(ctx.tenantId, plan as TenantPlan, "mock", period, { amount });
  redirect("/settings/billing?upgraded=1");
}

// ── Shopier checkout ───────────────────────────────────────────────────────────

export async function startShopierCheckoutAction(formData: FormData): Promise<void> {
  const plan = String(formData.get("plan") ?? "") as TenantPlan;
  if (!["starter", "pro"].includes(plan)) throw new Error("Geçersiz plan.");

  const ctx = await requireTenant();
  requireRole(ctx, ["owner"]);
  assertUpgrade(getEffectivePlan(ctx), plan as TenantPlan);

  const storeUrl = getShopierPlanUrl(plan);
  if (!storeUrl) throw new Error("Shopier mağaza URL'i ayarlanmamış.");

  redirect(storeUrl);
}

// ── Polar checkout ─────────────────────────────────────────────────────────────

export async function startPolarCheckoutAction(formData: FormData): Promise<void> {
  const plan = String(formData.get("plan") ?? "") as TenantPlan;
  if (!["starter", "pro"].includes(plan)) throw new Error("Geçersiz plan.");

  const ctx = await requireTenant();
  requireRole(ctx, ["owner"]);
  assertUpgrade(getEffectivePlan(ctx), plan as TenantPlan);

  const catalog = PLAN_CATALOG[plan as Exclude<TenantPlan, "free">];
  const orderId = generateOrderId();
  const appUrl = process.env.APP_URL?.replace(/\/$/, "") ?? "http://localhost:3001";

  const checkout = await createPolarCheckout({
    orderId,
    tenantId: ctx.tenantId,
    userEmail: ctx.user.email,
    successUrl: `${appUrl}/settings/billing?upgraded=1`,
  });

  void catalog;
  redirect(checkout.url);
}

// ── PayTR checkout ─────────────────────────────────────────────────────────────

export async function getPayTRTokenAction(formData: FormData): Promise<string> {
  const planId = String(formData.get("plan") ?? "") as Exclude<TenantPlan, "free">;
  const period = String(formData.get("period") ?? "monthly") as PlanPeriod;
  const discountCodeRaw = String(formData.get("discountCode") ?? "").trim();

  if (!["starter", "pro", "enterprise"].includes(planId)) throw new Error("Geçersiz plan.");
  if (!["monthly", "yearly"].includes(period)) throw new Error("Geçersiz dönem.");

  const ctx = await requireTenant();
  requireRole(ctx, ["owner"]);

  const currentPlan = getEffectivePlan(ctx);
  assertUpgrade(currentPlan, planId as TenantPlan);

  const catalog = PLAN_CATALOG[planId];
  let price = planPrice(catalog, period);

  // Proration: credit for unused days on current paid plan
  price = calculateProration(
    currentPlan,
    ctx.settings?.planPeriod ?? "monthly",
    ctx.settings?.planExpiresAt,
    price,
  );

  // Discount code
  if (discountCodeRaw) {
    const discountFraction = validateDiscountCode(discountCodeRaw);
    if (!discountFraction) throw new Error("Geçersiz indirim kodu.");
    price = Math.max(1, Math.round(price * (1 - discountFraction)));
  }

  // APP_URL: server-to-server callback (HTTPS zorunlu, prod'da veya ngrok)
  // APP_BROWSER_URL: browser redirect (dev'de localhost, prod'da aynı domain)
  const appUrl = process.env.APP_URL?.replace(/\/$/, "") ?? "http://localhost:3000";
  const browserUrl = (process.env.APP_BROWSER_URL ?? appUrl).replace(/\/$/, "");

  const requestHeaders = await headers();
  const userIp =
    requestHeaders.get("x-forwarded-for")?.split(",")[0]?.trim() ??
    requestHeaders.get("x-real-ip") ??
    "1.2.3.4";

  const timestamp = Date.now().toString();
  const random = Math.random().toString(36).slice(2, 8);
  // Uppercase harfler separator — tenantId (lowercase a-z0-9) hiçbir zaman içermez
  // Format: {tenantId}T{timestamp}{random}P{plan}X{period}
  const merchantOid = `${ctx.tenantId}T${timestamp}${random}P${planId}X${period}`;

  const discountLabel = discountCodeRaw ? ` + ${discountCodeRaw.toUpperCase()} İndirimi` : "";
  const userBasket: Array<[string, string, number]> = [
    [
      `KovakEmlak ${catalog.name} (${period === "yearly" ? "Yıllık" : "Aylık"})${discountLabel}`,
      price.toFixed(2),
      1,
    ],
  ];

  const officeName = ctx.settings?.officeName ?? ctx.user.name ?? "Müşteri";

  return getPayTRToken({
    merchantOid,
    email: ctx.user.email,
    userName: officeName,
    userAddress: ctx.settings?.address ?? "Türkiye",
    userPhone: ctx.settings?.phone ?? "05000000000",
    paymentAmountKurus: price * 100,
    userBasket,
    userIp,
    notifyUrl: `${appUrl}/api/payments/paytr/callback`,
    okUrl: `${browserUrl}/settings/billing?upgraded=1`,
    failUrl: `${browserUrl}/settings/billing?failed=1`,
  });
}

// ── Unified entry point (Polar/Shopier only — PayTR uses getPayTRTokenAction) ──

export async function startCheckoutAction(formData: FormData): Promise<void> {
  if (isPolarEnabled()) return startPolarCheckoutAction(formData);
  if (isShopierEnabled()) return startShopierCheckoutAction(formData);
  return startMockCheckoutAction(formData);
}

// ── Enterprise inquiry ─────────────────────────────────────────────────────────

export async function requestEnterpriseInquiryAction(
  formData: FormData,
): Promise<{ ok: boolean; error?: string }> {
  const ctx = await requireTenant();
  requireRole(ctx, ["owner"]);

  const officeName = ctx.settings?.officeName ?? ctx.user.name ?? "Bilinmiyor";
  const userEmail = ctx.user.email;
  const tenantId = ctx.tenantId;

  const teamSize = String(formData.get("teamSize") ?? "").trim();
  const listingCount = String(formData.get("listingCount") ?? "").trim();
  const needsCustomDev = String(formData.get("needsCustomDev") ?? "").trim();
  const notes = String(formData.get("notes") ?? "").trim();

  if (!teamSize || !listingCount || !needsCustomDev) {
    return { ok: false, error: "Lütfen tüm zorunlu alanları doldurun." };
  }

  const customDevLabel = needsCustomDev === "yes" ? "Evet" : needsCustomDev === "no" ? "Hayır" : "Belirsiz";

  try {
    const { messaging } = createAdminClient();

    // Confirmation email to the tenant owner
    await messaging.createEmail(
      `enterprise-inquiry-${tenantId}-${Date.now()}`,
      "Enterprise Plan Talebiniz Alındı — KovakEmlak",
      `<p>Merhaba ${officeName},</p>
<p>Enterprise plan talebiniz alındı. Ekibimiz en kısa sürede <strong>${userEmail}</strong> adresine size ulaşacak.</p>
<table style="border-collapse:collapse;margin:16px 0;font-size:14px;">
  <tr><td style="padding:6px 12px 6px 0;color:#888;">Ofis adı</td><td style="padding:6px 0"><strong>${officeName}</strong></td></tr>
  <tr><td style="padding:6px 12px 6px 0;color:#888;">Ekip büyüklüğü</td><td style="padding:6px 0"><strong>${teamSize} kişi</strong></td></tr>
  <tr><td style="padding:6px 12px 6px 0;color:#888;">Aktif ilan sayısı</td><td style="padding:6px 0"><strong>${listingCount}</strong></td></tr>
  <tr><td style="padding:6px 12px 6px 0;color:#888;">Özel modül geliştirme</td><td style="padding:6px 0"><strong>${customDevLabel}</strong></td></tr>
  ${notes ? `<tr><td style="padding:6px 12px 6px 0;color:#888;vertical-align:top;">Notlar</td><td style="padding:6px 0">${notes}</td></tr>` : ""}
</table>
<p style="color:#888;font-size:12px;">Bu e-posta otomatik olarak gönderilmiştir.</p>`,
      [],
      [ctx.user.id],
      [],
    );
  } catch {
    // Email gönderimi başarısız olsa bile talebi kabul et
  }

  return { ok: true };
}

// ── Downgrade (engellendi) ─────────────────────────────────────────────────────

export async function downgradeToFreeAction(): Promise<void> {
  // Ücretli plandan ücretsiz plana geçiş devre dışı.
  // Abonelik iptali için destek hattıyla iletişime geçin.
  throw new Error("Ücretli plandan ücretsiz plana geçiş yapılamaz. Abonelik iptali için info@kovakyazilim.com ile iletişime geçin.");
}

// ── Mevcut plan bilgisi ────────────────────────────────────────────────────────

export async function getCurrentPlanAction(): Promise<{
  plan: TenantPlan;
  expiresAt: string | null;
  provider: string | null;
}> {
  const ctx = await requireTenant();
  const plan = getEffectivePlan(ctx);
  return {
    plan,
    expiresAt: ctx.settings?.planExpiresAt ?? null,
    provider: ctx.settings?.planProvider ?? null,
  };
}

// ── Ödeme geçmişi (sadece owner) ──────────────────────────────────────────────

export async function getPaymentHistoryAction(): Promise<PaymentEvent[]> {
  const ctx = await requireTenant();
  requireRole(ctx, ["owner"]);

  const { tablesDB } = createAdminClient();
  const result = await tablesDB.listRows({
    databaseId: DATABASE_ID,
    tableId: TABLES.paymentEvents,
    queries: [
      Query.equal("tenantId", ctx.tenantId),
      Query.orderDesc("$createdAt"),
      Query.limit(50),
    ],
  });

  return result.rows as unknown as PaymentEvent[];
}
