import { Injectable } from '@nestjs/common';
import { type PrismaService } from '@modules/shared';
import type {
  AgentDashboardData,
  IAgentRepository,
} from '../../domain/repositories/agent.repository';

@Injectable()
export class PrismaAgentRepository implements IAgentRepository {
  constructor(private readonly prisma: PrismaService) {}

  async findByUserId(
    userId: string,
  ): Promise<{ id: string; userId: string; qualityScore: number } | null> {
    return this.prisma.agent.findUnique({
      where: { userId },
      select: { id: true, userId: true, qualityScore: true },
    });
  }

  async findById(
    agentId: string,
  ): Promise<{ id: string; userId: string; qualityScore: number } | null> {
    return this.prisma.agent.findUnique({
      where: { id: agentId },
      select: { id: true, userId: true, qualityScore: true },
    });
  }

  async updateQualityScore(agentId: string, score: number): Promise<void> {
    await this.prisma.agent.update({
      where: { id: agentId },
      data: { qualityScore: score },
    });
  }

  async getDashboard(agentId: string): Promise<AgentDashboardData> {
    const [agent, leads, inquiryStats, listingStats, reviewStats] =
      await Promise.all([
        this.prisma.agent.findUniqueOrThrow({
          where: { id: agentId },
          select: {
            id: true,
            qualityScore: true,
            totalDeals: true,
            responseTimeAvg: true,
            isVerified: true,
          },
        }),
        this.prisma.lead.groupBy({
          by: ['status'],
          where: { agentId },
          _count: { id: true },
        }),
        this.getInquiryStats(agentId),
        this.getListingStats(agentId),
        this.prisma.review.aggregate({
          where: { targetType: 'AGENT', targetId: agentId },
          _avg: { rating: true },
          _count: { rating: true },
        }),
      ]);

    const leadsByStatus: Record<string, number> = {};
    let totalLeads = 0;
    let convertedLeads = 0;

    for (const group of leads) {
      leadsByStatus[group.status] = group._count.id;
      totalLeads += group._count.id;
      if (group.status === 'CONVERTED') {
        convertedLeads = group._count.id;
      }
    }

    const conversionRate = totalLeads > 0 ? convertedLeads / totalLeads : 0;

    return {
      agentId: agent.id,
      qualityScore: agent.qualityScore,
      totalDeals: agent.totalDeals,
      responseTimeAvg: agent.responseTimeAvg,
      isVerified: agent.isVerified,
      totalLeads,
      leadsByStatus,
      conversionRate: Math.round(conversionRate * 1000) / 1000, // 3 decimals
      totalInquiries: inquiryStats.total,
      unreadInquiries: inquiryStats.unread,
      totalListings: listingStats.total,
      activeListings: listingStats.active,
      avgReviewRating:
        Math.round((reviewStats._avg.rating ?? 0) * 10) / 10,
      totalReviews: reviewStats._count.rating,
    };
  }

  private async getInquiryStats(
    agentId: string,
  ): Promise<{ total: number; unread: number }> {
    const [total, unread] = await Promise.all([
      this.prisma.inquiry.count({
        where: { listing: { agentId } },
      }),
      this.prisma.inquiry.count({
        where: { listing: { agentId }, isRead: false },
      }),
    ]);
    return { total, unread };
  }

  private async getListingStats(
    agentId: string,
  ): Promise<{ total: number; active: number }> {
    const [total, active] = await Promise.all([
      this.prisma.listing.count({ where: { agentId } }),
      this.prisma.listing.count({
        where: { agentId, status: 'ACTIVE' },
      }),
    ]);
    return { total, active };
  }
}
