import { Injectable, NotFoundException, BadRequestException, ForbiddenException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Order } from '@/entities/order.entity';
import { Room } from '@/entities/room.entity';
import { RoomCalendar } from '@/entities/room-calendar.entity';
import { QueryOrderDto } from './dto/order.dto';

@Injectable()
export class MerchantOrderService {
  constructor(
    @InjectRepository(Order)
    private orderRepo: Repository<Order>,
    @InjectRepository(Room)
    private roomRepo: Repository<Room>,
    @InjectRepository(RoomCalendar)
    private calendarRepo: Repository<RoomCalendar>,
  ) {}

  async findByMerchant(merchantId: number, query: QueryOrderDto) {
    const { page = 1, pageSize = 10, status, orderNo, startDate, endDate } = query;
    const qb = this.orderRepo.createQueryBuilder('o')
      .leftJoinAndSelect('o.room', 'r')
      .leftJoinAndSelect('o.user', 'u')
      .where('o.merchant_id = :merchantId', { merchantId });

    if (status) qb.andWhere('o.status = :status', { status });
    if (orderNo) qb.andWhere('o.order_no LIKE :orderNo', { orderNo: `%${orderNo}%` });
    if (startDate) qb.andWhere('o.created_at >= :startDate', { startDate });
    if (endDate) qb.andWhere('o.created_at <= :endDate', { endDate });

    qb.orderBy('o.createdAt', 'DESC');
    qb.skip((page - 1) * pageSize).take(pageSize);

    const [list, total] = await qb.getManyAndCount();
    return { list, total, page, pageSize, totalPages: Math.ceil(total / pageSize) };
  }

  async findOne(identifier: string | number) {
    const whereCondition = typeof identifier === 'number'
      ? { id: identifier }
      : { orderNo: identifier };

    const order = await this.orderRepo.findOne({
      where: whereCondition,
      relations: ['room', 'merchant', 'user'],
    });

    if (!order) throw new NotFoundException('订单不存在');
    return order;
  }

  async confirm(merchantId: number, orderNo: string) {
    const order = await this.findOne(orderNo);
    if (order.merchantId !== merchantId) throw new ForbiddenException('无权操作此订单');
    if (order.status !== 'pending_confirm') {
      throw new BadRequestException('当前订单状态不可确认');
    }

    await this.orderRepo.update(order.id, {
      status: 'pending_checkin',
      confirmedAt: new Date(),
    });
    return { message: '订单已确认' };
  }

  async reject(merchantId: number, orderNo: string, reason: string) {
    const order = await this.findOne(orderNo);
    if (order.merchantId !== merchantId) throw new ForbiddenException('无权操作此订单');
    if (order.status !== 'pending_confirm') {
      throw new BadRequestException('当前订单状态不可拒绝');
    }

    await this.orderRepo.update(order.id, {
      status: 'cancelled',
      cancelReason: reason,
      cancelledAt: new Date(),
    });
    return { message: '订单已拒绝' };
  }

  async checkin(merchantId: number, orderNo: string) {
    const order = await this.findOne(orderNo);
    if (order.merchantId !== merchantId) throw new ForbiddenException('无权操作此订单');
    if (order.status !== 'pending_checkin') {
      throw new BadRequestException('当前订单状态不可办理入住');
    }

    await this.orderRepo.update(order.id, {
      status: 'checked_in',
      checkinAt: new Date(),
    });
    return { message: '已办理入住' };
  }

  async checkout(merchantId: number, orderNo: string) {
    const order = await this.findOne(orderNo);
    if (order.merchantId !== merchantId) throw new ForbiddenException('无权操作此订单');
    if (order.status !== 'checked_in') {
      throw new BadRequestException('当前订单状态不可确认离店');
    }

    // 检查是否已到离店日期
    const today = new Date().toISOString().split('T')[0];
    if (order.checkOutDate > today) {
      throw new BadRequestException('未到离店日期，不可确认离店');
    }

    await this.orderRepo.update(order.id, {
      status: 'completed',
      checkoutAt: new Date(),
    });

    return { message: '已确认离店，订单已完成' };
  }
}
