import prisma from "../config/prisma.js";
import { Prisma } from "../generated/prisma/client.js";

// ─────────────────────────────────────────────────────────────
//  Data Structures
// ─────────────────────────────────────────────────────────────

export interface OutstandingParty {
  id: string;
  name: string;
  tamilName: string | null;
  mobileNo: string;
  address: string | null;
  openingBalance: number;
  outstandingBalance: number;
  status: boolean;
}

export interface OutstandingSummary {
  totalCount: number;
  withBalanceCount: number;
  clearedCount: number;
  totalOutstandingAmount: number;
}

// ─────────────────────────────────────────────────────────────
//  Service
// ─────────────────────────────────────────────────────────────

export class OutstandingReportService {

  private buildSearchWhere(search: string): any {
    if (!search || search.trim() === "") return {};
    const q = search.trim();
    return {
      OR: [
        { name: { contains: q } },
        { tamilName: { contains: q } },
        { mobileNo: { contains: q } },
      ]
    };
  }

  async getCustomers(page: number = 1, limit: number = 20, search: string = "") {
    const skip = (page - 1) * limit;
    const where = this.buildSearchWhere(search);

    const [items, totalCount, withBalanceCount, aggregate] = await Promise.all([
      prisma.customer.findMany({
        where,
        skip,
        take: limit,
        orderBy: [{ outstandingBalance: "desc" }, { name: "asc" }],
        select: {
          id: true, name: true, tamilName: true, mobileNo: true, address: true, openingBalance: true, outstandingBalance: true, status: true
        }
      }),
      prisma.customer.count({ where }),
      prisma.customer.count({ where: { ...where, outstandingBalance: { gt: 0 } } }),
      prisma.customer.aggregate({
        where: { ...where, outstandingBalance: { gt: 0 } },
        _sum: { outstandingBalance: true }
      })
    ]);

    const mappedItems: OutstandingParty[] = items.map(i => ({
      ...i,
      id: String(i.id),
      openingBalance: Number(i.openingBalance || 0),
      outstandingBalance: Number(i.outstandingBalance || 0),
    }));

    const summary: OutstandingSummary = {
      totalCount,
      withBalanceCount,
      clearedCount: totalCount - withBalanceCount,
      totalOutstandingAmount: Number(aggregate._sum.outstandingBalance || 0)
    };

    return {
      data: mappedItems,
      summary,
      meta: { total: totalCount, page, limit, totalPages: Math.ceil(totalCount / limit) }
    };
  }

  async getSuppliers(page: number = 1, limit: number = 20, search: string = "") {
    const skip = (page - 1) * limit;
    const where = this.buildSearchWhere(search);

    const [items, totalCount, withBalanceCount, aggregate] = await Promise.all([
      prisma.supplier.findMany({
        where,
        skip,
        take: limit,
        orderBy: [{ outstandingBalance: "desc" }, { name: "asc" }],
        select: {
          id: true, name: true, tamilName: true, mobileNo: true, address: true, openingBalance: true, outstandingBalance: true, status: true
        }
      }),
      prisma.supplier.count({ where }),
      prisma.supplier.count({ where: { ...where, outstandingBalance: { gt: 0 } } }),
      prisma.supplier.aggregate({
        where: { ...where, outstandingBalance: { gt: 0 } },
        _sum: { outstandingBalance: true }
      })
    ]);

    const mappedItems: OutstandingParty[] = items.map(i => ({
      ...i,
      id: String(i.id),
      openingBalance: Number(i.openingBalance || 0),
      outstandingBalance: Number(i.outstandingBalance || 0),
    }));

    const summary: OutstandingSummary = {
      totalCount,
      withBalanceCount,
      clearedCount: totalCount - withBalanceCount,
      totalOutstandingAmount: Number(aggregate._sum.outstandingBalance || 0)
    };

    return {
      data: mappedItems,
      summary,
      meta: { total: totalCount, page, limit, totalPages: Math.ceil(totalCount / limit) }
    };
  }
  
  async getAllForExport(type: "customers" | "suppliers") {
      // For export, we fetch everything (or apply search if needed, but standard is all)
      if (type === "customers") {
          return this.getCustomers(1, 999999, "");
      } else {
          return this.getSuppliers(1, 999999, "");
      }
  }
}

export default new OutstandingReportService();

