import { revalidatePath } from "next/cache";
import { redirect } from "next/navigation";

import {
  RoleCode,
  OptInStatus,
  TemplateApprovalStatus,
  CampaignStatus,
  CampaignAudienceType,
  CampaignType,
  AuthTokenType,
  UserStatus,
  TenantStatus,
  ChannelStatus
} from "@prisma/client";

import { getSession, hashPassword, verifyPassword } from "@/lib/auth";
import { getRequestAuditContext, writeAuditTrail } from "@/lib/audit";
import { createAuthToken } from "@/lib/auth-tokens";
import { prisma } from "@/lib/prisma";
import { assertPermission, type ActionPermission } from "@/lib/permissions";
import { dispatchCampaignById } from "@/lib/campaign-dispatch-service";
import { sendTransactionalNotification } from "@/lib/notification";
import { makeInviteUrl } from "@/lib/auth-tokens";

import { randomBytes } from "node:crypto";

function formValue(formData: FormData, name: string, fallback = "") {
  const value = formData.get(name);
  return typeof value === "string" ? value.trim() : fallback;
}

function parseSegmentRules(raw: string) {
  if (!raw) {
    return {
      description: null as string | null,
      rulesJson: null as string | null
    };
  }

  const trimmed = raw.trim();
  if (!trimmed) {
    return {
      description: null as string | null,
      rulesJson: null as string | null
    };
  }

  try {
    const parsed = JSON.parse(trimmed);
    return {
      description: null as string | null,
      rulesJson: JSON.stringify(parsed)
    };
  } catch {
    return {
      description: trimmed,
      rulesJson: null
    };
  }
}

function isValidTenantStatus(value: string) {
  return Object.prototype.hasOwnProperty.call(TenantStatus, value);
}

function isValidChannelStatus(value: string) {
  return Object.prototype.hasOwnProperty.call(ChannelStatus, value);
}

async function requireSuperAdminSession() {
  const session = await getSession();

  if (!session) {
    redirect("/login");
  }

  if (session.role !== "super_admin") {
    await writePermissionDeniedAudit({
      session,
      permission: "admin:manage",
      action: "super_admin_access"
    });
    redirect("/unauthorized");
  }

  return session;
}

async function writePermissionDeniedAudit(data: {
  session: { tenantId: string; userId: string };
  permission: ActionPermission | "super_admin";
  action: string;
}) {
  const requestContext = await getRequestAuditContext();
  await writeAuditTrail({
    tenantId: data.session.tenantId,
    actorUserId: data.session.userId,
    entityType: "user",
    entityId: data.session.userId,
    action: "permission_denied",
    metadata: {
      action: data.action,
      permission: data.permission
    },
    ipAddress: requestContext.ipAddress,
    userAgent: requestContext.userAgent
  });
}

async function requireAdminManageSession() {
  const session = await getSession();
  if (!session) {
    redirect("/login");
  }

  if (!assertPermission(session.role, "admin:manage", session.extraPermissions)) {
    await writePermissionDeniedAudit({
      session,
      permission: "admin:manage",
      action: "admin_manage_required"
    });
    redirect("/unauthorized");
  }

  return session;
}

async function requireProfileManageSession() {
  const session = await getSession();
  if (!session) {
    redirect("/login");
  }

  if (
    !assertPermission(session.role, "admin:manage", session.extraPermissions) &&
    !assertPermission(session.role, "agent:manage", session.extraPermissions) &&
    !assertPermission(session.role, "profile:manage_self", session.extraPermissions)
  ) {
    await writePermissionDeniedAudit({
      session,
      permission: "profile:manage_self",
      action: "profile_manage_required"
    });
    redirect("/unauthorized");
  }

  return session;
}

type AuditActorSession = {
  tenantId: string;
  userId: string;
};

async function getAuditContext(session: AuditActorSession) {
  const requestContext = await getRequestAuditContext();
  return {
    tenantId: session.tenantId,
    actorUserId: session.userId,
    ipAddress: requestContext.ipAddress,
    userAgent: requestContext.userAgent
  };
}

