import {
  BadRequestException,
  ConflictException,
  ForbiddenException,
  Injectable,
  NotFoundException,
} from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Children, StatutEnfantType } from 'src/entities/children.entity';
import { Parents } from 'src/entities/parents.entity';
import { ParentsChildren } from 'src/entities/parents_children.entity';
import { RoleType, Users } from 'src/entities/users.entity';
import { CreateEnfantsDto } from './dto/create_enfants.dto';

@Injectable()
export class EnfantsService {
  constructor(
    @InjectRepository(Children)
    private readonly childrenRepository: Repository<Children>,
    @InjectRepository(Parents)
    private readonly parentsRepository: Repository<Parents>,
    @InjectRepository(ParentsChildren)
    private readonly parentsChildrenRepository: Repository<ParentsChildren>,
  ) { }

  // Création d'un enfant
  async create(dto: CreateEnfantsDto, currentUser: Users, photoFile?: Express.Multer.File): Promise<Children> {
    const parent = await this.parentsRepository.findOne({
      where: { user_id: currentUser.id },
      relations: ['co_parent'],
    });
    if (!parent) throw new NotFoundException('Parent introuvable');

    // Vérif métier simple
    if (dto.status !== StatutEnfantType.A_NAITRE && !dto.birth_date) {
      throw new BadRequestException('Un enfant actif doit avoir une date de naissance');
    }

    // Vérif doublon éventuel (ex: même prénom + date de naissance pour ce parent)
    const exist = await this.childrenRepository.findOne({
      where: {
        first_name: dto.first_name,
        last_name: dto.last_name,
        birth_date: dto.birth_date ? new Date(dto.birth_date) : undefined,
      },
    });
    if (exist) throw new ConflictException('Cet enfant existe déjà');

    // Gestion de la photo uploadée
    if (photoFile) {
      dto.photo_url = `/uploads/photos/${photoFile.filename}`;
      if (dto.consent_photo) {
        dto.consent_photo_at = new Date().toISOString();
      }
    }

    // Création
    const child = this.childrenRepository.create(dto);
    await this.childrenRepository.save(child);

    // Lien parent-enfant (Parent 1)
    const parentLink = this.parentsChildrenRepository.create({
      parentId: parent.user_id,
      enfantId: child.id,
    });
    await this.parentsChildrenRepository.save(parentLink);

    // Rattachement automatique au co-parent s'il existe
    if (parent.co_parent) {
      const coParentLink = this.parentsChildrenRepository.create({
        parentId: parent.co_parent.id,
        enfantId: child.id,
      });
      await this.parentsChildrenRepository.save(coParentLink);
    }

    return this.findOne(child.id, currentUser);
  }

  // Liste des enfants
  async findAll(): Promise<Children[]> {
    return this.childrenRepository.find({
      relations: ['parentLinks'],
      order: { last_name: 'ASC', first_name: 'ASC' },
    });
  }

  // Récupérer un enfant par id
  async findOne(id: string, currentUser: Users): Promise<Children> {
    const child = await this.childrenRepository.findOne({
      where: { id },
      relations: ['parentLinks'],
    });
    if (!child) throw new NotFoundException('Enfant introuvable');

    switch (currentUser.role) {
      case RoleType.PARENT:
        if (!child.parentLinks.some(link => link.parentId === currentUser.id)) {
          throw new ForbiddenException('Cet enfant ne vous appartient pas');
        }
        break;

      case RoleType.ADMINISTRATEUR:
      case RoleType.SUPER_ADMIN:
      case RoleType.GESTIONNAIRE:
        // accès complet
        break;

      default:
        throw new ForbiddenException('Accès interdit');
    }

    return child;
  }


  // Mise à jour
  async update(id: string, dto: Partial<CreateEnfantsDto>, currentUser: Users): Promise<Children> {
    const child = await this.childrenRepository.findOne({ where: { id } });
    if (!child) throw new NotFoundException('Enfant introuvable');

    await this.childrenRepository.update(id, dto);
    return this.findOne(id, currentUser);
  }

  // Suppression
  async remove(id: string): Promise<void> {
    await this.childrenRepository.delete(id);
  }
}
