import { Injectable } from '@nestjs/common';
import { PrismaService } from '../prisma/prisma.service';
import { IContractTemplateRepository } from '../../../domain/repositories/contract-template.repository.interface';
import { ContractTemplate } from '../../../domain/aggregates/contract-template.aggregate';

@Injectable()
export class ContractTemplateRepositoryImpl implements IContractTemplateRepository {
  constructor(private readonly prisma: PrismaService) {}

  async save(template: ContractTemplate): Promise<ContractTemplate> {
    if (template.id) {
      // 更新
      const updated = await this.prisma.contractTemplate.update({
        where: { id: template.id },
        data: {
          version: template.version,
          title: template.title,
          content: template.content,
          effectiveFrom: template.effectiveFrom,
          effectiveTo: template.effectiveTo,
          isActive: template.isActive,
        },
      });
      return this.mapToDomain(updated);
    } else {
      // 创建
      const created = await this.prisma.contractTemplate.create({
        data: {
          version: template.version,
          title: template.title,
          content: template.content,
          effectiveFrom: template.effectiveFrom,
          effectiveTo: template.effectiveTo,
          isActive: template.isActive,
        },
      });
      return this.mapToDomain(created);
    }
  }

  async findById(id: number): Promise<ContractTemplate | null> {
    const template = await this.prisma.contractTemplate.findUnique({
      where: { id },
    });
    return template ? this.mapToDomain(template) : null;
  }

  async findByVersion(version: string): Promise<ContractTemplate | null> {
    const template = await this.prisma.contractTemplate.findUnique({
      where: { version },
    });
    return template ? this.mapToDomain(template) : null;
  }

  async findActiveTemplate(): Promise<ContractTemplate | null> {
    const now = new Date();
    const template = await this.prisma.contractTemplate.findFirst({
      where: {
        isActive: true,
        effectiveFrom: { lte: now },
        OR: [
          { effectiveTo: null },
          { effectiveTo: { gte: now } },
        ],
      },
      orderBy: { effectiveFrom: 'desc' },
    });
    return template ? this.mapToDomain(template) : null;
  }

  async findAll(): Promise<ContractTemplate[]> {
    const templates = await this.prisma.contractTemplate.findMany({
      orderBy: { createdAt: 'desc' },
    });
    return templates.map((t) => this.mapToDomain(t));
  }

  private mapToDomain(data: {
    id: number;
    version: string;
    title: string;
    content: string;
    effectiveFrom: Date;
    effectiveTo: Date | null;
    isActive: boolean;
    createdAt: Date;
    updatedAt: Date;
  }): ContractTemplate {
    return ContractTemplate.reconstitute({
      id: data.id,
      version: data.version,
      title: data.title,
      content: data.content,
      effectiveFrom: data.effectiveFrom,
      effectiveTo: data.effectiveTo ?? undefined,
      isActive: data.isActive,
      createdAt: data.createdAt,
      updatedAt: data.updatedAt,
    });
  }
}
