import type { PipelineStage } from "mongoose";
import { connectDB } from "@/lib/db";
import { Order } from "@/models/Order";
import { ORDER_TAGS, type OrderTag } from "@/lib/orderConstants";

// Extrahiert aus admin/orders/page.tsx — von dort UND von der Team-App-API
// (api/team/v1/orders) genutzt, damit Liste, Suche, Sortierung und
// Statistik-Zahlen an nur einer Stelle existieren.
const PAGE_SIZE = 20;

function escapeRegex(s: string) {
  return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}

export type OrderRow = {
  _id: string;
  characterOrConcept: string;
  tag: OrderTag;
  rejected: boolean;
  compensationType: "paid" | "tfp";
  paid: boolean;
  createdAt: string;
  client: { _id: string; name: string; email: string; avatarPath: string } | null;
  assignedStaffName: string | null;
};

export async function getOrderList(params: { sort?: string; q?: string; archived?: boolean; page?: number }) {
  const { sort = "newest", q = "", archived = false, page: pageParam = 1 } = params;
  const page = Math.max(1, pageParam || 1);

  await connectDB();

  const pipeline: PipelineStage[] = [
    { $match: { archived } },
    { $lookup: { from: "clients", localField: "clientId", foreignField: "_id", as: "client" } },
    { $unwind: { path: "$client", preserveNullAndEmptyArrays: true } },
    { $lookup: { from: "clients", localField: "assignedStaffId", foreignField: "_id", as: "assignedStaff" } },
    { $unwind: { path: "$assignedStaff", preserveNullAndEmptyArrays: true } },
  ];

  if (q.trim()) {
    const trimmed = q.trim();
    const rx = new RegExp(escapeRegex(trimmed), "i");
    const orConditions: Record<string, unknown>[] = [
      { characterOrConcept: rx },
      { "client.name": rx },
      { "client.email": rx },
      { "client.nickname": rx },
    ];

    // Suche nach der Auftrags-ID ("RK-XXXXXXXX", siehe formatPaymentReference)
    // — die ID ist keine eigene Spalte, sondern aus den letzten 8 Hex-Zeichen
    // der _id abgeleitet, daher hier per $expr gegen die in einen String
    // umgewandelte _id gematcht statt gegen ein echtes Feld.
    const idQuery = trimmed.replace(/^rk-?/i, "").replace(/[\s-]/g, "");
    if (/^[0-9a-fA-F]{3,24}$/.test(idQuery)) {
      orConditions.push({ $expr: { $regexMatch: { input: { $toString: "$_id" }, regex: idQuery, options: "i" } } });
    }

    pipeline.push({ $match: { $or: orConditions } });
  }

  if (sort === "client") {
    pipeline.push({ $sort: { "client.name": 1 } });
  } else if (sort === "tag") {
    pipeline.push({ $addFields: { tagRank: { $indexOfArray: [ORDER_TAGS, "$tag"] } } });
    pipeline.push({ $sort: { tagRank: 1 } });
  } else if (sort === "oldest") {
    pipeline.push({ $sort: { createdAt: 1 } });
  } else {
    pipeline.push({ $sort: { createdAt: -1 } });
  }

  const countPipeline = [...pipeline, { $count: "total" }];
  pipeline.push({ $skip: (page - 1) * PAGE_SIZE }, { $limit: PAGE_SIZE });

  const [rawOrders, countResult, totalActive, totalRejected, openPayments] = await Promise.all([
    Order.aggregate(pipeline),
    Order.aggregate(countPipeline),
    Order.countDocuments({ archived: false, rejected: false }),
    Order.countDocuments({ archived: false, rejected: true }),
    Order.countDocuments({ archived: false, rejected: false, compensationType: "paid", paid: false }),
  ]);

  const total = countResult[0]?.total ?? 0;
  const totalPages = Math.max(1, Math.ceil(total / PAGE_SIZE));

  const orders: OrderRow[] = rawOrders.map((o) => ({
    _id: String(o._id),
    characterOrConcept: o.characterOrConcept,
    tag: o.tag,
    rejected: o.rejected,
    compensationType: o.compensationType,
    paid: o.paid,
    createdAt: new Date(o.createdAt).toISOString(),
    client: o.client
      ? { _id: String(o.client._id), name: o.client.name, email: o.client.email, avatarPath: o.client.avatarPath || "" }
      : null,
    assignedStaffName: o.assignedStaff?.name ?? null,
  }));

  return { orders, total, totalPages, page, totalActive, totalRejected, openPayments };
}
