/**
 * 快照服务
 * 
 * 管理发布快照的生命周期
 * 
 * 快照（ReleaseSnapshot）绑定表单版本和流程版本，确保发布后版本不可变。
 * 简化流程：审核通过 = 发布（自动设为默认版本）
 */

import { Injectable, Logger } from '@nestjs/common';
import { PrismaService } from '@core/database/prisma/prisma.service';
import {
  SubmitReviewDto,
  ReviewSnapshotDto,
  ReviewAction,
  PublishSnapshotDto,
  SubmitReviewResponse,
  ReviewResponse,
  PublishResponse,
  SnapshotDetail,
  SnapshotListItem,
  PendingReviewItem,
  SnapshotStatus,
} from '../dto/snapshot.dto';
import {
  FormNotFoundException,
  SnapshotNotFoundException,
  NoActiveSnapshotException,
  DraftAlreadyExistsException,
  PendingAlreadyExistsException,
  InvalidStatusTransitionException,
  ReviewRequiredException,
  FormDefinitionArchivedException,
  AlreadyPublishedException,
} from '../exceptions';
import { RegionId } from '../decorators/region.decorator';
import { safeFindUnique } from '../utils/prisma-error-handler';
import * as crypto from 'crypto';

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

  constructor(private readonly prisma: PrismaService) {}

  // ============================================
  // 1. 提交审核 - 创建真正的 ReleaseSnapshot
  // ============================================

  async submitReview(
    formId: string,
    dto: SubmitReviewDto,
    regionId: RegionId,
    userId: string,
  ): Promise<SubmitReviewResponse> {
    this.logger.log(`Submitting review for form ${formId} in region ${regionId}`);

    // 获取表单定义
    const form = await safeFindUnique(() =>
      this.prisma.formDefinition.findUnique({
        where: { id: formId },
        include: {
          versions: {
            where: { status: 'DRAFT' },
            orderBy: { version: 'desc' },
            take: 1,
          },
        },
      }),
    );

    if (!form) {
      throw new FormNotFoundException(formId, regionId);
    }

    // 验证区域访问
    this.validateRegionAccess(form, regionId);

    // 检查是否已有 PENDING 状态的快照
    const existingPending = await this.prisma.releaseSnapshot.findFirst({
      where: {
        formDefinitionId: formId,
        status: 'PENDING',
      },
    });
    if (existingPending) {
      throw new PendingAlreadyExistsException(formId);
    }

    // 检查是否有草稿版本
    if (!form.versions || form.versions.length === 0) {
      throw new DraftAlreadyExistsException(formId);
    }

    const formVersion = form.versions[0];

    // 获取流程定义和版本
    let processDefinitionId: string | null = null;
    let processVersionId: string | null = null;
    
    if (form.approvalProcessKey) {
      const processDef = await this.prisma.approvalDefinition.findUnique({
        where: { key: form.approvalProcessKey },
        include: {
          versions: {
            where: { status: 'DRAFT' },
            orderBy: { version: 'desc' },
            take: 1,
          },
        },
      });
      if (processDef) {
        processDefinitionId = processDef.id;
        if (processDef.versions.length > 0) {
          processVersionId = processDef.versions[0].id;
        }
      }
    }

    // 在事务中创建快照并更新版本状态
    const snapshot = await this.prisma.$transaction(async (tx) => {
      // 1. 创建 ReleaseSnapshot 记录
      const newSnapshot = await tx.releaseSnapshot.create({
        data: {
          formDefinitionId: formId,
          formVersionId: formVersion.id,
          processDefinitionId,
          processVersionId,
          status: 'PENDING',
          versionName: `v${formVersion.version}`,
          submittedBy: userId,
          submittedAt: new Date(),
          submitComment: dto.comment,
        },
      });

      // 2. 更新表单版本状态
      await tx.formVersion.update({
        where: { id: formVersion.id },
        data: { status: 'PENDING_REVIEW' },
      });

      // 3. 更新流程版本状态（如果有）
      if (processVersionId) {
        await tx.approvalVersion.update({
          where: { id: processVersionId },
          data: { status: 'DRAFT' },
        });
      }

      return newSnapshot;
    });

    this.logger.log(`Review submitted: snapshot ${snapshot.id}`);

    return {
      snapshotId: snapshot.id,
      formVersionId: formVersion.id,
      processVersionId: processVersionId || '',
      status: SnapshotStatus.PENDING,
      submittedAt: snapshot.submittedAt?.toISOString() || new Date().toISOString(),
    };
  }

  // ============================================
  // 2. 获取待审核列表 - 从 ReleaseSnapshot 表查询
  // ============================================

  async getPendingReviews(regionId: RegionId): Promise<{ items: PendingReviewItem[]; total: number; page: number; limit: number; totalPages: number; hasNext: boolean; hasPrev: boolean }> {
    this.logger.log(`[getPendingReviews] 查询待审核快照`);
    
    // 从 ReleaseSnapshot 表查询待审核快照（不再按区域过滤，快照是全局的）
    const pendingSnapshots = await this.prisma.releaseSnapshot.findMany({
      where: {
        status: 'PENDING',
      },
      orderBy: { submittedAt: 'desc' },
    });

    // 获取关联的表单版本和定义信息
    const items: PendingReviewItem[] = [];
    
    for (const snapshot of pendingSnapshots) {
      const formVersion = await this.prisma.formVersion.findUnique({
        where: { id: snapshot.formVersionId },
        include: {
          definition: true,
          creator: {
            select: { id: true, username: true, displayName: true },
          },
        },
      });

      if (formVersion) {
        items.push({
          snapshotId: snapshot.id,
          formDefinitionId: snapshot.formDefinitionId,
          formDefinitionName: formVersion.definition.name,
          formVersionId: formVersion.id,
          formVersion: formVersion.version,
          submittedAt: snapshot.submittedAt?.toISOString() || snapshot.createdAt.toISOString(),
          submittedBy: formVersion.creator?.displayName || formVersion.createdBy,
          submittedById: snapshot.submittedBy || formVersion.createdBy,
          comment: snapshot.submitComment || undefined,
        });
      }
    }

    this.logger.log(`[getPendingReviews] 查询到 ${items.length} 条待审核快照`);

    const total = items.length;
    return {
      items,
      total,
      page: 1,
      limit: total || 20,
      totalPages: 1,
      hasNext: false,
      hasPrev: false,
    };
  }

  // ============================================
  // 3. 审核 - 从 ReleaseSnapshot 表操作
  // ============================================

  async review(
    snapshotId: string,
    dto: ReviewSnapshotDto,
    regionId: RegionId,
    userId: string,
  ): Promise<ReviewResponse> {
    this.logger.log(`Reviewing snapshot ${snapshotId}: ${dto.action}`);

    // 从 ReleaseSnapshot 表查询快照
    const snapshot = await this.prisma.releaseSnapshot.findUnique({
      where: { id: snapshotId },
    });

    if (!snapshot) {
      throw new SnapshotNotFoundException(snapshotId, regionId);
    }

    if (snapshot.status !== 'PENDING') {
      throw new InvalidStatusTransitionException(
        snapshot.status,
        dto.action === ReviewAction.APPROVE ? 'APPROVED' : 'REJECTED',
        '只能审核待审核状态的快照',
      );
    }

    // 获取关联的表单版本
    const formVersion = await this.prisma.formVersion.findUnique({
      where: { id: snapshot.formVersionId },
      include: { definition: true },
    });

    if (!formVersion) {
      throw new SnapshotNotFoundException(snapshotId, regionId);
    }

    const now = new Date();

    if (dto.action === ReviewAction.APPROVE) {
      // 审核通过 = 发布（简化流程）
      await this.prisma.$transaction(async (tx) => {
        // 1. 将当前区域其他 ACTIVE 快照设为 ARCHIVED
        await tx.releaseSnapshot.updateMany({
          where: {
            formDefinitionId: snapshot.formDefinitionId,
            status: 'ACTIVE',
          },
          data: {
            status: 'ARCHIVED',
          },
        });

        // 2. 更新快照为 ACTIVE（已发布）
        await tx.releaseSnapshot.update({
          where: { id: snapshotId },
          data: {
            status: 'ACTIVE',
            reviewedBy: userId,
            reviewedAt: now,
            reviewComment: dto.comment,
            publishedBy: userId,
            publishedAt: now,
          },
        });

        // 3. 取消其他版本的默认状态，并标记为 DEPRECATED
        await tx.formVersion.updateMany({
          where: {
            definitionId: formVersion.definitionId,
            isDefault: true,
            id: { not: formVersion.id },
          },
          data: {
            isDefault: false,
            status: 'DEPRECATED',
          },
        });

        // 4. 设置当前版本为 PUBLISHED 和默认版本
        await tx.formVersion.update({
          where: { id: formVersion.id },
          data: {
            status: 'PUBLISHED',
            isDefault: true,
            reviewedBy: userId,
            reviewedAt: now,
            reviewComment: dto.comment,
            publishedAt: now,
          },
        });

        // 5. 如果是首次发布，更新表单定义状态为 PUBLISHED
        if (formVersion.definition.status === 'DRAFT') {
          await tx.formDefinition.update({
            where: { id: formVersion.definitionId },
            data: { status: 'PUBLISHED' },
          });
        }
      });

      this.logger.log(`Snapshot ${snapshotId} approved and published`);

      return {
        snapshotId,
        status: 'PUBLISHED',
        isDefault: true,
        reviewedAt: now.toISOString(),
        reviewedBy: userId,
        reviewComment: dto.comment,
        publishedAt: now.toISOString(),
      };
    } else {
      // 审核驳回
      await this.prisma.$transaction(async (tx) => {
        // 1. 更新快照状态为 REJECTED
        await tx.releaseSnapshot.update({
          where: { id: snapshotId },
          data: {
            status: 'REJECTED',
            reviewedBy: userId,
            reviewedAt: now,
            reviewComment: dto.comment,
          },
        });

        // 2. 更新表单版本状态为 REJECTED
        await tx.formVersion.update({
          where: { id: formVersion.id },
          data: {
            status: 'REJECTED',
            reviewedBy: userId,
            reviewedAt: now,
            reviewComment: dto.comment,
          },
        });
      });

      this.logger.log(`Snapshot ${snapshotId} rejected`);

      return {
        snapshotId,
        status: 'REJECTED',
        reviewedAt: now.toISOString(),
        reviewedBy: userId,
        reviewComment: dto.comment,
      };
    }
  }

  // ============================================
  // 4. 发布（手动激活历史版本）- 在简化流程下主要用于回滚
  // ============================================

  async publish(
    snapshotId: string,
    dto: PublishSnapshotDto,
    regionId: RegionId,
    userId: string,
  ): Promise<PublishResponse> {
    this.logger.log(`Publishing snapshot ${snapshotId}`);

    // 从 ReleaseSnapshot 表查询快照
    const snapshot = await this.prisma.releaseSnapshot.findUnique({
      where: { id: snapshotId },
    });

    if (!snapshot) {
      throw new SnapshotNotFoundException(snapshotId, regionId);
    }

    // 获取关联的表单版本
    const formVersion = await this.prisma.formVersion.findUnique({
      where: { id: snapshot.formVersionId },
      include: { definition: true },
    });

    if (!formVersion) {
      throw new SnapshotNotFoundException(snapshotId, regionId);
    }

    // 检查表单定义状态
    if (formVersion.definition.status === 'ARCHIVED') {
      throw new FormDefinitionArchivedException(formVersion.definitionId);
    }

    // 检查快照状态（必须是 ACTIVE 或 ARCHIVED 才能重新激活）
    if (snapshot.status !== 'ACTIVE' && snapshot.status !== 'ARCHIVED') {
      throw new ReviewRequiredException(snapshotId);
    }

    // 如果已经是 ACTIVE 快照，返回冲突错误
    if (snapshot.status === 'ACTIVE') {
      throw new AlreadyPublishedException(snapshotId);
    }

    // 获取当前 ACTIVE 快照（用于返回 previousSnapshotId）
    const currentActiveSnapshot = await this.prisma.releaseSnapshot.findFirst({
      where: {
        formDefinitionId: snapshot.formDefinitionId,
        status: 'ACTIVE',
      },
    });

    // 事务：切换 ACTIVE 快照
    await this.prisma.$transaction(async (tx) => {
      // 1. 将当前 ACTIVE 快照设为 ARCHIVED
      if (currentActiveSnapshot) {
        await tx.releaseSnapshot.update({
          where: { id: currentActiveSnapshot.id },
          data: { status: 'ARCHIVED' },
        });
      }

      // 2. 将目标快照设为 ACTIVE
      await tx.releaseSnapshot.update({
        where: { id: snapshotId },
        data: {
          status: 'ACTIVE',
          publishedBy: userId,
          publishedAt: new Date(),
          releaseNote: dto.releaseNote,
        },
      });

      // 3. 取消其他版本的默认状态
      await tx.formVersion.updateMany({
        where: {
          definitionId: formVersion.definitionId,
          isDefault: true,
        },
        data: { isDefault: false },
      });

      // 4. 设置快照对应的版本为默认
      await tx.formVersion.update({
        where: { id: formVersion.id },
        data: {
          isDefault: true,
          publishedAt: new Date(),
          changelog: dto.releaseNote,
        },
      });
    });

    return {
      snapshotId,
      status: 'ACTIVE',
      releaseNote: dto.releaseNote,
      publishedAt: new Date().toISOString(),
      publishedBy: userId,
      previousSnapshotId: currentActiveSnapshot?.id,
      formDefinitionStatus: 'ACTIVE',
    };
  }

  // ============================================
  // 5. 回滚到指定快照
  // ============================================

  async rollback(
    snapshotId: string,
    regionId: RegionId,
    userId: string,
  ): Promise<PublishResponse> {
    this.logger.log(`Rolling back to snapshot ${snapshotId}`);

    // 从 ReleaseSnapshot 表查询快照
    const snapshot = await this.prisma.releaseSnapshot.findUnique({
      where: { id: snapshotId },
    });

    if (!snapshot) {
      throw new SnapshotNotFoundException(snapshotId, regionId);
    }

    // 获取关联的表单版本
    const formVersion = await this.prisma.formVersion.findUnique({
      where: { id: snapshot.formVersionId },
      include: { definition: true },
    });

    if (!formVersion) {
      throw new SnapshotNotFoundException(snapshotId, regionId);
    }

    // 检查表单定义状态
    if (formVersion.definition.status === 'ARCHIVED') {
      throw new FormDefinitionArchivedException(formVersion.definitionId);
    }

    // 检查快照状态（必须是 ARCHIVED 或 ACTIVE 的快照才能回滚）
    if (snapshot.status !== 'ARCHIVED' && snapshot.status !== 'ACTIVE') {
      throw new InvalidStatusTransitionException(
        snapshot.status,
        'ARCHIVED',
        '只能回滚到已发布过的快照',
      );
    }

    // 如果快照已经是 ACTIVE，不需要回滚
    if (snapshot.status === 'ACTIVE') {
      return {
        snapshotId,
        status: 'ACTIVE',
        releaseNote: '当前快照已是激活版本',
        publishedAt: snapshot.publishedAt?.toISOString() || new Date().toISOString(),
        publishedBy: userId,
        previousSnapshotId: undefined,
        formDefinitionStatus: 'ACTIVE',
      };
    }

    // 获取当前 ACTIVE 快照
    const currentActiveSnapshot = await this.prisma.releaseSnapshot.findFirst({
      where: {
        formDefinitionId: snapshot.formDefinitionId,
        status: 'ACTIVE',
      },
    });

    // 事务：回滚到指定快照
    await this.prisma.$transaction(async (tx) => {
      // 1. 将当前 ACTIVE 快照设为 ARCHIVED
      if (currentActiveSnapshot) {
        await tx.releaseSnapshot.update({
          where: { id: currentActiveSnapshot.id },
          data: { status: 'ARCHIVED' },
        });
      }

      // 2. 将目标快照设为 ACTIVE
      await tx.releaseSnapshot.update({
        where: { id: snapshotId },
        data: {
          status: 'ACTIVE',
          publishedBy: userId,
          publishedAt: new Date(),
        },
      });

      // 3. 取消其他版本的默认状态
      await tx.formVersion.updateMany({
        where: {
          definitionId: formVersion.definitionId,
          isDefault: true,
        },
        data: { isDefault: false },
      });

      // 4. 设置快照对应的版本为默认
      await tx.formVersion.update({
        where: { id: formVersion.id },
        data: {
          isDefault: true,
          changelog: formVersion.changelog || `回滚到版本 ${formVersion.version}`,
        },
      });
    });

    this.logger.log(`Rolled back to snapshot ${snapshotId}, previous: ${currentActiveSnapshot?.id}`);

    return {
      snapshotId,
      status: 'ACTIVE',
      releaseNote: `回滚到版本 ${formVersion.version}`,
      publishedAt: new Date().toISOString(),
      publishedBy: userId,
      previousSnapshotId: currentActiveSnapshot?.id,
      formDefinitionStatus: 'ACTIVE',
    };
  }

  // ============================================
  // 6. 获取激活快照 - 从 ReleaseSnapshot 表查询
  // ============================================

  async getActiveSnapshot(
    formId: string,
    regionId: RegionId,
  ): Promise<SnapshotDetail> {
    // 从 ReleaseSnapshot 表查询 ACTIVE 快照
    const activeSnapshot = await this.prisma.releaseSnapshot.findFirst({
      where: {
        formDefinitionId: formId,
        status: 'ACTIVE',
      },
    });

    if (!activeSnapshot) {
      throw new NoActiveSnapshotException(formId, regionId);
    }

    // 获取关联的表单版本
    const formVersion = await this.prisma.formVersion.findUnique({
      where: { id: activeSnapshot.formVersionId },
      include: { definition: true },
    });

    if (!formVersion) {
      throw new NoActiveSnapshotException(formId, regionId);
    }

    // 获取流程版本
    let processVersion = null;
    if (activeSnapshot.processVersionId) {
      processVersion = await this.prisma.approvalVersion.findUnique({
        where: { id: activeSnapshot.processVersionId },
      });
    }

    return {
      snapshotId: activeSnapshot.id,
      regionId,
      formDefinitionId: formId,
      formVersion: {
        id: formVersion.id,
        version: formVersion.version,
        versionName: activeSnapshot.versionName || undefined,
        schema: formVersion.schema,
        uiSchema: formVersion.uiSchema,
      },
      processVersion: processVersion
        ? {
            id: processVersion.id,
            version: processVersion.version,
            versionName: processVersion.name,
            model: processVersion.processModel,
          }
        : {
            id: '',
            version: 1,
            model: { nodes: [], edges: [] },
          },
      status: 'ACTIVE',
      releaseNote: activeSnapshot.releaseNote || undefined,
      publishedAt: activeSnapshot.publishedAt?.toISOString(),
      createdAt: activeSnapshot.createdAt.toISOString(),
    };
  }

  // ============================================
  // 7. 获取快照历史 - 从 ReleaseSnapshot 表查询
  // ============================================

  async getSnapshotHistory(
    formId: string,
    regionId: RegionId,
  ): Promise<{ items: SnapshotListItem[]; total: number; page: number; limit: number; totalPages: number; hasNext: boolean; hasPrev: boolean }> {
    const form = await safeFindUnique(() =>
      this.prisma.formDefinition.findUnique({
        where: { id: formId },
        include: {
          organization: {
            include: {
              organizationRegions: {
                include: { region: true }, // ✅ v2.0: 修复为 organizationRegions
              },
            },
          },
        },
      }),
    );

    if (!form) {
      throw new FormNotFoundException(formId, regionId);
    }

    this.validateRegionAccess(form, regionId);

    // 从 ReleaseSnapshot 表查询快照历史
    const snapshots = await this.prisma.releaseSnapshot.findMany({
      where: {
        formDefinitionId: formId,
        status: { in: ['ACTIVE', 'ARCHIVED'] },
      },
      orderBy: { createdAt: 'desc' },
    });

    const items: SnapshotListItem[] = [];
    
    for (const snapshot of snapshots) {
      items.push({
        snapshotId: snapshot.id,
        formVersionId: snapshot.formVersionId,
        formVersion: parseInt(snapshot.versionName?.replace('v', '') || '1'),
        processVersionId: snapshot.processVersionId || '',
        processVersion: parseInt(snapshot.versionName?.replace('v', '') || '1'),
        status: snapshot.status === 'ACTIVE' ? 'ACTIVE' : 'ARCHIVED',
        releaseNote: snapshot.releaseNote || undefined,
        publishedAt: snapshot.publishedAt?.toISOString(),
        createdAt: snapshot.createdAt.toISOString(),
      });
    }

    const total = items.length;
    return {
      items,
      total,
      page: 1,
      limit: total || 20,
      totalPages: 1,
      hasNext: false,
      hasPrev: false,
    };
  }

  // ============================================
  // 8. 获取快照详情 - 从 ReleaseSnapshot 表查询
  // ============================================

  async getSnapshotDetail(
    snapshotId: string,
    regionId: RegionId,
  ): Promise<SnapshotDetail> {
    // 从 ReleaseSnapshot 表查询快照
    const snapshot = await this.prisma.releaseSnapshot.findUnique({
      where: { id: snapshotId },
    });

    if (!snapshot) {
      throw new SnapshotNotFoundException(snapshotId, regionId);
    }

    // 获取关联的表单版本
    const formVersion = await this.prisma.formVersion.findUnique({
      where: { id: snapshot.formVersionId },
      include: { definition: true },
    });

    if (!formVersion) {
      throw new SnapshotNotFoundException(snapshotId, regionId);
    }

    // 获取流程版本
    let processVersion = null;
    if (snapshot.processVersionId) {
      processVersion = await this.prisma.approvalVersion.findUnique({
        where: { id: snapshot.processVersionId },
      });
    }

    return {
      snapshotId,
      regionId,
      formDefinitionId: formVersion.definitionId,
      formVersion: {
        id: formVersion.id,
        version: formVersion.version,
        versionName: snapshot.versionName || undefined,
        schema: formVersion.schema,
        uiSchema: formVersion.uiSchema,
      },
      processVersion: processVersion
        ? {
            id: processVersion.id,
            version: processVersion.version,
            versionName: processVersion.name,
            model: processVersion.processModel,
          }
        : {
            id: '',
            version: 1,
            model: { nodes: [], edges: [] },
          },
      status: snapshot.status === 'ACTIVE' ? 'ACTIVE' : snapshot.status,
      releaseNote: snapshot.releaseNote || undefined,
      publishedAt: snapshot.publishedAt?.toISOString(),
      publishedBy: snapshot.publishedBy || undefined,
      createdAt: snapshot.createdAt.toISOString(),
    };
  }

  // ============================================
  // 私有辅助方法
  // ============================================

  private validateRegionAccess(form: any, regionId: RegionId) {
    // 平台级表单：所有区域可访问
    if (!form.organizationId) {
      return;
    }
    
    // 组织专属表单：检查组织是否在当前区域运营
    if (form.organization && form.organization.organizationRegions) {
      // ✅ v2.0: 修复为 organizationRegions
      const orgRegionCodes = form.organization.organizationRegions
        .map((r: any) => r.region?.code)
        .filter(Boolean);
      
      if (!orgRegionCodes.includes(regionId)) {
        this.logger.warn(`[validateRegionAccess] 表单 ${form.id} 的组织区域 [${orgRegionCodes.join(', ')}] 不包含用户区域 ${regionId}`);
        throw new FormNotFoundException(form.id, regionId);
      }
      
      this.logger.debug(`[validateRegionAccess] 表单 ${form.id} 区域校验通过: ${regionId} in [${orgRegionCodes.join(', ')}]`);
    }
  }
}
