"use server";

import { revalidatePath } from "next/cache";
import { AppwriteException, ID, Permission, Role } from "node-appwrite";
import { z } from "zod";

import { logAudit } from "./audit";
import type { LeadActionState } from "./lead-types";
import { DATABASE_ID, TABLES, type Lead, type LeadStatus } from "./schema";
import { createAdminClient } from "./server";
import { requireTenant } from "./tenant-guard";
import { leadSchema } from "@/lib/validation/leads";

function appwriteError(e: unknown): string {
  if (e instanceof AppwriteException) return e.message || "Beklenmeyen bir hata oluştu.";
  return "Bağlantı hatası. Tekrar deneyin.";
}

function flattenErrors(err: z.ZodError): Record<string, string> {
  const out: Record<string, string> = {};
  for (const issue of err.issues) {
    const key = issue.path.join(".");
    if (key && !out[key]) out[key] = issue.message;
  }
  return out;
}

function teamRowPermissions(tenantId: string) {
  return [
    Permission.read(Role.team(tenantId)),
    Permission.update(Role.team(tenantId)),
    Permission.delete(Role.team(tenantId, "owner")),
    Permission.delete(Role.team(tenantId, "admin")),
  ];
}

function pickFormFields(formData: FormData) {
  return {
    name: String(formData.get("name") ?? "").trim(),
    contactName: String(formData.get("contactName") ?? "").trim(),
    email: String(formData.get("email") ?? "").trim(),
    phone: String(formData.get("phone") ?? "").trim(),
    source: String(formData.get("source") ?? "other"),
    status: String(formData.get("status") ?? "cold"),
    estimatedValue: String(formData.get("estimatedValue") ?? ""),
    currency: String(formData.get("currency") ?? "TRY"),
    notes: String(formData.get("notes") ?? "").trim(),
    assigneeId: String(formData.get("assigneeId") ?? ""),
  };
}

export async function createLeadAction(
  _prev: LeadActionState,
  formData: FormData,
): Promise<LeadActionState> {
  let ctx;
  try {
    ctx = await requireTenant();
  } catch {
    return { ok: false, error: "Yetkiniz yok." };
  }

  const parsed = leadSchema.safeParse(pickFormFields(formData));
  if (!parsed.success) {
    return { ok: false, error: "Form geçersiz.", fieldErrors: flattenErrors(parsed.error) };
  }

  try {
    const { tablesDB } = createAdminClient();
    const row = await tablesDB.createRow(
      DATABASE_ID,
      TABLES.leads,
      ID.unique(),
      { tenantId: ctx.tenantId, createdBy: ctx.user.id, ...parsed.data },
      teamRowPermissions(ctx.tenantId),
    );

    await logAudit({
      tenantId: ctx.tenantId,
      userId: ctx.user.id,
      action: "create",
      entityType: "lead",
      entityId: row.$id,
      changes: { name: parsed.data.name, status: parsed.data.status },
    });

    revalidatePath("/leads");
    return { ok: true, leadId: row.$id };
  } catch (e) {
    return { ok: false, error: appwriteError(e) };
  }
}

export async function updateLeadAction(
  _prev: LeadActionState,
  formData: FormData,
): Promise<LeadActionState> {
  const id = String(formData.get("id") ?? "");
  if (!id) return { ok: false, error: "ID eksik." };

  let ctx;
  try {
    ctx = await requireTenant();
  } catch {
    return { ok: false, error: "Yetkiniz yok." };
  }

  const parsed = leadSchema.safeParse(pickFormFields(formData));
  if (!parsed.success) {
    return { ok: false, error: "Form geçersiz.", fieldErrors: flattenErrors(parsed.error) };
  }

  try {
    const { tablesDB } = createAdminClient();
    const existing = (await tablesDB.getRow(DATABASE_ID, TABLES.leads, id)) as unknown as Lead;
    if (existing.tenantId !== ctx.tenantId) return { ok: false, error: "Erişim engellendi." };

    await tablesDB.updateRow(DATABASE_ID, TABLES.leads, id, parsed.data);

    await logAudit({
      tenantId: ctx.tenantId,
      userId: ctx.user.id,
      action: "update",
      entityType: "lead",
      entityId: id,
      changes: parsed.data,
    });

    revalidatePath("/leads");
    return { ok: true, leadId: id };
  } catch (e) {
    return { ok: false, error: appwriteError(e) };
  }
}