export async function createContact(formData: FormData) {
  const session = await requireAdminManageSession();
  const tenantId = session.tenantId;
  const auditContext = await getAuditContext(session);

  const fullName = formValue(formData, "fullName");
  const phoneNumber = formValue(formData, "phoneNumber");
  const email = formValue(formData, "email") || null;
  const countryCode = formValue(formData, "countryCode") || null;
  const channelId = formValue(formData, "channelId");
  const optInStatus = (formValue(formData, "optInStatus") as OptInStatus) || OptInStatus.UNKNOWN;
  const tagsRaw = formValue(formData, "tags");

  if (!fullName || !phoneNumber) {
    redirect("/contacts?error=missing_fields");
  }

  if (channelId) {
    const channel = await prisma.channel.findFirst({
      where: { id: channelId, tenantId }
    });
    if (!channel) {
      redirect("/contacts/new?error=invalid_channel");
    }
  }

  const contact = await prisma.contact.create({
    data: {
      tenantId,
      fullName,
      phoneNumber,
      email: email || null,
      countryCode: countryCode || null,
      optInStatus,
      channelId: channelId || null,
      lastInteractionAt: new Date()
    }
  });

  const tags = tagsRaw
    .split(",")
    .map((tag) => tag.trim())
    .filter(Boolean);
  const dedupedTags = [...new Set(tags)];

  for (const name of dedupedTags) {
    const tag = await prisma.tag.upsert({
      where: {
        tenantId_name: {
          tenantId,
          name
        }
      },
      create: {
        tenantId,
        name
      },
      update: {}
    });

    await prisma.contactTag.create({
      data: {
        tenantId,
        contactId: contact.id,
        tagId: tag.id
      }
    });
  }

  await writeAuditTrail({
    ...auditContext,
    entityType: "contact",
    entityId: contact.id,
    action: "create_contact",
    metadata: {
      fullName,
      phoneNumber,
      email,
      countryCode,
      optInStatus,
      channelId: channelId || null,
      tags: dedupedTags
    }
  });

  revalidatePath("/contacts");
  redirect("/contacts");
}

export async function updateContact(formData: FormData) {
  const session = await requireAdminManageSession();
  const tenantId = session.tenantId;
  const auditContext = await getAuditContext(session);

  const id = formValue(formData, "contactId");
  const fullName = formValue(formData, "fullName");
  const phoneNumber = formValue(formData, "phoneNumber");
  const email = formValue(formData, "email") || null;
  const countryCode = formValue(formData, "countryCode") || null;
  const channelId = formValue(formData, "channelId");
  const optInStatus = (formValue(formData, "optInStatus") as OptInStatus) || OptInStatus.UNKNOWN;
  const tagsRaw = formValue(formData, "tags");

  if (!id || !fullName || !phoneNumber) {
    redirect("/contacts?error=missing_fields");
  }

  const contact = await prisma.contact.findFirst({
    where: { id, tenantId }
  });

  if (!contact) {
    redirect("/contacts?error=contact_not_found");
  }

  if (channelId) {
    const channel = await prisma.channel.findFirst({
      where: { id: channelId, tenantId }
    });
    if (!channel) {
      redirect(`/contacts/${id}/edit?error=invalid_channel`);
    }
  }

  await prisma.contact.update({
    where: { id },
    data: {
      fullName,
      phoneNumber,
      email,
      countryCode,
      optInStatus,
      channelId: channelId || null
    }
  });

  await prisma.contactTag.deleteMany({
    where: { contactId: id }
  });

  const tags = tagsRaw
    .split(",")
    .map((tag) => tag.trim())
    .filter(Boolean);
  const dedupedTags = [...new Set(tags)];

  for (const name of dedupedTags) {
    const tag = await prisma.tag.upsert({
      where: {
        tenantId_name: {
          tenantId,
          name
        }
      },
      create: { tenantId, name },
      update: {}
    });

    await prisma.contactTag.create({
      data: {
        tenantId,
        contactId: id,
        tagId: tag.id
      }
    });
  }

  await writeAuditTrail({
    ...auditContext,
    entityType: "contact",
    entityId: id,
    action: "update_contact",
    metadata: {
      fullName,
      phoneNumber,
      email,
      countryCode,
      optInStatus,
      channelId: channelId || null,
      tags: dedupedTags,
      previousData: {
        previousFullName: contact.fullName,
        previousPhoneNumber: contact.phoneNumber,
        previousEmail: contact.email,
        previousCountryCode: contact.countryCode,
        previousOptInStatus: contact.optInStatus,
        previousChannelId: contact.channelId
      }
    }
  });

  revalidatePath("/contacts");
  revalidatePath(`/contacts/${id}`);
  redirect(`/contacts/${id}`);
}

export async function deleteContact(formData: FormData) {
  const session = await requireAdminManageSession();
  const tenantId = session.tenantId;
  const auditContext = await getAuditContext(session);

  const id = formValue(formData, "contactId");
  if (!id) {
    redirect("/contacts?error=missing_contact_id");
  }

  const contact = await prisma.contact.findFirst({
    where: { id, tenantId }
  });
  if (!contact) {
    redirect("/contacts?error=contact_not_found");
  }

  const conversationCount = await prisma.conversation.count({
    where: { contactId: id }
  });

  if (conversationCount > 0) {
    redirect("/contacts?error=contact_has_conversations");
  }

  await prisma.$transaction([
    prisma.contactTag.deleteMany({ where: { contactId: id, tenantId } }),
    prisma.contact.delete({ where: { id } })
  ]);

  await writeAuditTrail({
    ...auditContext,
    entityType: "contact",
    entityId: id,
    action: "delete_contact",
    metadata: {
      fullName: contact.fullName,
      phoneNumber: contact.phoneNumber,
      hasConversations: conversationCount > 0
    }
  });

  revalidatePath("/contacts");
  redirect("/contacts");
}

