import { Injectable } from '@nestjs/common';
import { PrismaService } from '../prisma/prisma.service';

@Injectable()
export class ReportsService {
    constructor(private prisma: PrismaService) { }

    private toCsv(headers: string[], rows: Record<string, unknown>[]): string {
        const lines = [headers.join(',')];
        for (const row of rows) {
            const values = headers.map(h => {
                const val = row[h];
                if (val === null || val === undefined) return '';
                const str = String(val);
                // Escape quotes and wrap in quotes if contains comma
                if (str.includes(',') || str.includes('"') || str.includes('\n')) {
                    return `"${str.replace(/"/g, '""')}"`;
                }
                return str;
            });
            lines.push(values.join(','));
        }
        return lines.join('\n');
    }

    async exportOrdersCsv(from: string, to: string): Promise<string> {
        const fromDate = new Date(from);
        const toDate = new Date(to);

        const orders = await this.prisma.$queryRaw<any[]>`
            SELECT 
                o.id,
                o.status,
                o.total_cents,
                o.shipping_cents,
                o.created_at,
                buyer.name as buyer_name,
                seller.corporate_name as seller_name
            FROM orders o
            LEFT JOIN users buyer ON o.buyer_id = buyer.id
            LEFT JOIN companies seller ON o.seller_id = seller.id
            WHERE o.created_at >= ${fromDate} AND o.created_at <= ${toDate}
            ORDER BY o.created_at DESC
        `;

        return this.toCsv(
            ['id', 'status', 'total_cents', 'shipping_cents', 'created_at', 'buyer_name', 'seller_name'],
            orders
        );
    }

    async exportSellersCsv(): Promise<string> {
        const sellers = await this.prisma.$queryRaw<any[]>`
            SELECT 
                c.id,
                c.cnpj,
                c.corporate_name,
                c.city,
                c.state,
                c.is_verified,
                c.created_at,
                COUNT(DISTINCT o.id) as total_orders,
                COALESCE(SUM(o.total_cents), 0) as total_sales_cents
            FROM companies c
            LEFT JOIN orders o ON o.seller_id = c.id
            WHERE c.category = 'distribuidora'
            GROUP BY c.id
            ORDER BY total_sales_cents DESC
        `;

        return this.toCsv(
            ['id', 'cnpj', 'corporate_name', 'city', 'state', 'is_verified', 'created_at', 'total_orders', 'total_sales_cents'],
            sellers
        );
    }

    async exportLedgerCsv(from: string, to: string): Promise<string> {
        const fromDate = new Date(from);
        const toDate = new Date(to);

        const entries = await this.prisma.$queryRaw<any[]>`
            SELECT 
                l.id,
                l.company_id,
                l.amount_cents,
                l.type,
                l.reference_id,
                l.description,
                l.created_at,
                c.corporate_name as company_name
            FROM ledger_entries l
            LEFT JOIN companies c ON l.company_id = c.id
            WHERE l.created_at >= ${fromDate} AND l.created_at <= ${toDate}
            ORDER BY l.created_at DESC
        `;

        return this.toCsv(
            ['id', 'company_id', 'company_name', 'amount_cents', 'type', 'reference_id', 'description', 'created_at'],
            entries
        );
    }

    async exportSellerPerformanceCsv(): Promise<string> {
        const performance = await this.prisma.$queryRaw<any[]>`
            SELECT 
                c.id,
                c.corporate_name,
                COUNT(DISTINCT o.id) as total_orders,
                COUNT(DISTINCT CASE WHEN o.status = 'Entregue' THEN o.id END) as delivered_orders,
                COUNT(DISTINCT CASE WHEN o.status = 'Cancelado' THEN o.id END) as cancelled_orders,
                COALESCE(AVG(r.rating), 0) as avg_rating,
                COUNT(DISTINCT r.id) as total_reviews,
                COALESCE(SUM(o.total_cents), 0) as total_sales_cents
            FROM companies c
            LEFT JOIN orders o ON o.seller_id = c.id
            LEFT JOIN reviews r ON r.company_id = c.id
            WHERE c.category = 'distribuidora'
            GROUP BY c.id
            ORDER BY avg_rating DESC, total_orders DESC
        `;

        return this.toCsv(
            ['id', 'corporate_name', 'total_orders', 'delivered_orders', 'cancelled_orders', 'avg_rating', 'total_reviews', 'total_sales_cents'],
            performance
        );
    }
}
