/**
 * 表单翻译服务
 * 完全符合 API 文档规范
 */

import {
  Injectable,
  Logger,
  NotFoundException,
  ConflictException,
} from '@nestjs/common';
import { PrismaService } from '@core/database/prisma/prisma.service';
import {
  CreateFormTranslationDto,
  UpdateFormTranslationDto,
  BatchImportTranslationsDto,
} from '../dto';
import { FormIdentifierResolverService } from './form-identifier-resolver.service';

@Injectable()
export class FormTranslationService {
  private readonly logger = new Logger(FormTranslationService.name);

  constructor(
    private readonly prisma: PrismaService,
    private readonly identifierResolver: FormIdentifierResolverService
  ) {}

  // ============================================
  // 1. 创建翻译
  // ============================================

  async create(
    formIdentifier: string,
    version: number,
    dto: CreateFormTranslationDto
  ) {
    this.logger.log(
      `Creating translation for form: ${formIdentifier}, version: ${version}, locale: ${dto.locale}`
    );

    const form = await this.identifierResolver.resolveFormDefinition(
      formIdentifier
    );

    const formVersion = await this.prisma.formVersion.findFirst({
      where: {
        definitionId: form.id,
        version,
      },
    });

    if (!formVersion) {
      throw new NotFoundException(
        `Version ${version} not found for form "${formIdentifier}"`
      );
    }

    // 检查是否已存在该语言的翻译
    const existing = await this.prisma.formTranslation.findUnique({
      where: {
        versionId_locale: {
          versionId: formVersion.id,
          locale: dto.locale,
        },
      },
    });

    if (existing) {
      throw new ConflictException(
        `Translation for locale "${dto.locale}" already exists for this version`
      );
    }

    const translation = await this.prisma.formTranslation.create({
      data: {
        versionId: formVersion.id,
        locale: dto.locale,
        translations: dto.translations,
      },
    });

    this.logger.log(`Translation created: ${translation.id}`);
    return translation;
  }

  // ============================================
  // 2. 获取所有翻译
  // ============================================

  async findAll(formIdentifier: string, version: number) {
    const form = await this.identifierResolver.resolveFormDefinition(
      formIdentifier
    );

    const formVersion = await this.prisma.formVersion.findFirst({
      where: {
        definitionId: form.id,
        version,
      },
    });

    if (!formVersion) {
      throw new NotFoundException(
        `Version ${version} not found for form "${formIdentifier}"`
      );
    }

    const translations = await this.prisma.formTranslation.findMany({
      where: {
        versionId: formVersion.id,
      },
      orderBy: {
        locale: 'asc',
      },
    });

    return translations;
  }

  // ============================================
  // 3. 获取指定语言的翻译
  // ============================================

  async findOne(formIdentifier: string, version: number, locale: string) {
    const form = await this.identifierResolver.resolveFormDefinition(
      formIdentifier
    );

    const formVersion = await this.prisma.formVersion.findFirst({
      where: {
        definitionId: form.id,
        version,
      },
    });

    if (!formVersion) {
      throw new NotFoundException(
        `Version ${version} not found for form "${formIdentifier}"`
      );
    }

    const translation = await this.prisma.formTranslation.findUnique({
      where: {
        versionId_locale: {
          versionId: formVersion.id,
          locale,
        },
      },
    });

    if (!translation) {
      throw new NotFoundException(
        `Translation for locale "${locale}" not found`
      );
    }

    return translation;
  }

  // ============================================
  // 4. 更新翻译
  // ============================================

  async update(
    formIdentifier: string,
    version: number,
    locale: string,
    dto: UpdateFormTranslationDto
  ) {
    this.logger.log(
      `Updating translation for form: ${formIdentifier}, version: ${version}, locale: ${locale}`
    );

    const form = await this.identifierResolver.resolveFormDefinition(
      formIdentifier
    );

    const formVersion = await this.prisma.formVersion.findFirst({
      where: {
        definitionId: form.id,
        version,
      },
    });

    if (!formVersion) {
      throw new NotFoundException(
        `Version ${version} not found for form "${formIdentifier}"`
      );
    }

    const translation = await this.prisma.formTranslation.findUnique({
      where: {
        versionId_locale: {
          versionId: formVersion.id,
          locale,
        },
      },
    });

    if (!translation) {
      throw new NotFoundException(
        `Translation for locale "${locale}" not found`
      );
    }

    const updated = await this.prisma.formTranslation.update({
      where: { id: translation.id },
      data: {
        translations: dto.translations,
      },
    });

    this.logger.log(`Translation updated: ${updated.id}`);
    return updated;
  }

  // ============================================
  // 5. 删除翻译
  // ============================================

  async remove(formIdentifier: string, version: number, locale: string) {
    this.logger.log(
      `Deleting translation for form: ${formIdentifier}, version: ${version}, locale: ${locale}`
    );

    const form = await this.identifierResolver.resolveFormDefinition(
      formIdentifier
    );

    const formVersion = await this.prisma.formVersion.findFirst({
      where: {
        definitionId: form.id,
        version,
      },
    });

    if (!formVersion) {
      throw new NotFoundException(
        `Version ${version} not found for form "${formIdentifier}"`
      );
    }

    const translation = await this.prisma.formTranslation.findUnique({
      where: {
        versionId_locale: {
          versionId: formVersion.id,
          locale,
        },
      },
    });

    if (!translation) {
      throw new NotFoundException(
        `Translation for locale "${locale}" not found`
      );
    }

    await this.prisma.formTranslation.delete({
      where: { id: translation.id },
    });

    this.logger.log(`Translation deleted: ${translation.id}`);
    return {
      id: translation.id,
      locale: translation.locale,
      deleted: true,
    };
  }

