import { prisma } from "../../config/prisma";
import { ClientStatus } from "@prisma/client";

// ---------- INVITE STAGE ----------

export function createInvitation(data: {
  organizationId: string;
  email: string;
  name: string;
  token: string;
  expiresAt: Date;
  companyName?: string;
  gstin?: string;
  pan?: string;
  phone?: string;
}) {
  return prisma.client.create({
    data: {
      organizationId: data.organizationId,
      email: data.email,
      name: data.name,
      token: data.token,
      expiresAt: data.expiresAt,
      status: "INVITED",
      companyName: data.companyName ?? null,
      gstin: data.gstin ?? null,
      pan: data.pan ?? null,
      phone: data.phone ?? null,
    },
  });
}

export function findInvitationByToken(token: string) {
  return prisma.client.findUnique({ where: { token } });
}

export function findInvitationByEmail(organizationId: string, email: string) {
  return prisma.client.findFirst({
    where: { organizationId, email, status: "INVITED" },
  });
}

// ---------- ACCEPT STAGE ----------

export function acceptInvitation(data: {
  clientId: string;
  organizationId: string;
  name: string;
  email: string;
  passwordHash: string;
}) {
  return prisma.$transaction(async (tx) => {
    const user = await tx.user.create({
      data: {
        organizationId: data.organizationId,
        name: data.name,
        email: data.email,
        passwordHash: data.passwordHash,
        role: "CLIENT",
        status: "ACTIVE",
      },
    });

    const client = await tx.client.update({
      where: { id: data.clientId },
      data: {
        userId: user.id,
        status: "ACTIVE",
        token: null,
        expiresAt: null,
      },
    });

    return { user, client };
  });
}

// ---------- QUERIES ----------

export async function findClientsByOrg(
  organizationId: string,
  page: number,
  limit: number,
  search?: string,
  status?: ClientStatus,
) {
  const where = {
    organizationId,
    ...(status ? { status } : {}),
    ...(search
      ? {
          OR: [
            { name: { contains: search } },
            { email: { contains: search } },
            { companyName: { contains: search } },
          ],
        }
      : {}),
  };

  const [data, total] = await Promise.all([
    prisma.client.findMany({
      where,
      include: {
        user: { select: { id: true, name: true, email: true, status: true, phone: true } },
      },
      orderBy: { createdAt: "desc" },
      skip: (page - 1) * limit,
      take: limit,
    }),
    prisma.client.count({ where }),
  ]);

  return { data, total };
}

export function findClientById(id: string, organizationId: string) {
  return prisma.client.findFirst({
    where: { id, organizationId },
    include: {
      user: { select: { id: true, name: true, email: true, status: true, phone: true } },
      organization: { select: { id: true, name: true } },
    },
  });
}

export function updateClient(
  id: string,
  data: { name?: string; companyName?: string; gstin?: string; pan?: string; phone?: string; status?: string },
) {
  return prisma.$transaction(async (tx) => {
    const client = await tx.client.update({
      where: { id },
      data: {
        ...(data.name !== undefined ? { name: data.name } : {}),
        ...(data.companyName !== undefined ? { companyName: data.companyName || null } : {}),
        ...(data.gstin !== undefined ? { gstin: data.gstin || null } : {}),
        ...(data.pan !== undefined ? { pan: data.pan || null } : {}),
        ...(data.phone !== undefined ? { phone: data.phone || null } : {}),
        ...(data.status ? { status: data.status as ClientStatus } : {}),
      },
    });

    // Sync matching fields to User table
    if (client.userId) {
      const userUpdate: any = {};
      if (data.name) userUpdate.name = data.name;
      if (data.phone !== undefined) userUpdate.phone = data.phone || null;
      if (data.status) {
        const statusMap: Record<string, string> = {
          ACTIVE: "ACTIVE",
          SUSPENDED: "SUSPENDED",
          REVOKED: "INACTIVE",
          INVITED: "ACTIVE",
        };
        userUpdate.status = statusMap[data.status] ?? "ACTIVE";
      }
      if (Object.keys(userUpdate).length > 0) {
        await tx.user.update({ where: { id: client.userId }, data: userUpdate });
      }
    }

    return client;
  });
}

export function deleteClient(id: string) {
  return prisma.$transaction(async (tx) => {
    // delete child records that don't cascade automatically
    await tx.document.deleteMany({ where: { clientId: id } });
    await tx.task.deleteMany({ where: { clientId: id } });
    await tx.documentFolder.deleteMany({ where: { clientId: id } });
    await tx.quotation.deleteMany({ where: { clientId: id } });
    await tx.invoice.deleteMany({ where: { clientId: id } });
    await tx.payment.deleteMany({ where: { clientId: id } });
    await tx.gstReturn.deleteMany({ where: { clientId: id } });
    await tx.tdsReturn.deleteMany({ where: { clientId: id } });
    await tx.bankStatement.deleteMany({ where: { clientId: id } });
    await tx.clientHealthScore.deleteMany({ where: { clientId: id } });
    await tx.dueDateReminder.deleteMany({ where: { clientId: id } });
    await tx.diyApplication.deleteMany({ where: { clientId: id } });
    await tx.feedback.deleteMany({ where: { clientId: id } });
    await tx.referral.deleteMany({ where: { referrerId: id } });
    await tx.referral.deleteMany({ where: { referredId: id } });
    await tx.tallyVoucher.deleteMany({ where: { clientId: id } });
    const client = await tx.client.findUnique({ where: { id }, select: { userId: true } });
    await tx.client.delete({ where: { id } });
    if (client?.userId) await tx.user.delete({ where: { id: client.userId } });
  });
}
