import { Injectable, NotFoundException, ConflictException } from '@nestjs/common';
import { PrismaService } from '@core/database/prisma/prisma.service';
import {
  CreateStorageLocationDto,
  UpdateStorageLocationDto,
  QueryStorageLocationDto,
} from '../dto/storage-location.dto';

@Injectable()
export class StorageLocationService {
  constructor(private readonly prisma: PrismaService) {}

  async create(dto: CreateStorageLocationDto) {
    // 检查仓库是否存在
    const warehouse = await this.prisma.warehouse.findUnique({
      where: { id: dto.warehouseId },
    });

    if (!warehouse || warehouse.deletedAt) {
      throw new NotFoundException('仓库不存在');
    }

    // 检查编码是否已存在（同一仓库内唯一）
    const existing = await this.prisma.storageLocation.findUnique({
      where: {
        warehouseId_code: {
          warehouseId: dto.warehouseId,
          code: dto.code,
        },
      },
    });

    if (existing) {
      throw new ConflictException(`仓位编码 ${dto.code} 在该仓库中已存在`);
    }

    return this.prisma.storageLocation.create({
      data: dto,
      include: {
        warehouse: {
          select: { id: true, code: true, nameEn: true, nameCn: true },
        },
        _count: {
          select: { parts: true },
        },
      },
    });
  }

  async findAll(query: QueryStorageLocationDto) {
    const { warehouseId, search, zone, status, page = 1, limit = 20 } = query;

    const where: any = {
      deletedAt: null,
    };

    if (warehouseId) {
      where.warehouseId = warehouseId;
    }

    if (search) {
      where.OR = [
        { code: { contains: search, mode: 'insensitive' } },
        { nameEn: { contains: search, mode: 'insensitive' } },
        { nameCn: { contains: search, mode: 'insensitive' } },
      ];
    }

    if (zone) {
      where.zone = zone;
    }

    if (status) {
      where.status = status;
    }

    const [items, total] = await Promise.all([
      this.prisma.storageLocation.findMany({
        where,
        include: {
          warehouse: {
            select: { id: true, code: true, nameEn: true, nameCn: true },
          },
          _count: {
            select: { parts: true },
          },
        },
        orderBy: [{ sortOrder: 'asc' }, { code: 'asc' }],
        skip: (page - 1) * limit,
        take: limit,
      }),
      this.prisma.storageLocation.count({ where }),
    ]);

    return {
      items,
      total,
      page,
      limit,
      totalPages: Math.ceil(total / limit),
    };
  }

  async findOne(id: string) {
    const location = await this.prisma.storageLocation.findUnique({
      where: { id },
      include: {
        warehouse: {
          select: { id: true, code: true, nameEn: true, nameCn: true },
        },
        _count: {
          select: { parts: true },
        },
      },
    });

    if (!location || location.deletedAt) {
      throw new NotFoundException('仓位不存在');
    }

    return location;
  }

  async update(id: string, dto: UpdateStorageLocationDto) {
    const location = await this.findOne(id);

    // 检查编码是否与其他仓位冲突
    if (dto.code && dto.code !== location.code) {
      const existing = await this.prisma.storageLocation.findUnique({
        where: {
          warehouseId_code: {
            warehouseId: location.warehouseId,
            code: dto.code,
          },
        },
      });
      if (existing) {
        throw new ConflictException(`仓位编码 ${dto.code} 在该仓库中已存在`);
      }
    }

    return this.prisma.storageLocation.update({
      where: { id },
      data: dto,
      include: {
        warehouse: {
          select: { id: true, code: true, nameEn: true, nameCn: true },
        },
        _count: {
          select: { parts: true },
        },
      },
    });
  }

  async remove(id: string) {
    await this.findOne(id);

    // 软删除
    return this.prisma.storageLocation.update({
      where: { id },
      data: { deletedAt: new Date() },
    });
  }

  // 获取仓库下的所有仓位（下拉选择用）
  async findByWarehouse(warehouseId: string) {
    return this.prisma.storageLocation.findMany({
      where: {
        warehouseId,
        deletedAt: null,
        status: 'ACTIVE',
      },
      select: {
        id: true,
        code: true,
        nameEn: true,
        nameCn: true,
        zone: true,
      },
      orderBy: [{ sortOrder: 'asc' }, { code: 'asc' }],
    });
  }

  // 获取所有区域（去重）
  async getZones(warehouseId?: string) {
    const where: any = {
      deletedAt: null,
      zone: { not: null },
    };

    if (warehouseId) {
      where.warehouseId = warehouseId;
    }

    const locations = await this.prisma.storageLocation.findMany({
      where,
      select: { zone: true },
      distinct: ['zone'],
    });

    return locations.map((l) => l.zone).filter(Boolean);
  }

  // 批量导入仓位
  async bulkImport(warehouseId: string, locations: CreateStorageLocationDto[]) {
    // 检查仓库是否存在
    const warehouse = await this.prisma.warehouse.findUnique({
      where: { id: warehouseId },
    });

    if (!warehouse || warehouse.deletedAt) {
      throw new NotFoundException('仓库不存在');
    }

    const results = {
      success: 0,
      failed: 0,
      errors: [] as { row: number; code: string; error: string }[],
      created: [] as any[],
    };

    for (let i = 0; i < locations.length; i++) {
      const location = locations[i];
      try {
        // 检查编码是否已存在
        const existing = await this.prisma.storageLocation.findUnique({
          where: {
            warehouseId_code: {
              warehouseId,
              code: location.code,
            },
          },
        });

        if (existing) {
          // 如果已存在且未删除，跳过
          if (!existing.deletedAt) {
            results.failed++;
            results.errors.push({
              row: i + 1,
              code: location.code,
              error: `仓位编码 ${location.code} 已存在`,
            });
            continue;
          }
          // 如果已删除，恢复并更新
          const updated = await this.prisma.storageLocation.update({
            where: { id: existing.id },
            data: {
              ...location,
              warehouseId,
              deletedAt: null,
            },
          });
          results.success++;
          results.created.push(updated);
        } else {
          // 创建新仓位
          const created = await this.prisma.storageLocation.create({
            data: {
              ...location,
              warehouseId,
            },
          });
          results.success++;
          results.created.push(created);
        }
      } catch (error: any) {
        results.failed++;
        results.errors.push({
          row: i + 1,
          code: location.code,
          error: error.message || '创建失败',
        });
      }
    }

    return results;
  }

  // 生成导入模板数据
  getImportTemplate() {
    return [
      {
        code: 'A-01-01',
        nameEn: 'Shelf A-01-01',
        nameCn: '货架 A-01-01',
        zone: 'A',
        aisle: '01',
        rack: '01',
        level: '01',
        position: '01',
        capacity: 100,
        description: 'Sample location',
      },
    ];
  }
}