  // ============================================
  // 6. 创建或更新翻译 (PUT 语义)
  // ============================================

  async upsert(
    formIdentifier: string,
    version: number,
    locale: string,
    dto: UpdateFormTranslationDto
  ) {
    this.logger.log(
      `Upserting translation for form: ${formIdentifier}, version: ${version}, locale: ${locale}`
    );

    const form = await this.identifierResolver.resolveFormDefinition(
      formIdentifier
    );

    const formVersion = await this.prisma.formVersion.findFirst({
      where: {
        definitionId: form.id,
        version,
      },
    });

    if (!formVersion) {
      throw new NotFoundException(
        `Version ${version} not found for form "${formIdentifier}"`
      );
    }

    const translation = await this.prisma.formTranslation.upsert({
      where: {
        versionId_locale: {
          versionId: formVersion.id,
          locale,
        },
      },
      update: {
        translations: dto.translations,
      },
      create: {
        versionId: formVersion.id,
        locale,
        translations: dto.translations,
      },
    });

    this.logger.log(`Translation upserted: ${translation.id}`);
    return translation;
  }

  // ============================================
  // 7. 检查翻译完整性
  // ============================================

  async checkCompleteness(
    formIdentifier: string,
    version: number,
    locale: string
  ) {
    this.logger.log(
      `Checking translation completeness for form: ${formIdentifier}, version: ${version}, locale: ${locale}`
    );

    const form = await this.identifierResolver.resolveFormDefinition(
      formIdentifier
    );

    const formVersion = await this.prisma.formVersion.findFirst({
      where: {
        definitionId: form.id,
        version,
      },
    });

    if (!formVersion) {
      throw new NotFoundException(
        `Version ${version} not found for form "${formIdentifier}"`
      );
    }

    const translation = await this.prisma.formTranslation.findUnique({
      where: {
        versionId_locale: {
          versionId: formVersion.id,
          locale,
        },
      },
    });

    if (!translation) {
      throw new NotFoundException(
        `Translation for locale "${locale}" not found`
      );
    }

    // 从 schema 中提取需要翻译的 keys
    const schema = formVersion.schema as any;
    const requiredKeys: string[] = [];

    // 提取字段标签
    if (schema.properties) {
      for (const [fieldName, fieldDef] of Object.entries(schema.properties)) {
        requiredKeys.push(`fields.${fieldName}.label`);
        if ((fieldDef as any).description) {
          requiredKeys.push(`fields.${fieldName}.description`);
        }
        // 如果有 enum，提取选项
        if ((fieldDef as any).enum) {
          for (const option of (fieldDef as any).enum) {
            requiredKeys.push(`fields.${fieldName}.options.${option}`);
          }
        }
      }
    }

    // 计算覆盖率
    const translations = translation.translations as Record<string, string>;
    const translatedKeys = Object.keys(translations);
    const missingKeys = requiredKeys.filter(key => !translatedKeys.includes(key));
    const coverage = requiredKeys.length > 0
      ? Math.round((translatedKeys.length / requiredKeys.length) * 100) / 100
      : 1;

    return {
      locale,
      isComplete: missingKeys.length === 0,
      coverage,
      totalRequired: requiredKeys.length,
      translated: translatedKeys.length,
      missingKeys,
    };
  }

  // ============================================
  // 8. 批量导入翻译
  // ============================================

  async batchImport(
    formIdentifier: string,
    version: number,
    dto: BatchImportTranslationsDto
  ) {
    this.logger.log(
      `Batch importing translations for form: ${formIdentifier}, version: ${version}`
    );

    const form = await this.identifierResolver.resolveFormDefinition(
      formIdentifier
    );

    const formVersion = await this.prisma.formVersion.findFirst({
      where: {
        definitionId: form.id,
        version,
      },
    });

    if (!formVersion) {
      throw new NotFoundException(
        `Version ${version} not found for form "${formIdentifier}"`
      );
    }

    const results = {
      imported: 0,
      created: 0,
      updated: 0,
      failed: 0,
      errors: [] as Array<{ locale: string; error: string }>,
    };

    for (const [locale, translations] of Object.entries(dto.translations)) {
      try {
        const existing = await this.prisma.formTranslation.findUnique({
          where: {
            versionId_locale: {
              versionId: formVersion.id,
              locale,
            },
          },
        });

        if (existing) {
          if (dto.overwrite !== false) {
            await this.prisma.formTranslation.update({
              where: { id: existing.id },
              data: { translations },
            });
            results.updated++;
            results.imported++;
          } else {
            results.failed++;
            results.errors.push({
              locale,
              error: 'Translation already exists and overwrite is false',
            });
          }
        } else {
          await this.prisma.formTranslation.create({
            data: {
              versionId: formVersion.id,
              locale,
              translations,
            },
          });
          results.created++;
          results.imported++;
        }
      } catch (error) {
        results.failed++;
        results.errors.push({
          locale,
          error: error.message,
        });
      }
    }

    this.logger.log(
      `Batch import completed: ${results.created} created, ${results.updated} updated, ${results.failed} failed`
    );
    return results;
  }
}

