import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository, DeepPartial } from 'typeorm';
import { QualityCheck } from '../entities/quality-check.entity';
import { Inspection } from '../entities/inspection.entity';
import { OrderItem } from '../entities/order-item.entity';
import { CreateQualityCheckDto } from '../dto/create-quality-check.dto';
import { UpdateQualityCheckDto } from '../dto/update-quality-check.dto';

@Injectable()
export class QualityControlService {
  constructor(
    @InjectRepository(QualityCheck)
    private qualityCheckRepository: Repository<QualityCheck>,
    @InjectRepository(Inspection)
    private inspectionRepository: Repository<Inspection>,
    @InjectRepository(OrderItem)
    private orderItemRepository: Repository<OrderItem>,
  ) {}

  async createQualityCheck(
    createDto: CreateQualityCheckDto,
  ): Promise<QualityCheck> {
    const orderItem = await this.orderItemRepository.findOne({
      where: { id: createDto.orderItemId },
      relations: ['order'],
    });

    if (!orderItem) {
      throw new Error('Order item not found');
    }

    const qualityCheck = this.qualityCheckRepository.create({
      ...createDto,
      status: 'pass' as any,
      createdAt: new Date(),
    });

    return this.qualityCheckRepository.save(qualityCheck);
  }

  async getQualityChecks(
    status?: string,
    productionLineId?: string,
  ): Promise<QualityCheck[]> {
    const query = this.qualityCheckRepository
      .createQueryBuilder('check')
      .leftJoinAndSelect('check.orderItem', 'item')
      .leftJoinAndSelect('item.order', 'order')
      .leftJoinAndSelect('item.productionLine', 'line')
      .orderBy('check.createdAt', 'DESC');

    if (status) {
      query.where('check.status = :status', { status });
    }

    if (productionLineId) {
      query.andWhere('line.id = :productionLineId', { productionLineId });
    }

    return query.getMany();
  }

  async updateQualityCheck(
    id: string,
    updateDto: UpdateQualityCheckDto,
  ): Promise<QualityCheck> {
    const qualityCheck = await this.qualityCheckRepository.findOne({
      where: { id },
      relations: ['orderItem'],
    });

    if (!qualityCheck) {
      throw new Error('Quality check not found');
    }

    Object.assign(qualityCheck, updateDto);
    return this.qualityCheckRepository.save(qualityCheck);
  }

  async createInspection(
    qualityCheckId: string,
    inspectionData: any,
  ): Promise<Inspection> {
    const qualityCheck = await this.qualityCheckRepository.findOne({
      where: { id: qualityCheckId },
      relations: ['orderItem'],
    });

    if (!qualityCheck) {
      throw new Error('Quality check not found');
    }

    const inspection: DeepPartial<Inspection> = {
      qualityCheckId,
      ...inspectionData,
      createdAt: new Date(),
    };

    return this.inspectionRepository.save(inspection);
  }

  async getInspectionHistory(
    qualityCheckId: string,
  ): Promise<Inspection[]> {
    return this.inspectionRepository.find({
      where: { qualityCheckId },
      order: { createdAt: 'DESC' },
    });
  }

  async getQualityMetrics(): Promise<any> {
    const [totalChecks, passedChecks, failedChecks] = await Promise.all([
      this.qualityCheckRepository.count(),
      this.qualityCheckRepository.count({
        where: { status: 'pass' as any },
      }),
      this.qualityCheckRepository.count({
        where: { status: 'fail' as any },
      }),
    ]);

    const inspectionRate = await this.qualityCheckRepository
      .createQueryBuilder('check')
      .leftJoinAndSelect('check.inspections', 'inspection')
      .select('COUNT(DISTINCT check.id)', 'total')
      .addSelect('COUNT(inspection.id)', 'inspections')
      .getRawOne();

    return {
      totalChecks,
      passedChecks,
      failedChecks,
      passRate: totalChecks > 0
        ? Math.round((passedChecks / totalChecks) * 100)
        : 0,
      inspectionRate: inspectionRate.total > 0
        ? Math.round((inspectionRate.inspections / inspectionRate.total) * 100)
        : 0,
    };
  }

  // Additional methods for controller compatibility
  async submitInspection(submitDto: any): Promise<Inspection> {
    return this.createInspection(submitDto.qualityCheckId, submitDto);
  }

  async getQualityChecksByStatus(status: 'pass' | 'fail'): Promise<QualityCheck[]> {
    return this.qualityCheckRepository.find({
      where: { status },
      relations: ['orderItem', 'inspections'],
    });
  }
}
