import { Injectable } from '@nestjs/common';
import { PrismaService } from '../prisma/prisma.service';
import { UsersService } from '../users/users.service';
import { user_role } from '@prisma/client';
import { v4 as uuid } from 'uuid';

@Injectable()
export class StrategicActivitiesService {
    constructor(
        private prisma: PrismaService,
        private usersService: UsersService
    ) { }

    async create(userId: string, data: any) {
        let metadataObj = data.metadata || {};
        if (typeof metadataObj === 'string') {
            try { metadataObj = JSON.parse(metadataObj); } catch (e) { }
        }

        if (data.updateClientStatus && metadataObj.clientId) {
            // Update the client status
            const updatedClient = await this.prisma.client.update({
                where: { id: metadataObj.clientId },
                data: { status: data.updateClientStatus }
            });
            metadataObj.convertedToStatus = data.updateClientStatus;

            // Map client status to opportunity stage
            const stageMap: any = {
                'QUALITY': 'QUALIFIED',
                'POTENTIAL': 'POTENTIAL',
                'DEMO': 'DEMO',
                'SALES': 'WON',
                'CLOSED': 'WON'
            };

            const targetStage = stageMap[data.updateClientStatus];
            if (targetStage) {
                // Check if an opportunity already exists for this client to avoid duplicates
                const existingOpp = await this.prisma.opportunity.findFirst({
                    where: {
                        clientId: metadataObj.clientId,
                        stage: { notIn: ['WON', 'LOST'] as any }
                    }
                });

                if (existingOpp) {
                    // Update existing opportunity stage
                    await this.prisma.opportunity.update({
                        where: { id: existingOpp.id },
                        data: {
                            stage: targetStage as any,
                            updatedAt: new Date()
                        }
                    });
                } else {
                    // Create a new opportunity in the pipeline
                    await this.prisma.opportunity.create({
                        data: {
                            id: uuid(),
                            title: `${updatedClient.name} - ${data.updateClientStatus}`,
                            value: 0,
                            clientId: metadataObj.clientId,
                            assignedTo: userId, // Assign to the person who made the call
                            stage: targetStage as any,
                            updatedAt: new Date()
                        }
                    });
                }
            }
        }

        const stringifiedMetadata = JSON.stringify(metadataObj);

        return this.prisma.strategicActivity.create({
            data: {
                id: uuid(),
                type: data.type,
                description: data.description,
                leadsGenerated: data.leadsGenerated,
                revenueGenerated: data.revenueGenerated,
                metadata: stringifiedMetadata,
                userId,
                updatedAt: new Date()
            }
        });
    }

    async findAll(user: any, filters: any) {
        let allowedUserIds: string[] = [];
        if (user.role === user_role.ADMIN) {
            if (filters.userId) {
                allowedUserIds = [filters.userId];
            }
        } else {
            const subordinateIds = await this.usersService.getSubordinateIds(user.id);
            const myAllowedIds = [user.id, ...subordinateIds];
            if (filters.userId && myAllowedIds.includes(filters.userId)) {
                allowedUserIds = [filters.userId];
            } else {
                allowedUserIds = myAllowedIds;
            }
        }

        const where: any = {};
        if (allowedUserIds.length > 0) {
            where.userId = { in: allowedUserIds };
        }

        if (filters.startDate || filters.endDate) {
            where.createdAt = {};
            if (filters.startDate) where.createdAt.gte = new Date(filters.startDate);
            if (filters.endDate) {
                const end = new Date(filters.endDate);
                end.setHours(23, 59, 59, 999);
                where.createdAt.lte = end;
            }
        }

        if (filters.clientId) {
            where.metadata = { contains: filters.clientId };
        }

        return this.prisma.strategicActivity.findMany({
            where,
            include: { user: { select: { name: true } } },
            orderBy: { createdAt: 'desc' }
        });
    }

    async getStats(userId: string) {
        const activities = await this.prisma.strategicActivity.groupBy({
            by: ['type'],
            where: { userId },
            _count: true
        });
        return activities;
    }
}
