import { Injectable } from '@nestjs/common';
import { PrismaService } from '../prisma/prisma.service';
import { IPlantingPositionRepository } from '../../../domain/repositories/planting-position.repository.interface';
import { PlantingPosition } from '../../../domain/aggregates/planting-position.aggregate';
import { PlantingPositionMapper } from '../mappers/planting-position.mapper';

@Injectable()
export class PlantingPositionRepositoryImpl
  implements IPlantingPositionRepository
{
  constructor(private readonly prisma: PrismaService) {}

  async save(position: PlantingPosition): Promise<void> {
    const { positionData, distributions } =
      PlantingPositionMapper.toPersistence(position);

    if (position.id) {
      // 更新持仓
      await this.prisma.plantingPosition.update({
        where: { id: position.id },
        data: {
          totalTreeCount: positionData.totalTreeCount,
          effectiveTreeCount: positionData.effectiveTreeCount,
          pendingTreeCount: positionData.pendingTreeCount,
          firstMiningStartAt: positionData.firstMiningStartAt,
        },
      });

      // 更新分布
      for (const dist of distributions) {
        await this.prisma.positionDistribution.upsert({
          where: {
            userId_provinceCode_cityCode: {
              userId: dist.userId,
              provinceCode: dist.provinceCode ?? '',
              cityCode: dist.cityCode ?? '',
            },
          },
          update: {
            treeCount: dist.treeCount,
          },
          create: {
            userId: dist.userId,
            provinceCode: dist.provinceCode,
            cityCode: dist.cityCode,
            treeCount: dist.treeCount,
          },
        });
      }
    } else {
      // 创建
      const created = await this.prisma.plantingPosition.create({
        data: {
          userId: positionData.userId,
          totalTreeCount: positionData.totalTreeCount,
          effectiveTreeCount: positionData.effectiveTreeCount,
          pendingTreeCount: positionData.pendingTreeCount,
          firstMiningStartAt: positionData.firstMiningStartAt,
        },
      });

      position.setId(created.id);

      // 创建分布
      if (distributions.length > 0) {
        await this.prisma.positionDistribution.createMany({
          data: distributions,
        });
      }
    }
  }

  async findById(positionId: bigint): Promise<PlantingPosition | null> {
    const position = await this.prisma.plantingPosition.findUnique({
      where: { id: positionId },
      include: { distributions: true },
    });

    return position ? PlantingPositionMapper.toDomain(position) : null;
  }

  async findByUserId(userId: bigint): Promise<PlantingPosition | null> {
    const position = await this.prisma.plantingPosition.findUnique({
      where: { userId },
      include: { distributions: true },
    });

    return position ? PlantingPositionMapper.toDomain(position) : null;
  }

  async getOrCreate(userId: bigint): Promise<PlantingPosition> {
    let position = await this.findByUserId(userId);

    if (!position) {
      position = PlantingPosition.create(userId);
      await this.save(position);
    }

    return position;
  }
}
