import { randomBytes } from "node:crypto";
import type { Prisma, PrismaClient } from "@prisma/client";
import { createId } from "./id.js";

type TeamWorkspaceDb = Prisma.TransactionClient | PrismaClient;

type EnsureLawFirmTeamUserInput = {
  lawFirmId: string;
  userId: string;
  displayName: string;
  email: string;
  membershipRole: "owner" | "member";
  invitedByUserId?: string | null;
  teamName?: string | null;
};

type EnsureWorkspaceMembershipInput = {
  lawFirmId: string;
  userId: string;
  membershipRole: "owner" | "member";
  createdByUserId?: string | null;
  isDefault?: boolean;
};

function normalizeDisplayName(displayName: string, email: string) {
  return String(displayName ?? "").trim() || String(email ?? "").trim() || "Usuário";
}

function buildDefaultAgentPrompt(input: {
  displayName: string;
  email: string;
  membershipRole: "owner" | "member";
}) {
  const roleLabel = input.membershipRole === "owner" ? "líder do time" : "membro do time";

  return [
    `Você representa o estilo de revisão documental de ${input.displayName}.`,
    `Essa pessoa participa do team como ${roleLabel} e usa o e-mail ${input.email}.`,
    "Aprenda com reprovações, aprovações, orientações e comentários ancorados dessa pessoa.",
    "Quando houver memória prévia, priorize esse histórico antes de recorrer a padrões genéricos do time.",
    "Se faltar histórico suficiente, seja explícito e conservador na conclusão.",
  ].join(" ");
}

export function splitName(fullName: string) {
  const cleaned = fullName.trim().replace(/\s+/g, " ");
  const [firstName, ...rest] = cleaned.split(" ");

  return {
    firstName: firstName || "Admin",
    lastName: rest.join(" ") || "User",
    displayName: cleaned,
  };
}

export function buildWorkspaceName(displayName: string) {
  return `Workspace de ${displayName.trim() || "Usuário"}`;
}

export function buildTemporaryPassword() {
  return `Tmp!${randomBytes(12).toString("base64url")}`;
}

export async function ensureWorkspaceMembership(
  db: TeamWorkspaceDb,
  input: EnsureWorkspaceMembershipInput,
) {
  const [membership] = await db.$queryRaw<Array<{ id: string; is_default: number }>>`
    SELECT id, is_default
    FROM workspace_memberships
    WHERE law_firm_id = ${input.lawFirmId}
      AND user_id = ${input.userId}
    LIMIT 1
  `;

  if (!membership) {
    await db.$executeRaw`
      INSERT INTO workspace_memberships (
        id, law_firm_id, user_id, membership_role, is_default, created_by_user_id, joined_at
      ) VALUES (
        ${createId()},
        ${input.lawFirmId},
        ${input.userId},
        ${input.membershipRole},
        ${input.isDefault ?? false},
        ${input.createdByUserId ?? input.userId},
        CURRENT_TIMESTAMP
      )
    `;
    return;
  }

  if (input.isDefault && !membership.is_default) {
    await db.$executeRaw`
      UPDATE workspace_memberships
      SET is_default = 1
      WHERE id = ${membership.id}
    `;
  }
}

export async function ensureLawFirmTeamUser(
  db: TeamWorkspaceDb,
  input: EnsureLawFirmTeamUserInput,
) {
  await ensureWorkspaceMembership(db, {
    lawFirmId: input.lawFirmId,
    userId: input.userId,
    membershipRole: input.membershipRole,
    createdByUserId: input.invitedByUserId ?? input.userId,
    isDefault: false,
  });

  const displayName = normalizeDisplayName(input.displayName, input.email);
  const defaultTeamName = String(input.teamName ?? "").trim() || "Time interno";

  const [existingTeam] = await db.$queryRaw<Array<{ id: string }>>`
    SELECT id
    FROM teams
    WHERE law_firm_id = ${input.lawFirmId}
    LIMIT 1
  `;

  let team = existingTeam;

  if (!team) {
    team = { id: createId() };
    await db.$executeRaw`
      INSERT INTO teams (
        id, law_firm_id, name, created_by_user_id, created_at, updated_at
      ) VALUES (
        ${team.id},
        ${input.lawFirmId},
        ${defaultTeamName},
        ${input.invitedByUserId ?? input.userId},
        CURRENT_TIMESTAMP,
        CURRENT_TIMESTAMP
      )
    `;
  }

  const [membership] = await db.$queryRaw<Array<{ id: string }>>`
    SELECT id
    FROM team_memberships
    WHERE law_firm_id = ${input.lawFirmId}
      AND user_id = ${input.userId}
    LIMIT 1
  `;

  if (!membership) {
    await db.$executeRaw`
      INSERT INTO team_memberships (
        id, law_firm_id, team_id, user_id, membership_role, invited_by_user_id, joined_at
      ) VALUES (
        ${createId()},
        ${input.lawFirmId},
        ${team.id},
        ${input.userId},
        ${input.membershipRole},
        ${input.invitedByUserId ?? null},
        CURRENT_TIMESTAMP
      )
    `;
  }

  const [teamAgent] = await db.$queryRaw<Array<{ id: string }>>`
    SELECT id
    FROM team_agents
    WHERE law_firm_id = ${input.lawFirmId}
      AND user_id = ${input.userId}
    LIMIT 1
  `;

  if (!teamAgent) {
    await db.$executeRaw`
      INSERT INTO team_agents (
        id, law_firm_id, team_id, user_id, agent_name, system_prompt, learning_summary,
        memory_count, last_learning_at, created_at, updated_at
      ) VALUES (
        ${createId()},
        ${input.lawFirmId},
        ${team.id},
        ${input.userId},
        ${`Agente de ${displayName}`},
        ${buildDefaultAgentPrompt({
          displayName,
          email: input.email,
          membershipRole: input.membershipRole,
        })},
        NULL,
        0,
        NULL,
        CURRENT_TIMESTAMP,
        CURRENT_TIMESTAMP
      )
    `;
  }

  return {
    teamId: team.id,
  };
}