export async function createTeamUser(formData: FormData) {
  const session = await requireAdminManageSession();
  const tenantId = session.tenantId;
  const auditContext = await getAuditContext(session);

  const fullName = formValue(formData, "fullName");
  const email = formValue(formData, "email");
  const roleId = formValue(formData, "roleId");
  const status = (formValue(formData, "status") as UserStatus) || UserStatus.INVITED;
  const password = formValue(formData, "password");

  if (!fullName || !email || !roleId) {
    redirect("/team/new?error=missing_fields");
  }

  if (status === UserStatus.ACTIVE && !password) {
    redirect("/team/new?error=missing_fields");
  }

  const role = await prisma.role.findFirst({
    where: { id: roleId, tenantId, code: { in: [RoleCode.ADMIN_CLIENT, RoleCode.AGENT] } }
  });
  if (!role) {
    redirect("/team/new?error=invalid_role");
  }

  const initialPassword = password || randomBytes(20).toString("hex");

  const createdUser = await prisma.user.create({
    data: {
      tenantId,
      fullName,
      email,
      roleId,
      status,
      passwordHash: await hashPassword(initialPassword)
    }
  });

  if (status === UserStatus.INVITED) {
    const invite = await createAuthToken({
      userId: createdUser.id,
      tenantId,
      tokenType: AuthTokenType.INVITE_ACCEPTANCE,
      createdByUserId: session.userId,
      metadata: { source: "team_invitation" }
    });
    const inviteUrl = makeInviteUrl(invite.rawToken);

    const inviteNotification = await sendTransactionalNotification({
      to: email,
      subject: `Undangan akun: ${fullName}`,
      text: `Anda diundang masuk ke tenant ${session.tenantId}. Klik tautan ini untuk mengaktifkan akun Anda: ${inviteUrl}`,
      html: `<p>Anda diundang masuk ke tenant <b>${tenantId}</b>.</p><p>Aktifkan akun Anda di sini: <a href="${inviteUrl}">${inviteUrl}</a></p>`,
      metadata: { tenantId, type: "team_invite" }
    });

    if (!inviteNotification.ok && process.env.NODE_ENV !== "production") {
      console.error(`Invite notification failed for ${email}: ${inviteNotification.error ?? "unknown"}`);
    }

    await writeAuditTrail({
      ...auditContext,
      entityType: "user",
      entityId: createdUser.id,
      action: "team_user_invite_sent",
      metadata: {
        email,
        fullName,
        inviteStatus: inviteNotification.ok ? "queued" : "failed",
        inviteError: inviteNotification.ok ? null : inviteNotification.error ?? null,
        source: "team_user"
      }
    });
  }

  await writeAuditTrail({
    ...auditContext,
    entityType: "user",
    entityId: createdUser.id,
    action: "create_team_user",
    metadata: {
      fullName,
      email,
      roleId,
      status,
      roleCode: role.code
    }
  });

  revalidatePath("/team");
  redirect("/team");
}

export async function updateTeamUser(formData: FormData) {
  const session = await requireAdminManageSession();
  const tenantId = session.tenantId;
  const auditContext = await getAuditContext(session);

  const id = formValue(formData, "userId");
  const fullName = formValue(formData, "fullName");
  const email = formValue(formData, "email");
  const roleId = formValue(formData, "roleId");
  const status = (formValue(formData, "status") as UserStatus) || UserStatus.INVITED;
  const password = formValue(formData, "password");

  if (!id || !fullName || !email || !roleId) {
    redirect("/team?error=missing_fields");
  }

  const user = await prisma.user.findFirst({
    where: { id, tenantId },
    include: { role: true }
  });
  if (!user) {
    redirect("/team?error=user_not_found");
  }

  const role = await prisma.role.findFirst({
    where: { id: roleId, tenantId, code: { in: [RoleCode.ADMIN_CLIENT, RoleCode.AGENT] } }
  });
  if (!role) {
    redirect(`/team/${id}/edit?error=invalid_role`);
  }

  const updateData: {
    fullName: string;
    email: string;
    roleId: string;
    status: UserStatus;
    passwordHash?: string;
  } = {
    fullName,
    email,
    roleId,
    status
  };

  if (password) {
    updateData.passwordHash = await hashPassword(password);
  }

  await prisma.user.update({
    where: { id },
    data: updateData
  });

  await writeAuditTrail({
    ...auditContext,
    entityType: "user",
    entityId: id,
    action: "update_team_user",
    metadata: {
      fullName,
      email,
      roleId,
      status,
      passwordChanged: Boolean(password)
    }
  });

  revalidatePath("/team");
  revalidatePath(`/team/${id}`);
  redirect(`/team/${id}`);
}