export async function moveLeadAction(
  leadId: string,
  status: LeadStatus,
): Promise<LeadActionState> {
  let ctx;
  try {
    ctx = await requireTenant();
  } catch {
    return { ok: false, error: "Yetkiniz yok." };
  }

  try {
    const { tablesDB } = createAdminClient();
    const existing = (await tablesDB.getRow(DATABASE_ID, TABLES.leads, leadId)) as unknown as Lead;
    if (existing.tenantId !== ctx.tenantId) return { ok: false, error: "Erişim engellendi." };

    const prevStatus = existing.status;
    await tablesDB.updateRow(DATABASE_ID, TABLES.leads, leadId, {
      status,
      lastContactAt: new Date().toISOString(),
    });

    // Auto-create a status_change activity
    await tablesDB.createRow(
      DATABASE_ID,
      TABLES.leadActivities,
      ID.unique(),
      {
        tenantId: ctx.tenantId,
        createdBy: ctx.user.id,
        leadId,
        type: "status_change",
        content: `${prevStatus ?? "cold"} → ${status}`,
        occurredAt: new Date().toISOString(),
      },
      [
        Permission.read(Role.team(ctx.tenantId)),
        Permission.update(Role.team(ctx.tenantId)),
        Permission.delete(Role.team(ctx.tenantId, "owner")),
      ],
    );

    revalidatePath("/leads");
    return { ok: true };
  } catch (e) {
    return { ok: false, error: appwriteError(e) };
  }
}

export async function deleteLeadAction(formData: FormData): Promise<LeadActionState> {
  const id = String(formData.get("id") ?? "");
  if (!id) return { ok: false, error: "ID eksik." };

  let ctx;
  try {
    ctx = await requireTenant();
  } catch {
    return { ok: false, error: "Yetkiniz yok." };
  }

  try {
    const { tablesDB } = createAdminClient();
    const existing = (await tablesDB.getRow(DATABASE_ID, TABLES.leads, id)) as unknown as Lead;
    if (existing.tenantId !== ctx.tenantId) return { ok: false, error: "Erişim engellendi." };

    await tablesDB.deleteRow(DATABASE_ID, TABLES.leads, id);

    await logAudit({
      tenantId: ctx.tenantId,
      userId: ctx.user.id,
      action: "delete",
      entityType: "lead",
      entityId: id,
      changes: { name: existing.name },
    });

    revalidatePath("/leads");
    return { ok: true };
  } catch (e) {
    return { ok: false, error: appwriteError(e) };
  }
}

export async function convertLeadToCustomerAction(formData: FormData): Promise<LeadActionState> {
  const leadId = String(formData.get("leadId") ?? "");
  if (!leadId) return { ok: false, error: "Lead ID eksik." };

  let ctx;
  try {
    ctx = await requireTenant();
  } catch {
    return { ok: false, error: "Yetkiniz yok." };
  }

  try {
    const { tablesDB } = createAdminClient();
    const lead = (await tablesDB.getRow(DATABASE_ID, TABLES.leads, leadId)) as unknown as Lead;
    if (lead.tenantId !== ctx.tenantId) return { ok: false, error: "Erişim engellendi." };

    const permissions = teamRowPermissions(ctx.tenantId);

    // Create customer from lead data
    const customer = await tablesDB.createRow(
      DATABASE_ID,
      TABLES.customers,
      ID.unique(),
      {
        tenantId: ctx.tenantId,
        createdBy: ctx.user.id,
        name: lead.contactName || lead.name,
        email: lead.email,
        phone: lead.phone,
        notes: lead.notes,
        status: "active",
      },
      permissions,
    );

    // Update lead: mark converted + link customerId
    await tablesDB.updateRow(DATABASE_ID, TABLES.leads, leadId, {
      status: "converted",
      customerId: customer.$id,
      lastContactAt: new Date().toISOString(),
    });

    await tablesDB.createRow(
      DATABASE_ID,
      TABLES.leadActivities,
      ID.unique(),
      {
        tenantId: ctx.tenantId,
        createdBy: ctx.user.id,
        leadId,
        type: "status_change",
        content: `Müşteriye dönüştürüldü → ${lead.contactName || lead.name}`,
        occurredAt: new Date().toISOString(),
      },
      permissions,
    );

    await logAudit({
      tenantId: ctx.tenantId,
      userId: ctx.user.id,
      action: "create",
      entityType: "customer_from_lead",
      entityId: customer.$id,
      changes: { leadId, customerId: customer.$id },
    });

    revalidatePath("/leads");
    revalidatePath("/customers");
    return { ok: true, leadId: customer.$id };
  } catch (e) {
    return { ok: false, error: appwriteError(e) };
  }
}
