import { Injectable, NotFoundException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Queue } from './entities/queue.entity';
import { CreateQueueDto } from './dto/create-queue.dto';
import { UpdateQueueDto } from './dto/update-queue.dto';
import { Machine } from '@/machines/entities/machine.entity';
import { Page } from '@/pages/entities/page.entity';
import { Order } from '@/orders/entities/order.entity';
import { Employee } from '@/employees/entities/employee.entity';

@Injectable()
export class QueuesService {
  constructor(
    @InjectRepository(Queue)
    private readonly queueRepository: Repository<Queue>,

    @InjectRepository(Machine)
    private readonly machineRepository: Repository<Machine>,

    @InjectRepository(Page)
    private readonly pageRepository: Repository<Page>,

    @InjectRepository(Order)
    private readonly orderRepository: Repository<Order>,

    @InjectRepository(Employee)
    private readonly employeeRepository: Repository<Employee>,
  ) {}

  async create(createQueueDto: CreateQueueDto) {
    const { MachineID, PageID, OrderID, employeeIds, ...queueData } =
      createQueueDto;

    console.log('📌 Received CreateQueueDto:', createQueueDto);

    // 🔍 Fetch related entities
    const machine = await this.machineRepository.findOne({
      where: { MachineID },
    });
    if (!machine)
      throw new NotFoundException(`Machine with ID ${MachineID} not found`);

    const page = await this.pageRepository.findOne({ where: { PageID } });
    if (!page) throw new NotFoundException(`Page with ID ${PageID} not found`);

    const order = await this.orderRepository.findOne({ where: { OrderID } });
    if (!order)
      throw new NotFoundException(`Order with ID ${OrderID} not found`);

    const employees = await this.employeeRepository.findByIds(employeeIds);
    if (employees.length !== employeeIds.length) {
      throw new NotFoundException(`One or more employees not found`);
    }

    console.log('✅ Related Entities Fetched:');
    console.log('   - Machine:', machine);
    console.log('   - Page:', page);
    console.log('   - Order:', order);
    console.log('   - Employees:', employees);

    // ✅ Create Queue entity and save to DB
    const newQueue = this.queueRepository.create({
      ...queueData,
      machine,
      page,
      order,
      employees,
    });

    console.log('🛠️ Preparing to save new Queue:', newQueue);

    const savedQueue = await this.queueRepository.save(newQueue);

    console.log('✅ Queue saved successfully:', savedQueue);

    // ✅ Return the response with full details
    return {
      message: 'Queue created successfully',
      queue: savedQueue,
    };
  }

  // ✅ Fetch all Queues with relationships
  async findAll() {
    return await this.queueRepository.find({
      relations: ['machine', 'page', 'order', 'employees'],
    });
  }

  // ✅ Fetch a single Queue by ID
  async findOne(id: number) {
    const queue = await this.queueRepository.findOne({
      where: { QueueID: id },
      relations: ['machine', 'page', 'order', 'employees'],
    });

    if (!queue) {
      throw new NotFoundException(`Queue with ID ${id} not found`);
    }

    return queue;
  }

  // ✅ Update Queue
  async update(id: number, updateQueueDto: UpdateQueueDto) {
    const {
      MachineID,
      PageID,
      OrderID,
      employeeIds,
      startTime,
      finishTime,
      ...queueData
    } = updateQueueDto;

    // 🔍 Fetch entities if IDs are provided
    const machine = MachineID
      ? await this.machineRepository.findOne({ where: { MachineID } })
      : undefined;
    if (MachineID && !machine)
      throw new NotFoundException(`Machine with ID ${MachineID} not found`);

    const page = PageID
      ? await this.pageRepository.findOne({ where: { PageID } })
      : undefined;
    if (PageID && !page)
      throw new NotFoundException(`Page with ID ${PageID} not found`);

    const order = OrderID
      ? await this.orderRepository.findOne({ where: { OrderID } })
      : undefined;
    if (OrderID && !order)
      throw new NotFoundException(`Order with ID ${OrderID} not found`);

    const employees = employeeIds
      ? await this.employeeRepository.findByIds(employeeIds)
      : undefined;
    if (employeeIds && employees.length !== employeeIds.length) {
      throw new NotFoundException(`One or more employees not found`);
    }

    // ✅ Convert timestamps from string to Date
    const updateData: Partial<Queue> = {
      ...queueData,
      machine: machine || undefined,
      page: page || undefined,
      order: order || undefined,
      employees: employees || undefined,
      startTime: startTime ? new Date(startTime) : undefined,
      finishTime: finishTime ? new Date(finishTime) : undefined,
    };

    const updateResult = await this.queueRepository.update(id, updateData);
    if (updateResult.affected === 0) {
      throw new NotFoundException(`Queue with ID ${id} not found`);
    }

    return await this.queueRepository.findOne({
      where: { QueueID: id },
      relations: ['machine', 'page', 'order', 'employees'],
    });
  }

  // ✅ Delete Queue
  async remove(id: number) {
    const queue = await this.queueRepository.findOne({
      where: { QueueID: id },
      relations: ['machine', 'page', 'order', 'employees'],
    });

    if (!queue) {
      throw new NotFoundException(`Queue with ID ${id} not found`);
    }

    await this.queueRepository.delete(id);

    return { message: 'Queue deleted successfully', deletedQueue: queue };
  }
}