export async function deleteTeamUser(formData: FormData) {
  const session = await requireAdminManageSession();
  const tenantId = session.tenantId;
  const auditContext = await getAuditContext(session);

  const id = formValue(formData, "userId");
  if (!id) {
    redirect("/team?error=missing_user_id");
  }

  if (id === session.userId) {
    redirect("/team?error=self_delete_not_allowed");
  }

  const user = await prisma.user.findFirst({
    where: { id, tenantId },
    include: { role: true }
  });
  if (!user) {
    redirect("/team?error=user_not_found");
  }

  const campaignCount = await prisma.broadcastCampaign.count({
    where: { createdByUserId: id }
  });
  if (campaignCount > 0) {
    redirect("/team?error=user_has_campaigns");
  }

  await prisma.$transaction([
    prisma.conversation.updateMany({ where: { assignedUserId: id }, data: { assignedUserId: null } }),
    prisma.conversationNote.deleteMany({ where: { userId: id } }),
    prisma.conversationActivity.deleteMany({ where: { actorUserId: id } }),
    prisma.message.updateMany({ where: { sentByUserId: id }, data: { sentByUserId: null } }),
    prisma.user.delete({ where: { id } })
  ]);

  await writeAuditTrail({
    ...auditContext,
    entityType: "user",
    entityId: id,
    action: "delete_team_user",
    metadata: {
      deletedEmail: user.email,
      deletedName: user.fullName,
      roleCode: user.role.code
    }
  });

  revalidatePath("/team");
  redirect("/team");
}

export async function createTemplate(formData: FormData) {
  const session = await requireAdminManageSession();
  const tenantId = session.tenantId;
  const auditContext = await getAuditContext(session);

  const name = formValue(formData, "name");
  const category = formValue(formData, "category");
  const languageCode = formValue(formData, "languageCode");
  const bodyText = formValue(formData, "bodyText");
  const channelId = formValue(formData, "channelId");
  const templateType = formValue(formData, "templateType") || "text";

  if (!name || !category || !languageCode || !bodyText || !channelId) {
    redirect("/templates/new?error=missing_fields");
  }

  const channel = await prisma.channel.findFirst({
    where: { id: channelId, tenantId }
  });
  if (!channel) {
    redirect("/templates/new?error=invalid_channel");
  }

  const template = await prisma.messageTemplate.create({
    data: {
      tenantId,
      channelId,
      name,
      category,
      languageCode,
      templateType,
      bodyText,
      approvalStatus: TemplateApprovalStatus.DRAFT
    }
  });

  await writeAuditTrail({
    ...auditContext,
    entityType: "message_template",
    entityId: template.id,
    action: "create_template",
    metadata: {
      name,
      category,
      languageCode,
      templateType,
      channelId
    }
  });

  revalidatePath("/templates");
  redirect("/templates");
}

export async function updateTemplate(formData: FormData) {
  const session = await requireAdminManageSession();
  const tenantId = session.tenantId;
  const auditContext = await getAuditContext(session);

  const id = formValue(formData, "templateId");
  const name = formValue(formData, "name");
  const category = formValue(formData, "category");
  const languageCode = formValue(formData, "languageCode");
  const bodyText = formValue(formData, "bodyText");
  const channelId = formValue(formData, "channelId");

  if (!id || !name || !category || !languageCode || !bodyText || !channelId) {
    redirect("/templates?error=missing_fields");
  }

  const template = await prisma.messageTemplate.findFirst({
    where: { id, tenantId }
  });
  if (!template) {
    redirect("/templates?error=template_not_found");
  }

  await prisma.messageTemplate.update({
    where: { id },
    data: {
      name,
      category,
      languageCode,
      bodyText,
      channelId
    }
  });

  await writeAuditTrail({
    ...auditContext,
    entityType: "message_template",
    entityId: id,
    action: "update_template",
    metadata: {
      name,
      category,
      languageCode,
      bodyText,
      channelId
    }
  });

  revalidatePath("/templates");
  revalidatePath(`/templates/${id}`);
  redirect(`/templates/${id}`);
}

export async function deleteTemplate(formData: FormData) {
  const session = await requireAdminManageSession();
  const tenantId = session.tenantId;
  const auditContext = await getAuditContext(session);

  const id = formValue(formData, "templateId");
  if (!id) {
    redirect("/templates?error=missing_template_id");
  }

  const template = await prisma.messageTemplate.findFirst({
    where: { id, tenantId }
  });
  if (!template) {
    redirect("/templates?error=template_not_found");
  }

  const recipientCount = await prisma.broadcastCampaign.count({
    where: { templateId: id }
  });
  if (recipientCount > 0) {
    redirect("/templates?error=template_in_use");
  }

  await prisma.messageTemplate.delete({
    where: { id }
  });

  await writeAuditTrail({
    ...auditContext,
    entityType: "message_template",
    entityId: id,
    action: "delete_template",
    metadata: {
      reason: "manual_delete"
    }
  });

  revalidatePath("/templates");
  redirect("/templates");
}

