/**
 * 表单标识符解析服务
 * 支持通过 id / key / slug / alias 查找表单
 */

import { Injectable, NotFoundException } from '@nestjs/common';
import { PrismaService } from '@core/database/prisma/prisma.service';
import { Prisma } from '@prisma/client';

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

  /**
   * 解析表单标识符，返回表单定义
   * 支持的标识符类型：id / key / slug / alias
   * 查找优先级：id > key > slug > alias
   * 
   * @param identifier - 表单标识符
   * @param options - Prisma 查询选项（include, select 等）
   */
  async resolveFormDefinition<T extends Prisma.FormDefinitionFindUniqueArgs>(
    identifier: string,
    options?: Omit<T, 'where'>
  ) {
    // 1. 尝试作为 UUID (id)
    if (this.isUUID(identifier)) {
      const form = await this.prisma.formDefinition.findUnique({
        where: { id: identifier },
        ...options,
      } as any);
      if (form) return form;
    }

    // 2. 尝试作为 key
    const formByKey = await this.prisma.formDefinition.findUnique({
      where: { key: identifier },
      ...options,
    } as any);
    if (formByKey) return formByKey;

    // 3. 尝试作为 slug
    const formBySlug = await this.prisma.formDefinition.findUnique({
      where: { slug: identifier },
      ...options,
    } as any);
    if (formBySlug) return formBySlug;

    // 4. 尝试作为 alias（在 aliases JSON 数组中查找）
    // 注意：path: ['$'] 是 MongoDB jsonpath，PG 下查不到任何记录；用 array_contains 直接对应 PG `@>`
    const formByAlias = await this.prisma.formDefinition.findFirst({
      where: {
        aliases: { array_contains: identifier },
      },
      ...options,
    } as any);
    if (formByAlias) return formByAlias;

    // 5. 尝试在 slugHistory 中查找（历史 slug）
    const formBySlugHistory = await this.prisma.formDefinition.findFirst({
      where: {
        slugHistory: { array_contains: identifier },
      },
      ...options,
    } as any);
    if (formBySlugHistory) return formBySlugHistory;

    throw new NotFoundException(
      `Form with identifier "${identifier}" not found`
    );
  }

  /**
   * 解析表单标识符，返回表单定义（带查询选项）
   * @deprecated 使用 resolveFormDefinition 代替
   */
  async resolveFormDefinitionWithOptions<T extends Prisma.FormDefinitionInclude>(
    identifier: string,
    include?: T
  ) {
    return this.resolveFormDefinition(identifier, { include } as any);
  }

  /**
   * 解析表单实例标识符，返回表单实例
   * 支持的标识符类型：id
   */
  async resolveFormInstance(identifier: string, includeDeleted = false) {
    // 首先尝试 UUID
    if (this.isUUID(identifier)) {
      const instance = await this.prisma.formInstance.findUnique({
        where: { id: identifier },
      });

      if (!instance || (!includeDeleted && instance.deletedAt)) {
        throw new NotFoundException(
          `Form instance with id "${identifier}" not found`
        );
      }

      return instance;
    }

    // 然后尝试 businessKey
    const instance = await this.prisma.formInstance.findUnique({
      where: { businessKey: identifier },
    });

    if (!instance || (!includeDeleted && instance.deletedAt)) {
      throw new NotFoundException(
        `Form instance with identifier "${identifier}" not found`
      );
    }

    return instance;
  }

  /**
   * 解析表单模板标识符，返回表单模板
   * 支持的标识符类型：id
   */
  async resolveFormTemplate(identifier: string) {
    if (!this.isUUID(identifier)) {
      throw new NotFoundException(
        `Invalid form template identifier "${identifier}". Must be a valid UUID.`
      );
    }

    const template = await this.prisma.formTemplate.findUnique({
      where: { id: identifier },
    });

    if (!template) {
      throw new NotFoundException(
        `Form template with id "${identifier}" not found`
      );
    }

    return template;
  }

  /**
   * 检查是否为有效的 UUID
   */
  private isUUID(str: string): boolean {
    const uuidRegex =
      /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
    return uuidRegex.test(str);
  }
}

