import { Injectable } from '@nestjs/common';
import { CreateClientDto } from './dto/create-client.dto';
import { UpdateClientDto } from './dto/update-client.dto';
import { PrismaService } from '../prisma/prisma.service';
import { UsersService } from '../users/users.service';
import { WhatsappService } from '../whatsapp/whatsapp.service';
import { user_role, client_status } from '@prisma/client';

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

  async create(createClientDto: CreateClientDto) {
    console.log('API Received Client DTO:', JSON.stringify(createClientDto, null, 2));
    const { id: _, user: __, createdAt: ___, updatedAt: ____, enquiries: _____, followups: ______, meetings: _______, opportunities: ________, files, ...data } = createClientDto as any;

    // Convert empty strings to null for optional DB fields
    if (data.assignedTo === '') data.assignedTo = null;
    if (data.companyName === '') data.companyName = null;
    if (data.contactName === '') data.contactName = null;
    if (data.expectedClosingTimeframe === '') data.expectedClosingTimeframe = null;

    const client = await this.prisma.client.create({
      data: {
        ...data,
        files: files && files.length > 0 ? {
          create: files.map((f: any) => ({
            name: f.name,
            url: f.url,
            size: f.size,
            type: f.type
          }))
        } : undefined
      },
      include: { files: true }
    });

    // Trigger onboarding message if client is created with SALES status
    if (client.status === client_status.SALES || client.status === client_status.CLOSED) {
      try {
        await this.whatsappService.sendOnboarding(client.phone, client.name, client.id.substring(0, 8));
      } catch (err) {
        console.error('Failed to send onboarding WhatsApp:', err.message);
      }
    }

    return client;
  }

  async findAll(user: any) {
    try {
      console.log(`[ClientsService] findAll called for user: ${user.id}, role: ${user.role}`);
      
      // Use string literal for role check to be safe against enum mismatch
      if (user.role === 'ADMIN') {
        return await this.prisma.client.findMany({
          include: { 
            user: {
                select: { id: true, name: true, email: true, role: true }
            }, 
            files: true 
          }
        });
      }

      const subordinateIds = await this.usersService.getSubordinateIds(user.id);
      const allowedUserIds = [user.id, ...subordinateIds];

      return await this.prisma.client.findMany({
        where: {
          assignedTo: { in: allowedUserIds }
        },
        include: { 
            user: {
                select: { id: true, name: true, email: true, role: true }
            }, 
            files: true 
        }
      });
    } catch (error) {
      const fs = require('fs');
      const errorMsg = `[${new Date().toISOString()}] Error in ClientsService.findAll: ${error.message}\nStack: ${error.stack}\n`;
      fs.appendFileSync('API_ERROR_FOUND.txt', errorMsg);
      console.error('Error in ClientsService.findAll:', error);
      throw error;
    }
  }

  findOne(id: string) {
    return this.prisma.client.findUnique({
      where: { id },
      include: { user: true, meetings: true, files: true }
    });
  }

  update(id: string, updateClientDto: UpdateClientDto) {
    const { id: _, user: __, createdAt: ___, updatedAt: ____, enquiries: _____, followups: ______, meetings: _______, opportunities: ________, files, ...data } = updateClientDto as any;

    // Convert empty strings to null for optional DB fields to avoid foreign key or constraint issues
    if (data.assignedTo === '') data.assignedTo = null;
    if (data.companyName === '') data.companyName = null;
    if (data.contactName === '') data.contactName = null;
    if (data.expectedClosingTimeframe === '') data.expectedClosingTimeframe = null;

    return this.prisma.client.update({
      where: { id },
      data: {
        ...data,
        files: files ? {
          deleteMany: {},
          create: files.map((f: any) => ({
            name: f.name,
            url: f.url,
            size: f.size,
            type: f.type
          }))
        } : undefined
      },
      include: { files: true }
    });
  }

  remove(id: string) {
    return this.prisma.client.delete({ where: { id } });
  }
}