export async function dispatchCampaign(formData: FormData) {
  const session = await requireAdminManageSession();
  const tenantId = session.tenantId;
  const auditContext = await getAuditContext(session);
  const campaignId = formValue(formData, "campaignId");
  if (!campaignId) {
    redirect("/campaigns?error=missing_campaign_id");
  }

  const { ipAddress, userAgent } = await getRequestAuditContext();

  const summary = await dispatchCampaignById({
    campaignId,
    tenantId,
    actorUserId: session.userId,
    actorIpAddress: ipAddress,
    actorUserAgent: userAgent,
    source: "manual"
  });

  if (summary.skippedReason === "campaign_not_found") {
    redirect("/campaigns?error=campaign_not_found");
  }

  revalidatePath("/campaigns");
  revalidatePath(`/campaigns/${campaignId}`);
  revalidatePath(`/campaigns/${campaignId}/recipients`);

  if (summary.skippedReason === "campaign_not_ready") {
    await writeAuditTrail({
      ...auditContext,
      entityType: "campaign",
      entityId: campaignId,
      action: "campaign_dispatch_blocked",
      metadata: {
        reason: summary.skippedReason,
        attempt: "manual"
      }
    });
    redirect("/campaigns?error=campaign_not_ready");
  }

  if (summary.skippedReason === "no_recipients") {
    await writeAuditTrail({
      ...auditContext,
      entityType: "campaign",
      entityId: campaignId,
      action: "campaign_dispatch_blocked",
      metadata: {
        reason: summary.skippedReason,
        attempt: "manual"
      }
    });
    redirect("/campaigns?error=no_recipients");
  }

  if (summary.idle) {
    await writeAuditTrail({
      ...auditContext,
      entityType: "campaign",
      entityId: campaignId,
      action: "campaign_dispatch_executed_noop",
      metadata: {
        reason: "idle",
        attempt: "manual",
        seededRecipients: summary.seededRecipients,
        processableRecipients: summary.processableRecipients
      }
    });
    redirect(`/campaigns/${campaignId}?dispatch=idle`);
  }

  await writeAuditTrail({
    ...auditContext,
    entityType: "campaign",
    entityId: campaignId,
    action: "campaign_dispatch_executed",
    metadata: {
      attempt: "manual",
      seededRecipients: summary.seededRecipients,
      processableRecipients: summary.processableRecipients,
      attempted: summary.attempted,
      successful: summary.successful,
      failed: summary.failed
    }
  });

  redirect(`/campaigns/${campaignId}?dispatch=done`);
}

export async function createCampaign(formData: FormData) {
  const session = await requireAdminManageSession();
  const tenantId = session.tenantId;
  const auditContext = await getAuditContext(session);

  const name = formValue(formData, "name");
  const channelId = formValue(formData, "channelId");
  const templateId = formValue(formData, "templateId");
  const audienceType = formValue(formData, "audienceType") as CampaignAudienceType;
  const segmentId = formValue(formData, "segmentId");
  const scheduledAtRaw = formValue(formData, "scheduledAt");
  const scheduledAt = scheduledAtRaw ? new Date(scheduledAtRaw) : null;

  if (!name || !channelId || !templateId || !audienceType) {
    redirect("/campaigns/new?error=missing_fields");
  }

  const channel = await prisma.channel.findFirst({
    where: { id: channelId, tenantId }
  });
  if (!channel) {
    redirect("/campaigns/new?error=invalid_channel");
  }

  const template = await prisma.messageTemplate.findFirst({
    where: { id: templateId, tenantId }
  });
  if (!template) {
    redirect("/campaigns/new?error=invalid_template");
  }

  let targetSegmentId = segmentId || null;
  if (audienceType === CampaignAudienceType.SEGMENT) {
    const segment = await prisma.contactSegment.findFirst({
      where: { id: segmentId, tenantId }
    });
    if (!segment) {
      redirect("/campaigns/new?error=invalid_segment");
    }
    targetSegmentId = segment.id;
  } else {
    targetSegmentId = null;
  }

  const campaign = await prisma.broadcastCampaign.create({
    data: {
      tenantId,
      channelId,
      templateId,
      createdByUserId: session.userId,
      name,
      audienceType,
      segmentId: targetSegmentId,
      scheduledAt: scheduledAtRaw ? scheduledAt : null,
      status: scheduledAtRaw ? CampaignStatus.SCHEDULED : CampaignStatus.DRAFT,
      campaignType: audienceType === CampaignAudienceType.SEGMENT ? CampaignType.BROADCAST : CampaignType.BULK_FOLLOWUP
    }
  });

  await writeAuditTrail({
    ...auditContext,
    entityType: "campaign",
    entityId: campaign.id,
    action: "create_campaign",
    metadata: {
      name,
      channelId,
      templateId,
      audienceType,
      segmentId: targetSegmentId,
      scheduledAt: scheduledAt?.toISOString() ?? null,
      status: campaign.status
    }
  });

  revalidatePath("/campaigns");
  redirect(`/campaigns/${campaign.id}`);
}

