import { Injectable, NotFoundException, BadRequestException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { KYCVerification } from './entities/kyc-verification.entity';
import { KYCDocument } from './entities/kyc-document.entity';
import { KYCReviewLog } from './entities/kyc-review-log.entity';
import { StorageService } from '../storage/storage.service';
import { NotificationsService } from '../notifications/notifications.service';
import { UsersService } from '../users/users.service';
import { SubmitKYCDto } from './dto/submit-kyc.dto';
import { BusinessInfoDto } from './dto/business-info.dto';
import { KYCStatus, KYCType, DocumentType, DocumentStatus } from '@livebeauty/shared';

@Injectable()
export class KYCService {
  constructor(
    @InjectRepository(KYCVerification)
    private readonly kycRepo: Repository<KYCVerification>,
    @InjectRepository(KYCDocument)
    private readonly docRepo: Repository<KYCDocument>,
    @InjectRepository(KYCReviewLog)
    private readonly logRepo: Repository<KYCReviewLog>,
    private readonly storageService: StorageService,
    private readonly notificationsService: NotificationsService,
    private readonly usersService: UsersService,
  ) {}

  async submitIdentityInfo(userId: string, dto: SubmitKYCDto): Promise<KYCVerification> {
    const existing = await this.kycRepo.findOne({
      where: { userId },
      order: { createdAt: 'DESC' },
    });

    if (existing && existing.status === KYCStatus.APPROVED) {
      throw new BadRequestException('KYC already verified');
    }

    const verification = this.kycRepo.create({
      userId,
      type: dto.type,
      status: KYCStatus.PENDING,
      identityData: {
        fullName: dto.fullName,
        dateOfBirth: dto.dateOfBirth,
        nationality: dto.nationality,
        idNumber: dto.idNumber,
        idType: dto.idType,
        address: dto.address,
        phoneNumber: dto.phoneNumber,
        email: dto.email,
      },
      submittedAt: new Date(),
    });

    const saved = await this.kycRepo.save(verification);

    await this.notificationsService.sendToUser(userId, {
      type: 'kyc_started',
      data: { verificationId: saved.id, message: 'Identity information submitted. Please upload required documents.' },
    });

    return saved;
  }

  async uploadDocument(
    userId: string,
    verificationId: string,
    file: Express.Multer.File,
    documentType: DocumentType,
  ): Promise<KYCDocument> {
    const verification = await this.kycRepo.findOne({
      where: { id: verificationId, userId },
      relations: ['documents'],
    });

    if (!verification) throw new NotFoundException('Verification not found');

    // Validate file
    this.validateDocument(file, documentType);

    // Save to local storage
    const filePath = await this.storageService.saveLocal(
      file.buffer,
      `kyc/${documentType}`,
      `${Date.now()}-${file.originalname}`,
    );

    const document = this.docRepo.create({
      verificationId,
      type: documentType,
      filePath,
      fileName: file.originalname,
      mimeType: file.mimetype,
      fileSize: file.size,
      status: DocumentStatus.PENDING,
    });

    return this.docRepo.save(document);
  }

  async submitBusinessInfo(userId: string, dto: BusinessInfoDto): Promise<KYCVerification> {
    const verification = await this.kycRepo.findOne({
      where: { userId, type: KYCType.SELLER },
      order: { createdAt: 'DESC' },
    });

    if (!verification) {
      throw new BadRequestException('Submit identity information first');
    }

    verification.businessData = {
      businessName: dto.businessName,
      registrationNumber: dto.registrationNumber,
      taxNumber: dto.taxNumber,
      businessType: dto.businessType,
      businessAddress: dto.businessAddress,
      website: dto.website,
      businessDescription: dto.businessDescription,
    };

    return this.kycRepo.save(verification);
  }

  async uploadSelfie(userId: string, verificationId: string, file: Express.Multer.File): Promise<KYCDocument> {
    return this.uploadDocument(userId, verificationId, file, DocumentType.SELFIE);
  }

  async finalizeSubmission(userId: string, verificationId: string): Promise<KYCVerification> {
    const verification = await this.kycRepo.findOne({
      where: { id: verificationId, userId },
      relations: ['documents'],
    });

    if (!verification) throw new NotFoundException('Verification not found');

    // Validate all required documents are present
    const requiredDocs = this.getRequiredDocuments(verification.type);
    const uploadedTypes = verification.documents?.map(d => d.type) || [];

    const missingDocs = requiredDocs.filter(req => !uploadedTypes.includes(req));
    if (missingDocs.length > 0) {
      throw new BadRequestException(`Missing required documents: ${missingDocs.join(', ')}`);
    }

    verification.status = KYCStatus.UNDER_REVIEW;
    verification.submittedAt = new Date();
    await this.kycRepo.save(verification);

    // Notify admin team
    await this.notificationsService.sendToAdmins({
      type: 'kyc_submitted',
      data: {
        verificationId: verification.id,
        userId: verification.userId,
        type: verification.type,
        submittedAt: verification.submittedAt,
      },
    });

    // Notify user
    await this.notificationsService.sendToUser(userId, {
      type: 'kyc_status_update',
      data: { status: KYCStatus.UNDER_REVIEW, message: 'Your documents are under review' },
    });

    return verification;
  }

  async getVerificationStatus(userId: string): Promise<KYCVerification | null> {
    return this.kycRepo.findOne({
      where: { userId },
      order: { createdAt: 'DESC' },
      relations: ['documents'],
    });
  }

  private validateDocument(file: Express.Multer.File, type: DocumentType): void {
    const maxSize = 10 * 1024 * 1024; // 10MB
    const allowedTypes = ['image/jpeg', 'image/png', 'image/webp', 'application/pdf'];

    if (file.size > maxSize) {
      throw new BadRequestException('File too large (max 10MB)');
    }

    if (!allowedTypes.includes(file.mimetype)) {
      throw new BadRequestException('Invalid file type (JPEG, PNG, WebP, PDF only)');
    }
  }

  private getRequiredDocuments(type: KYCType): DocumentType[] {
    const buyerDocs: DocumentType[] = [DocumentType.ID_FRONT, DocumentType.ID_BACK, DocumentType.SELFIE];
    const sellerDocs: DocumentType[] = [
      DocumentType.ID_FRONT, DocumentType.ID_BACK, DocumentType.SELFIE,
      DocumentType.BUSINESS_LICENSE, DocumentType.TAX_DOCUMENT,
    ];
    return type === KYCType.BUYER ? buyerDocs : sellerDocs;
  }
}