import { FastifyRequest, FastifyReply } from 'fastify';

export const getOverview = async (request: FastifyRequest, reply: FastifyReply) => {
    try {
        const prisma = request.server.prisma;

        // Get date ranges
        const now = new Date();
        const startOfWeek = new Date(now);
        startOfWeek.setDate(now.getDate() - now.getDay());
        startOfWeek.setHours(0, 0, 0, 0);

        const startOfMonth = new Date(now.getFullYear(), now.getMonth(), 1);

        // Parallel queries for efficiency
        const [
            totalBatches,
            activeBatches,
            totalRooms,
            tasksCompletedThisWeek,
            tasksPending,
            touchPointsToday,
            totalPlants
        ] = await Promise.all([
            prisma.batch.count(),
            prisma.batch.count({ where: { status: 'ACTIVE' } }),
            prisma.room.count(),
            prisma.task.count({
                where: {
                    status: 'COMPLETED',
                    completedAt: { gte: startOfWeek }
                }
            }),
            prisma.task.count({ where: { status: 'PENDING' } }),
            prisma.plantTouchPoint.count({
                where: {
                    createdAt: { gte: new Date(now.setHours(0, 0, 0, 0)) }
                }
            }),
            prisma.batch.aggregate({
                where: { status: 'ACTIVE' },
                _sum: { plantCount: true }
            })
        ]);

        return {
            totalBatches,
            activeBatches,
            totalRooms,
            tasksCompletedThisWeek,
            tasksPending,
            touchPointsToday,
            totalPlants: totalPlants._sum.plantCount || 0
        };
    } catch (error) {
        request.log.error(error);
        return reply.code(500).send({ message: 'Failed to fetch analytics overview' });
    }
};

export const getYieldAnalytics = async (request: FastifyRequest, reply: FastifyReply) => {
    try {
        const prisma = request.server.prisma;

        // Get all weight logs with batch info
        const weightLogs = await prisma.weightLog.findMany({
            include: {
                batch: {
                    select: {
                        id: true,
                        name: true,
                        strain: true,
                        plantCount: true
                    }
                }
            },
            orderBy: { createdAt: 'desc' }
        });

        // Aggregate by batch
        const batchYields: Record<string, {
            batchId: string;
            batchName: string;
            strain: string;
            plantCount: number;
            totalGrams: number;
            logCount: number;
        }> = {};

        for (const log of weightLogs) {
            if (!log.batch) continue;

            if (!batchYields[log.batchId]) {
                batchYields[log.batchId] = {
                    batchId: log.batchId,
                    batchName: log.batch.name,
                    strain: log.batch.strain,
                    plantCount: log.batch.plantCount,
                    totalGrams: 0,
                    logCount: 0
                };
            }

            batchYields[log.batchId].totalGrams += log.weight; // Use 'weight' field
            batchYields[log.batchId].logCount += 1;
        }

        const yieldData = Object.values(batchYields).map(b => ({
            ...b,
            gramsPerPlant: b.plantCount > 0 ? Math.round(b.totalGrams / b.plantCount * 10) / 10 : 0
        }));

        // Aggregate by strain
        const strainYields: Record<string, { strain: string; totalGrams: number; totalPlants: number; batchCount: number }> = {};
        for (const b of yieldData) {
            if (!strainYields[b.strain]) {
                strainYields[b.strain] = { strain: b.strain, totalGrams: 0, totalPlants: 0, batchCount: 0 };
            }
            strainYields[b.strain].totalGrams += b.totalGrams;
            strainYields[b.strain].totalPlants += b.plantCount;
            strainYields[b.strain].batchCount += 1;
        }

        const strainData = Object.values(strainYields).map(s => ({
            ...s,
            avgGramsPerPlant: s.totalPlants > 0 ? Math.round(s.totalGrams / s.totalPlants * 10) / 10 : 0
        }));

        return {
            byBatch: yieldData,
            byStrain: strainData
        };
    } catch (error) {
        request.log.error(error);
        return reply.code(500).send({ message: 'Failed to fetch yield analytics' });
    }
};

export const getTaskAnalytics = async (request: FastifyRequest, reply: FastifyReply) => {
    try {
        const prisma = request.server.prisma;

        const now = new Date();
        const startOfWeek = new Date(now);
        startOfWeek.setDate(now.getDate() - now.getDay());
        startOfWeek.setHours(0, 0, 0, 0);

        // Task counts by status
        const [completed, pending, inProgress, overdue] = await Promise.all([
            prisma.task.count({ where: { status: 'COMPLETED' } }),
            prisma.task.count({ where: { status: 'PENDING' } }),
            prisma.task.count({ where: { status: 'IN_PROGRESS' } }),
            prisma.task.count({
                where: {
                    status: { in: ['PENDING', 'IN_PROGRESS'] },
                    dueDate: { lt: now }
                }
            })
        ]);

        // Tasks completed per user this week
        const tasksPerUser = await prisma.task.groupBy({
            by: ['assignedToId'],
            where: {
                status: 'COMPLETED',
                completedAt: { gte: startOfWeek },
                assignedToId: { not: null }
            },
            _count: { id: true }
        });

        // Get user names
        const userIds = tasksPerUser.map(t => t.assignedToId).filter(Boolean) as string[];
        const users = await prisma.user.findMany({
            where: { id: { in: userIds } },
            select: { id: true, name: true }
        });

        const userMap = Object.fromEntries(users.map(u => [u.id, u.name]));

        const completedByUser = tasksPerUser.map(t => ({
            userId: t.assignedToId,
            userName: userMap[t.assignedToId!] || 'Unknown',
            completedCount: t._count.id
        }));

        return {
            summary: {
                completed,
                pending,
                inProgress,
                overdue,
                total: completed + pending + inProgress
            },
            completedByUserThisWeek: completedByUser
        };
    } catch (error) {
        request.log.error(error);
        return reply.code(500).send({ message: 'Failed to fetch task analytics' });
    }
};