export async function deleteCampaign(formData: FormData) {
  const session = await requireAdminManageSession();
  const tenantId = session.tenantId;
  const auditContext = await getAuditContext(session);

  const id = formValue(formData, "campaignId");
  if (!id) {
    redirect("/campaigns?error=missing_campaign_id");
  }

  const campaign = await prisma.broadcastCampaign.findFirst({
    where: { id, tenantId }
  });
  if (!campaign) {
    redirect("/campaigns?error=campaign_not_found");
  }

  await prisma.$transaction([
    prisma.campaignRecipient.deleteMany({ where: { campaignId: id } }),
    prisma.broadcastCampaign.delete({ where: { id } })
  ]);

  await writeAuditTrail({
    ...auditContext,
    entityType: "campaign",
    entityId: id,
    action: "delete_campaign",
    metadata: {
      campaignName: campaign.name
    }
  });

  revalidatePath("/campaigns");
  redirect("/campaigns");
}

export async function updateMyProfile(formData: FormData) {
  const session = await requireProfileManageSession();
  const auditContext = await getAuditContext(session);

  const fullName = formValue(formData, "fullName");
  const avatarUrl = formValue(formData, "avatarUrl") || null;

  if (!fullName) {
    redirect("/profile/edit?error=missing_fullname");
  }

  await prisma.user.update({
    where: { id: session.userId },
    data: {
      fullName,
      avatarUrl: avatarUrl || null
    }
  });

  await writeAuditTrail({
    ...auditContext,
    entityType: "user",
    entityId: session.userId,
    action: "update_profile",
    metadata: {
      fullName,
      avatarUrl: avatarUrl || null
    }
  });

  revalidatePath("/profile");
  revalidatePath("/profile/edit");
  redirect("/profile");
}

export async function updateTenantProfile(formData: FormData) {
  const session = await requireAdminManageSession();
  const auditContext = await getAuditContext(session);

  const companyName = formValue(formData, "companyName");
  const timezone = formValue(formData, "timezone");
  const slug = formValue(formData, "slug");

  if (!companyName || !timezone || !slug) {
    redirect("/settings/profile?error=missing_fields");
  }

  const tenantId = session.tenantId;
  const existing = await prisma.tenant.findUnique({
    where: { slug }
  });

  if (existing && existing.id !== tenantId) {
    redirect("/settings/profile?error=tenant_slug_taken");
  }

  await prisma.tenant.update({
    where: { id: tenantId },
    data: {
      name: companyName,
      companyName,
      slug,
      timezone
    }
  });

  await writeAuditTrail({
    ...auditContext,
    entityType: "tenant",
    entityId: tenantId,
    action: "update_tenant_profile",
    metadata: {
      companyName,
      slug,
      timezone
    }
  });

  revalidatePath("/settings/profile");
  revalidatePath("/profile");
  redirect("/settings/profile?success=updated");
}

export async function changePassword(formData: FormData) {
  const session = await requireProfileManageSession();
  const auditContext = await getAuditContext(session);

  const currentPassword = formValue(formData, "currentPassword");
  const newPassword = formValue(formData, "newPassword");
  const confirmPassword = formValue(formData, "confirmPassword");

  if (!currentPassword || !newPassword || !confirmPassword) {
    redirect("/profile/change-password?error=missing_fields");
  }

  if (newPassword !== confirmPassword) {
    redirect("/profile/change-password?error=password_mismatch");
  }

  const user = await prisma.user.findUnique({
    where: { id: session.userId },
    select: { passwordHash: true }
  });

  if (!user) {
    redirect("/unauthorized");
  }

  const isCurrentValid = await verifyPassword(currentPassword, user.passwordHash);
  if (!isCurrentValid) {
    redirect("/profile/change-password?error=wrong_current_password");
  }

  await prisma.user.update({
    where: { id: session.userId },
    data: {
      passwordHash: await hashPassword(newPassword)
    }
  });

  await writeAuditTrail({
    ...auditContext,
    entityType: "user",
    entityId: session.userId,
    action: "change_password",
    metadata: {
      success: true
    }
  });

  redirect("/profile/change-password?success=updated");
}

