import { Injectable, NotFoundException, Logger } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository, Connection } from 'typeorm';
import { Order } from './entities/order.entity';
import { CreateOrderDto } from './dto/create-order.dto';
import { UpdateOrderDto } from './dto/update-order.dto';
import { Product } from '@/products/entities/product.entity';
import { OrderPriority } from '@/orderpiorities/entities/orderpiority.entity';
import { Page } from '@/pages/entities/page.entity';
import { OrderDetail } from '@/order_details/entities/order_detail.entity';

@Injectable()
export class OrdersService {
  private readonly logger = new Logger(OrdersService.name);

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

    @InjectRepository(Product)
    private readonly productRepository: Repository<Product>,

    @InjectRepository(OrderPriority)
    private readonly orderpiorityRepository: Repository<OrderPriority>,

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

    private readonly connection: Connection,
  ) {}

  async create(createOrderDto: CreateOrderDto): Promise<Order> {
    this.logger.log(
      `Creating or updating order for customer ${createOrderDto.customerID}`,
    );

    return await this.connection.transaction(async (manager) => {
      const isUpdate = !!createOrderDto.orderID;

      // ✅ Map orderDetails จาก product
      if (createOrderDto.orderDetails?.length > 0) {
        for (const detail of createOrderDto.orderDetails) {
          const product = await this.productRepository.findOne({
            where: { ProductID: detail.productID },
          });
          if (!product) {
            throw new NotFoundException(
              `Product with ID ${detail.productID} not found`,
            );
          }
          detail.Productname = `${product.brand} ${product.size}`;
          detail.size = product.size;
          detail.waterBrand = product.brand;
          detail.status = detail.status || 'Active';
          detail.totalPrice = detail.quantity * detail.pricePerUnit;
        }
      }

      // ✅ Default status
      if (!createOrderDto.status) {
        createOrderDto.status = 'กำลังรอ';
      }

      let order: Order;

      if (isUpdate) {
        const existing = await this.orderRepository.findOne({
          where: { OrderID: createOrderDto.orderID },
          relations: ['orderDetails'],
        });

        if (!existing) {
          throw new NotFoundException(
            `Order with ID ${createOrderDto.orderID} not found`,
          );
        }

        Object.assign(existing, createOrderDto);

        if (createOrderDto.orderDetails) {
          // ✅ ตัด entity.order = existing ออก เพื่อไม่ให้เกิด recursive loop
          const orderDetailEntities = createOrderDto.orderDetails.map((dto) =>
            this.orderDetailRepository.create(dto),
          );

          existing.orderDetails = orderDetailEntities;
        }

        order = await manager.save(existing);
        this.logger.log(`Order updated with ID ${order.OrderID}`);
      } else {
        order = this.orderRepository.create(createOrderDto);
        order = await manager.save(order);
        this.logger.log(`Order created with ID ${order.OrderID}`);
      }

      // ✅ สร้าง OrderPriority ให้ทุกหน้า (ถ้ายังไม่มี)
      const allPages = await this.pageRepository.find({
        relations: ['orderPriorities'],
      });

      for (const page of allPages) {
        const alreadyExists = page.orderPriorities.some(
          (op) => op.order?.OrderID === order.OrderID,
        );
        if (!alreadyExists) {
          const newPriority = this.orderpiorityRepository.create({
            order,
            page,
            priority: page.orderPriorities.length + 1,
          });
          await manager.save(newPriority);
          this.logger.log(`Created OrderPriority for Page ${page.PageID}`);
        }
      }

      return order;
    });
  }
  async upsertMany(ordersDto: CreateOrderDto[]): Promise<Order[]> {
    this.logger.log(`Upserting ${ordersDto.length} order(s)`);

    return await this.connection.transaction(async (manager) => {
      const upsertedOrders: Order[] = [];

      // ดึง Page ทั้งหมดมาไว้ก่อน
      const allPages = await this.pageRepository.find({
        relations: ['orderPriorities'],
      });

      for (const dto of ordersDto) {
        // ถ้าไม่มี status → ตั้ง default
        if (!dto.status) {
          dto.status = 'กำลังรอ';
        }

        // ถ้ามี orderDetails → map ข้อมูลจาก Product
        if (dto.orderDetails && dto.orderDetails.length > 0) {
          for (const detail of dto.orderDetails) {
            const product = await this.productRepository.findOne({
              where: { ProductID: detail.productID },
            });
            if (!product) {
              throw new NotFoundException(
                `Product with ID ${detail.productID} not found`,
              );
            }

            detail.Productname = `${product.brand} ${product.size}`;
            detail.size = product.size;
            detail.waterBrand = product.brand;
            detail.status = detail.status || 'Active';
            detail.totalPrice = detail.quantity * detail.pricePerUnit;
          }
        }

        // Save Order
        const orderEntity = this.orderRepository.create(dto);
        const savedOrder = await manager.save(orderEntity);
        upsertedOrders.push(savedOrder);
        this.logger.log(`📝 Order upserted with ID ${savedOrder.OrderID}`);

        // 🔁 สร้าง OrderPriority ให้ทุก Page ถ้ายังไม่มี
        for (const page of allPages) {
          const alreadyExists = page.orderPriorities?.some(
            (op) => op.order?.OrderID === savedOrder.OrderID,
          );
          if (!alreadyExists) {
            const newPriority = this.orderpiorityRepository.create({
              order: savedOrder,
              page: page,
              priority: page.orderPriorities.length + 1,
            });
            const savedPriority = await manager.save(newPriority);
            page.orderPriorities.push(savedPriority);
            this.logger.log(
              `📌 OrderPriority created in Page ${page.PageID} for Order ${savedOrder.OrderID}`,
            );
          }
        }
      }

      return upsertedOrders;
    });
  }

  async findAll(): Promise<Order[]> {
    this.logger.log('Fetching all orders with orderDetails');
    const orders = await this.orderRepository.find({
      relations: ['orderDetails'],
    });
    this.logger.log(`Fetched ${orders.length} order(s)`);
    return orders;
  }

  async findOne(id: number): Promise<Order> {
    this.logger.log(`Fetching order with ID ${id}`);
    const order = await this.orderRepository.findOne({
      where: { OrderID: id },
      relations: ['orderDetails'],
    });
    if (!order) {
      this.logger.error(`Order with ID ${id} not found`);
      throw new NotFoundException(`Order with ID ${id} not found`);
    }
    this.logger.log(`Order with ID ${id} fetched successfully`);
    return order;
  }

  async update(id: number, updateOrderDto: UpdateOrderDto): Promise<Order> {
    this.logger.log(`Updating order with ID ${id}`);
    await this.orderRepository.update(id, updateOrderDto);
    const updatedOrder = await this.findOne(id);
    this.logger.log(`Order with ID ${id} updated successfully`);
    return updatedOrder;
  }

  async remove(id: number): Promise<Order> {
    this.logger.log(`Deleting order with ID ${id}`);

    // ✅ หา order พร้อมดึง orderDetails มา
    const order = await this.orderRepository.findOne({
      where: { OrderID: id },
      relations: ['orderDetails'],
    });

    if (!order) {
      this.logger.error(`Order with ID ${id} not found for deletion`);
      throw new NotFoundException(`Order with ID ${id} not found`);
    }

    // ✅ ลบ orderDetails ทีละตัว
    if (order.orderDetails && order.orderDetails.length > 0) {
      this.logger.log(
        `Deleting ${order.orderDetails.length} orderDetails for order ID ${id}`,
      );
      await this.orderDetailRepository.remove(order.orderDetails);
    }

    // ✅ ลบ order หลังจากลบ orderDetails
    await this.orderRepository.remove(order);

    this.logger.log(`Order with ID ${id} and its orderDetails deleted`);

    return order; // ส่งกลับ order ที่ลบไป (หรือจะเปลี่ยนเป็น message เฉยๆ ก็ได้)
  }
}