export async function createContactSegment(formData: FormData) {
  const session = await requireAdminManageSession();
  const tenantId = session.tenantId;
  const auditContext = await getAuditContext(session);

  const name = formValue(formData, "name");
  const rulesRaw = formValue(formData, "rules");

  if (!name) {
    redirect("/contacts/segments/new?error=missing_fields");
  }

  const parsedRules = parseSegmentRules(rulesRaw);

  const segment = await prisma.contactSegment.create({
    data: {
      tenantId,
      name,
      description: parsedRules.description,
      rulesJson: parsedRules.rulesJson
    }
  });

  await writeAuditTrail({
    ...auditContext,
    entityType: "contact_segment",
    entityId: segment.id,
    action: "create_contact_segment",
    metadata: {
      name,
      hasRules: Boolean(parsedRules.rulesJson)
    }
  });

  revalidatePath("/contacts/segments");
  redirect("/contacts/segments");
}

export async function createTenant(formData: FormData) {
  const session = await requireSuperAdminSession();
  const auditContext = await getAuditContext(session);

  const name = formValue(formData, "name");
  const companyName = formValue(formData, "companyName") || name;
  const slug = formValue(formData, "slug").toLowerCase();
  const timezone = formValue(formData, "timezone");
  const planId = formValue(formData, "planId");
  const adminFullName = formValue(formData, "adminFullName") || `Admin ${name}`;
  const adminEmail = formValue(formData, "adminEmail");
  const adminPassword = formValue(formData, "adminPassword");

  if (!name || !slug || !timezone || !planId) {
    redirect("/super-admin/tenants/new?error=missing_fields");
  }

  const [plan, existingTenant, existingAdmin] = await Promise.all([
    prisma.subscriptionPlan.findUnique({ where: { id: planId } }),
    prisma.tenant.findUnique({ where: { slug } }),
    adminEmail ? prisma.user.findUnique({ where: { email: adminEmail } }) : Promise.resolve(null)
  ]);

  if (!plan) {
    redirect("/super-admin/tenants/new?error=invalid_plan");
  }

  if (existingTenant) {
    redirect("/super-admin/tenants/new?error=slug_exists");
  }

  if (adminEmail && existingAdmin) {
    redirect("/super-admin/tenants/new?error=admin_email_exists");
  }

  type AdminInvitePayload = {
    adminId: string;
    tenantId: string;
    tenantName: string;
    adminEmail: string;
  };

  const tenantCreation = await prisma.$transaction(async (tx) => {
    const createdTenant = await tx.tenant.create({
      data: {
        name,
        companyName: companyName || name,
        slug,
        timezone,
        status: TenantStatus.ACTIVE,
        planId
      }
    });

    if (adminEmail) {
      const shouldInviteAdmin = !adminPassword;
      const adminPasswordRaw = shouldInviteAdmin
        ? randomBytes(20).toString("hex")
        : adminPassword;
      const adminStatus = shouldInviteAdmin ? UserStatus.INVITED : UserStatus.ACTIVE;
      const adminPasswordHash = await hashPassword(adminPasswordRaw);
      const adminRole = await tx.role.create({
        data: {
          tenantId: createdTenant.id,
          name: `${companyName} Admin`,
          code: RoleCode.ADMIN_CLIENT,
          permissionsJson: JSON.stringify({ tenant: true })
        }
      });

      const createdAdmin = await tx.user.create({
        data: {
          tenantId: createdTenant.id,
          fullName: adminFullName || `${companyName} Admin`,
          email: adminEmail,
          roleId: adminRole.id,
          status: adminStatus,
          passwordHash: adminPasswordHash
        }
      });

      if (shouldInviteAdmin) {
        return {
          tenant: createdTenant,
          adminInvite: {
            adminId: createdAdmin.id,
            tenantId: createdTenant.id,
            tenantName: name,
            adminEmail
          } satisfies AdminInvitePayload
        };
      }
    }

    return {
      tenant: createdTenant,
      adminInvite: null
    };
  });

  const tenant = tenantCreation.tenant;
  const adminInvite = tenantCreation.adminInvite;

  if (adminInvite) {
    const adminInviteToken = await createAuthToken({
      userId: adminInvite.adminId,
      tenantId: adminInvite.tenantId,
      tokenType: AuthTokenType.INVITE_ACCEPTANCE,
      createdByUserId: session.userId,
      metadata: { source: "tenant_admin_invitation", tenantId: adminInvite.tenantId }
    });

    const inviteUrl = makeInviteUrl(adminInviteToken.rawToken);
    const adminInviteResult = await sendTransactionalNotification({
      to: adminInvite.adminEmail,
      subject: `Setup admin tenant ${adminInvite.tenantName}`,
      text: `Anda diundang menjadi admin untuk tenant ${adminInvite.tenantName}. Gunakan tautan ini untuk mengatur kata sandi: ${inviteUrl}`,
      html: `<p>Anda diundang menjadi admin untuk tenant <b>${adminInvite.tenantName}</b>.</p><p>Gunakan tautan berikut untuk mengaktifkan akun: <a href="${inviteUrl}">${inviteUrl}</a></p>`
    });

    if (!adminInviteResult.ok) {
      await writeAuditTrail({
        ...auditContext,
        entityType: "user",
        entityId: adminInvite.adminId,
        action: "tenant_admin_invite_delivery_failed",
        metadata: {
          email: adminInvite.adminEmail,
          tenantId: adminInvite.tenantId,
          reason: adminInviteResult.error ?? "delivery_error",
          source: "tenant_admin"
        }
      });
    }
  }

  revalidatePath("/super-admin/tenants");

  await writeAuditTrail({
    ...auditContext,
    entityType: "tenant",
    entityId: tenant.id,
    action: "create_tenant",
    metadata: {
      name,
      companyName,
      slug,
      timezone,
      planId
    }
  });

  redirect(`/super-admin/tenants/${tenant.id}`);
}

export async function updateTenant(formData: FormData) {
  const session = await requireSuperAdminSession();
  const auditContext = await getAuditContext(session);

  const tenantId = formValue(formData, "tenantId");
  const name = formValue(formData, "name");
  const companyName = formValue(formData, "companyName");
  const slug = formValue(formData, "slug");
  const timezone = formValue(formData, "timezone");
  const planId = formValue(formData, "planId");
  const statusValue = formValue(formData, "status");

  if (!tenantId || !name || !companyName || !slug || !timezone || !planId || !statusValue) {
    redirect(`/super-admin/tenants/${tenantId || ""}?error=missing_fields`);
  }

  const tenant = await prisma.tenant.findUnique({ where: { id: tenantId }, include: { plan: true } });
  if (!tenant) {
    redirect("/super-admin/tenants?error=tenant_not_found");
  }

  const slugConflict = await prisma.tenant.findFirst({
    where: {
      slug,
      NOT: { id: tenantId }
    }
  });
  if (slugConflict) {
    redirect(`/super-admin/tenants/${tenantId}?error=slug_exists`);
  }

  const plan = await prisma.subscriptionPlan.findUnique({ where: { id: planId } });
  if (!plan) {
    redirect(`/super-admin/tenants/${tenantId}?error=invalid_plan`);
  }

  const normalizedStatus = isValidTenantStatus(statusValue) ? (statusValue as TenantStatus) : tenant.status;

  await prisma.tenant.update({
    where: { id: tenantId },
    data: {
      name,
      companyName,
      slug,
      timezone,
      status: normalizedStatus,
      planId
    }
  });

  await writeAuditTrail({
    ...auditContext,
    entityType: "tenant",
    entityId: tenantId,
    action: "update_tenant",
    metadata: {
      name,
      companyName,
      slug,
      timezone,
      status: normalizedStatus,
      planId
    }
  });

  revalidatePath(`/super-admin/tenants/${tenantId}`);
  revalidatePath("/super-admin/tenants");
  redirect(`/super-admin/tenants/${tenantId}`);
}

export async function connectTenantChannel(formData: FormData) {
  const session = await requireSuperAdminSession();
  const auditContext = await getAuditContext(session);

  const tenantId = formValue(formData, "tenantId");
  const channelName = formValue(formData, "channelName");
  const provider = formValue(formData, "provider");
  const wabaId = formValue(formData, "wabaId");
  const phoneNumberId = formValue(formData, "phoneNumberId");
  const displayPhoneNumber = formValue(formData, "displayPhoneNumber");
  const statusValue = formValue(formData, "status");

  if (!tenantId || !provider || !channelName || !wabaId || !phoneNumberId || !displayPhoneNumber) {
    redirect(`/super-admin/tenants/${tenantId || ""}/channels/new?error=missing_fields`);
  }

  const tenant = await prisma.tenant.findUnique({ where: { id: tenantId } });
  if (!tenant) {
    redirect("/super-admin/tenants?error=tenant_not_found");
  }

  const status = isValidChannelStatus(statusValue) ? (statusValue as ChannelStatus) : ChannelStatus.PENDING;

  const channel = await prisma.channel.create({
    data: {
      tenantId,
      channelName,
      provider,
      wabaId,
      phoneNumberId,
      displayPhoneNumber,
      status,
      webhookStatus: "pending"
    }
  });

  await writeAuditTrail({
    ...auditContext,
    entityType: "channel",
    entityId: channel.id,
    action: "connect_tenant_channel",
    metadata: {
      tenantId,
      channelName,
      provider,
      wabaId,
      phoneNumberId,
      displayPhoneNumber,
      status
    }
  });

  revalidatePath("/super-admin/channels");
  revalidatePath(`/super-admin/tenants/${tenantId}`);
  redirect(`/super-admin/channels/${channel.id}`);
}
