import { Injectable } from '@nestjs/common';
import { Prisma } from '@/generated/prisma/client';
import type { ActivitySnapshotSource } from '@/common/decorators/activity-log.decorator';
import { PrismaService } from '@/prisma/prisma.service';

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

  findSnapshot(
    source: ActivitySnapshotSource,
    id: number,
    client: Prisma.TransactionClient = this.prisma,
  ) {
    switch (source) {
      case 'issues':
        return client.issues.findUnique({
          where: { id },
          select: issuesActivitySelect,
        });
      case 'user':
        return client.user.findUnique({
          where: { id },
          select: userActivitySelect,
        });
      case 'roles':
        return client.roles.findUnique({
          where: { id },
          select: rolesActivitySelect,
        });
      case 'permissions':
        return client.permissions.findUnique({
          where: { id },
          select: permissionsActivitySelect,
        });
      case 'stakeholder':
        return client.stakeholder.findUnique({
          where: { id },
          select: stakeholderActivitySelect,
        });
      case 'stakeholderTypes':
        return client.stakeholderTypes.findUnique({
          where: { id },
          select: stakeholderTypesActivitySelect,
        });
      case 'commentType':
        return client.commentType.findUnique({
          where: { id },
          select: commentTypeActivitySelect,
        });
      case 'indicator':
        return client.indicator.findUnique({
          where: { id },
          select: indicatorActivitySelect,
        });
      case 'issueStatuses':
        return client.issueStatuses.findUnique({
          where: { id },
          select: issueStatusesActivitySelect,
        });
      case 'categories':
        return client.categories.findUnique({
          where: { id },
          select: categoriesActivitySelect,
        });
      case 'meetingSummaryStatus':
        return client.meetingSummaryStatus.findUnique({
          where: { id },
          select: meetingSummaryStatusActivitySelect,
        });
      case 'meetingRequests':
        return client.meetingRequests.findUnique({
          where: { id },
          select: meetingRequestsActivitySelect,
        });
      case 'meeting':
        return client.meeting.findUnique({
          where: { id },
          select: meetingActivitySelect,
        });
      case 'meetingSummary':
        return client.meetingSummary.findUnique({
          where: { id },
          select: meetingSummaryActivitySelect,
        });
      case 'meetingSummaryIssueComment':
        return client.meetingSummaryIssueComment.findUnique({
          where: { id },
          select: meetingSummaryIssueCommentActivitySelect,
        });
      case 'issueResolves':
        return client.issueResolves.findUnique({
          where: { id },
          select: issueResolvesActivitySelect,
        });
      case 'progressReport':
        return client.progressReport.findUnique({
          where: { id },
          select: progressReportActivitySelect,
        });
      case 'progressReportMeeting':
        return client.progressReportMeeting.findUnique({
          where: { id },
          select: progressReportMeetingActivitySelect,
        });
      case 'progressReportDeadline':
        return client.progressReportDeadline.findUnique({
          where: { id },
          select: progressReportDeadlineActivitySelect,
        });
      case 'progressReportMinistry':
        return client.progressReportMinistry.findUnique({
          where: { id },
          select: progressReportMinistryActivitySelect,
        });
      case 'progressReportMinistryComment':
        return client.progressReportMinistryComment.findUnique({
          where: { id },
          select: progressReportMinistryCommentActivitySelect,
        });
      case 'progressReportIssueComment':
        return client.progressReportIssueComment.findUnique({
          where: { id },
          select: progressReportIssueCommentActivitySelect,
        });
      case 'progressReportIssueEvaluation':
        return client.progressReportIssueEvaluation.findUnique({
          where: { id },
          select: progressReportIssueEvaluationActivitySelect,
        });
      case 'progressReportUpdate':
        return client.progressReportUpdate.findUnique({
          where: { id },
          select: progressReportUpdateActivitySelect,
        });
      case 'progressReportUpdatePlenaryDecision':
        return client.progressReportUpdatePlenaryDecision.findUnique({
          where: { id },
          select: progressReportUpdatePlenaryDecisionActivitySelect,
        });
      case 'progressReportDashboard':
        return client.progressReportDashboard.findUnique({
          where: { id },
          select: progressReportDashboardActivitySelect,
        });
      case 'plenary':
        return client.plenary.findUnique({
          where: { id },
          select: plenaryActivitySelect,
        });
      case 'plenaryRgcDecision':
        return client.plenaryRgcDecision.findUnique({
          where: { id },
          select: plenaryRgcDecisionActivitySelect,
        });
      case 'myOrganization':
        return client.myOrganization.findUnique({
          where: { userId: id },
          select: myOrganizationActivitySelect,
        });
      case 'translation':
        return client.translation.findUnique({
          where: { id },
          select: translationActivitySelect,
        });
      case 'notificationSetting':
        return client.notificationSetting.findUnique({
          where: { userId: id },
          select: notificationSettingActivitySelect,
        });
      case 'systemNotification':
        return client.systemNotification.findUnique({
          where: { id },
          select: systemNotificationActivitySelect,
        });
    }
  }

  findActor(actorId: number) {
    return this.prisma.user.findUnique({
      where: { id: actorId },
      select: { name: true },
    });
  }

  create(data: Prisma.ActivityLogCreateInput) {
    return this.prisma.activityLog.create({ data });
  }

  findActorDetails(actorIds: number[]) {
    return this.prisma.user.findMany({
      where: { id: { in: actorIds } },
      select: {
        id: true,
        avatar: true,
        stakeholders: {
          take: 1,
          select: {
            stakeholder: { select: { name: true, description: true } },
          },
        },
      },
    });
  }

  // Read the rows and their total from the same database snapshot.
  findPage(
    where: Prisma.ActivityLogWhereInput,
    orderBy: Prisma.ActivityLogOrderByWithRelationInput[],
    page: number,
    pageSize: number,
  ) {
    return this.prisma.$transaction(
      [
        this.prisma.activityLog.findMany({
          where,
          orderBy,
          skip: (page - 1) * pageSize,
          take: pageSize,
        }),
        this.prisma.activityLog.count({ where }),
      ],
      { isolationLevel: Prisma.TransactionIsolationLevel.RepeatableRead },
    );
  }

  findForExport(
    where: Prisma.ActivityLogWhereInput,
    orderBy: Prisma.ActivityLogOrderByWithRelationInput[],
    limit: number,
  ) {
    return this.prisma.activityLog.findMany({ where, orderBy, take: limit });
  }

  findMeetingSummaryStatus(id: number) {
    return this.prisma.meetingSummary.findUnique({
      where: { id },
      select: { meetingSummaryStatus: { select: { name: true } } },
    });
  }

  findIssuePrimaryAgency(id: number) {
    return this.prisma.issues.findUnique({
      where: { id },
      select: {
        governmentAgencies: {
          where: { agencyOrder: 1 },
          take: 1,
          select: { stakeholder: { select: { name: true } } },
        },
      },
    });
  }

  findIssueStatus(id: number) {
    return this.prisma.issues.findUnique({
      where: { id },
      select: { issueStatus: { select: { name: true } } },
    });
  }

  findProgressReportMinistryStatus(
    progressReportId: number,
    ministryId: number,
  ) {
    return this.prisma.progressReportMinistry.findUnique({
      where: {
        progressReportId_ministryId: { progressReportId, ministryId },
      },
      select: { status: true },
    });
  }

  findFilterOptions() {
    return Promise.all([
      this.prisma.activityLog.findMany({
        distinct: ['module'],
        select: { module: true },
        orderBy: { module: 'asc' },
      }),
      this.prisma.activityLog.findMany({
        distinct: ['action'],
        select: { action: true },
        orderBy: { action: 'asc' },
      }),
      this.prisma.activityLog.findMany({
        distinct: ['actorId'],
        select: { actorId: true, actorName: true },
        orderBy: [{ createdAt: 'desc' }, { id: 'desc' }],
      }),
      this.prisma.activityLog.findMany({
        distinct: ['actorRoles'],
        select: { actorRoles: true },
      }),
    ]);
  }
}

// Only these fields may be read for activity changes. Never select authentication secrets.
const issuesActivitySelect = {
  id: true,
  title: true,
  description: true,
  recommendation: true,
  attachment: true,
  escalation: true,
  deletedAt: true,
  issueStatus: { select: { id: true, name: true } },
  category: { select: { id: true, name: true } },
  stakeholder: { select: { id: true, name: true } },
  governmentAgencies: {
    select: {
      stakeholder: { select: { id: true, name: true } },
      agencyOrder: true,
    },
  },
  linkedMeetingRequests: {
    select: { meetingRequest: { select: { id: true, title: true } } },
  },
} satisfies Prisma.IssuesSelect;
const userActivitySelect = {
  id: true,
  name: true,
  position: true,
  isActive: true,
  avatar: true,
  deletedAt: true,
  roles: { select: { role: { select: { id: true, name: true } } } },
  permissions: { select: { permission: { select: { id: true, name: true } } } },
  stakeholders: {
    select: { stakeholder: { select: { id: true, name: true } } },
  },
} satisfies Prisma.UserSelect;
const rolesActivitySelect = {
  id: true,
  name: true,
  guardName: true,
  deletedAt: true,
  permissions: { select: { permission: { select: { id: true, name: true } } } },
} satisfies Prisma.RolesSelect;
const permissionsActivitySelect = {
  id: true,
  name: true,
  guardName: true,
  deletedAt: true,
} satisfies Prisma.PermissionsSelect;
const stakeholderActivitySelect = {
  id: true,
  name: true,
  description: true,
  coChair: true,
  active: true,
  logo: true,
  deletedAt: true,
  stakeholderType: { select: { id: true, name: true } },
  relatedStakeholder: { select: { id: true, name: true } },
  users: { select: { user: { select: { id: true, name: true } } } },
} satisfies Prisma.StakeholderSelect;
const stakeholderTypesActivitySelect = {
  id: true,
  name: true,
  deletedAt: true,
} satisfies Prisma.StakeholderTypesSelect;
const commentTypeActivitySelect = {
  id: true,
  name: true,
  description: true,
  deletedAt: true,
} satisfies Prisma.CommentTypeSelect;
const indicatorActivitySelect = {
  id: true,
  name: true,
  description: true,
  deletedAt: true,
} satisfies Prisma.IndicatorSelect;
const issueStatusesActivitySelect = {
  id: true,
  code: true,
  name: true,
  deletedAt: true,
} satisfies Prisma.IssueStatusesSelect;
const categoriesActivitySelect = {
  id: true,
  name: true,
  deletedAt: true,
} satisfies Prisma.CategoriesSelect;
const meetingSummaryStatusActivitySelect = {
  id: true,
  code: true,
  name: true,
  deletedAt: true,
} satisfies Prisma.MeetingSummaryStatusSelect;
const meetingRequestsActivitySelect = {
  id: true,
  title: true,
  description: true,
  meetingRequestLetter: true,
  status: true,
  submittedAt: true,
  deletedAt: true,
  governmentAgencies: {
    select: { stakeholder: { select: { id: true, name: true } } },
  },
  linkedIssues: { select: { issue: { select: { id: true, title: true } } } },
} satisfies Prisma.MeetingRequestsSelect;
const meetingActivitySelect = {
  id: true,
  title: true,
  description: true,
  meetingDate: true,
  startTime: true,
  location: true,
  documentReference: true,
  status: true,
  deletedAt: true,
  guests: { select: { id: true, user: { select: { id: true, name: true } } } },
  linkedMeetingRequests: {
    select: { meetingRequest: { select: { id: true, title: true } } },
  },
} satisfies Prisma.MeetingSelect;
const meetingSummaryActivitySelect = {
  id: true,
  documentReference: true,
  share: true,
  sharedAt: true,
  sendBackReason: true,
  sentBackAt: true,
  pswg_reporter: true,
  pswg_reporter_position: true,
  pswg_representative: true,
  pswg_representative_position: true,
  ministry_reporter: true,
  ministry_reporter_position: true,
  ministry_representative: true,
  ministry_representative_position: true,
  deletedAt: true,
  meetingSummaryStatus: { select: { id: true, name: true } },
  linkedMeetings: {
    select: { meeting: { select: { id: true, title: true } } },
  },
  issueResolves: {
    select: {
      id: true,
      rgcDecision: true,
      nextStep: true,
      remark: true,
      documentReference: true,
      deletedAt: true,
      issueStatus: { select: { id: true, name: true } },
      escalate: { select: { id: true, name: true } },
      issue: { select: { id: true, title: true } },
      issueResolveAgencies: {
        select: { stakeholder: { select: { id: true, name: true } } },
      },
    },
  },
  issueComments: {
    select: {
      id: true,
      comment: true,
      releasedAt: true,
      deletedAt: true,
      commentType: { select: { id: true, name: true } },
      issue: { select: { id: true, title: true } },
    },
  },
} satisfies Prisma.MeetingSummarySelect;
const meetingSummaryIssueCommentActivitySelect = {
  id: true,
  comment: true,
  releasedAt: true,
  deletedAt: true,
  commentType: { select: { id: true, name: true } },
  issue: { select: { id: true, title: true } },
} satisfies Prisma.MeetingSummaryIssueCommentSelect;
const issueResolvesActivitySelect = {
  id: true,
  rgcDecision: true,
  nextStep: true,
  remark: true,
  documentReference: true,
  deletedAt: true,
  issueStatus: { select: { id: true, name: true } },
  escalate: { select: { id: true, name: true } },
  issue: { select: { id: true, title: true } },
  issueResolveAgencies: {
    select: { stakeholder: { select: { id: true, name: true } } },
  },
} satisfies Prisma.IssueResolvesSelect;
const progressReportActivitySelect = {
  id: true,
  title: true,
  description: true,
  year: true,
  semester: true,
  status: true,
  attachment: true,
  draftSemesterReport: true,
  finalSemesterReport: true,
  draftSemesterReportStatus: true,
  finalSemesterReportStatus: true,
  deletedAt: true,
  ministries: {
    select: {
      id: true,
      issues: true,
      attachment: true,
      status: true,
      submittedAt: true,
      reviewedAt: true,
      deletedAt: true,
      ministry: { select: { id: true, name: true } },
      reviewedBy: { select: { id: true, name: true } },
      comment: {
        select: {
          id: true,
          comment: true,
          deletedAt: true,
          commentType: { select: { id: true, name: true } },
        },
      },
      progressReportIssueEvaluations: {
        select: {
          id: true,
          isResolved: true,
          rating: true,
          feedback: true,
          deletedAt: true,
          issue: { select: { id: true, title: true } },
        },
      },
    },
  },
  meetings: {
    select: {
      id: true,
      title: true,
      description: true,
      meetingDate: true,
      startTime: true,
      location: true,
      documentReference: true,
      status: true,
      deletedAt: true,
    },
  },
  deadlines: {
    select: {
      id: true,
      deadline: true,
      status: true,
      sentAt: true,
      deletedAt: true,
    },
  },
  progressReportUpdates: {
    select: {
      id: true,
      indicators: true,
      progressSolution: true,
      implementationChallenges: true,
      requests: true,
      sourceOfVerification: true,
      linkToVerificationSource: true,
      dateOfIssueSolution: true,
      attachement: true,
      next_step: true,
      deletedAt: true,
      issueStatus: { select: { id: true, name: true } },
      ministry: { select: { id: true, name: true } },
      issue: { select: { id: true, title: true } },
      progressReportUpdateIssues: {
        select: {
          id: true,
          issueId: true,
          progressReportIssueComments: {
            select: {
              id: true,
              comment: true,
              deletedAt: true,
              commentType: { select: { id: true, name: true } },
            },
          },
        },
      },
    },
  },
  progressReportUpdatePlenaryDecisions: {
    select: {
      id: true,
      cdcInProgressStatus: true,
      deletedAt: true,
      progressReportIssueComments: {
        select: {
          id: true,
          comment: true,
          deletedAt: true,
          commentType: { select: { id: true, name: true } },
        },
      },
      progressReportUpdate: {
        select: {
          id: true,
          indicators: true,
          progressSolution: true,
          implementationChallenges: true,
          requests: true,
          sourceOfVerification: true,
          linkToVerificationSource: true,
          dateOfIssueSolution: true,
          attachement: true,
          next_step: true,
          deletedAt: true,
        },
      },
    },
  },
  progressReportDashboards: {
    select: {
      id: true,
      type: true,
      status: true,
      totalIssues: true,
      solved: true,
      inProgress: true,
      notAddressed: true,
      totalPrimaryAgencies: true,
      midProgress: true,
      earlyProgress: true,
      generatedAt: true,
      deletedAt: true,
    },
  },
  ministryDocuments: {
    select: { id: true, ministryId: true, document: true, deletedAt: true },
  },
} satisfies Prisma.ProgressReportSelect;
const progressReportMeetingActivitySelect = {
  id: true,
  title: true,
  description: true,
  meetingDate: true,
  startTime: true,
  location: true,
  documentReference: true,
  status: true,
  deletedAt: true,
} satisfies Prisma.ProgressReportMeetingSelect;
const progressReportDeadlineActivitySelect = {
  id: true,
  deadline: true,
  status: true,
  sentAt: true,
  deletedAt: true,
} satisfies Prisma.ProgressReportDeadlineSelect;
const progressReportMinistryActivitySelect = {
  id: true,
  issues: true,
  attachment: true,
  status: true,
  submittedAt: true,
  reviewedAt: true,
  deletedAt: true,
  ministry: { select: { id: true, name: true } },
  reviewedBy: { select: { id: true, name: true } },
  comment: {
    select: {
      id: true,
      comment: true,
      deletedAt: true,
      commentType: { select: { id: true, name: true } },
    },
  },
  progressReportIssueEvaluations: {
    select: {
      id: true,
      isResolved: true,
      rating: true,
      feedback: true,
      deletedAt: true,
      issue: { select: { id: true, title: true } },
    },
  },
} satisfies Prisma.ProgressReportMinistrySelect;
const progressReportMinistryCommentActivitySelect = {
  id: true,
  comment: true,
  deletedAt: true,
  commentType: { select: { id: true, name: true } },
} satisfies Prisma.ProgressReportMinistryCommentSelect;
const progressReportIssueCommentActivitySelect = {
  id: true,
  comment: true,
  deletedAt: true,
  commentType: { select: { id: true, name: true } },
} satisfies Prisma.ProgressReportIssueCommentSelect;
const progressReportIssueEvaluationActivitySelect = {
  id: true,
  isResolved: true,
  rating: true,
  feedback: true,
  deletedAt: true,
  issue: { select: { id: true, title: true } },
} satisfies Prisma.ProgressReportIssueEvaluationSelect;
const progressReportUpdateActivitySelect = {
  id: true,
  indicators: true,
  progressSolution: true,
  implementationChallenges: true,
  requests: true,
  sourceOfVerification: true,
  linkToVerificationSource: true,
  dateOfIssueSolution: true,
  attachement: true,
  next_step: true,
  deletedAt: true,
  issueStatus: { select: { id: true, name: true } },
  ministry: { select: { id: true, name: true } },
  issue: { select: { id: true, title: true } },
  progressReportUpdateIssues: {
    select: {
      id: true,
      issueId: true,
      progressReportIssueComments: {
        select: {
          id: true,
          comment: true,
          deletedAt: true,
          commentType: { select: { id: true, name: true } },
        },
      },
    },
  },
} satisfies Prisma.ProgressReportUpdateSelect;
const progressReportUpdatePlenaryDecisionActivitySelect = {
  id: true,
  cdcInProgressStatus: true,
  deletedAt: true,
  progressReportIssueComments: {
    select: {
      id: true,
      comment: true,
      deletedAt: true,
      commentType: { select: { id: true, name: true } },
    },
  },
  progressReportUpdate: {
    select: {
      id: true,
      indicators: true,
      progressSolution: true,
      implementationChallenges: true,
      requests: true,
      sourceOfVerification: true,
      linkToVerificationSource: true,
      dateOfIssueSolution: true,
      attachement: true,
      next_step: true,
      deletedAt: true,
    },
  },
} satisfies Prisma.ProgressReportUpdatePlenaryDecisionSelect;
const progressReportDashboardActivitySelect = {
  id: true,
  type: true,
  status: true,
  totalIssues: true,
  solved: true,
  inProgress: true,
  notAddressed: true,
  totalPrimaryAgencies: true,
  midProgress: true,
  earlyProgress: true,
  generatedAt: true,
  deletedAt: true,
} satisfies Prisma.ProgressReportDashboardSelect;
const plenaryActivitySelect = {
  id: true,
  name: true,
  meetingDate: true,
  deadline: true,
  documentReference: true,
  status: true,
  deletedAt: true,
  ministries: { select: { stakeholder: { select: { id: true, name: true } } } },
} satisfies Prisma.PlenarySelect;
const plenaryRgcDecisionActivitySelect = {
  id: true,
  meetingDate: true,
  status: true,
  focalPerson: true,
  decision: true,
  verificationSource: true,
  verificationLink: true,
  submittedToCdcAt: true,
  revisionOpen: true,
  deletedAt: true,
  category: { select: { id: true, name: true } },
  indicator: { select: { id: true, name: true } },
  stakeholder: { select: { id: true, name: true } },
  decisionIssues: { select: { issue: { select: { id: true, title: true } } } },
} satisfies Prisma.PlenaryRgcDecisionSelect;
const myOrganizationActivitySelect = {
  id: true,
  name: true,
  organizationType: true,
  description: true,
  coChair: true,
  active: true,
  logo: true,
  systemLogo: true,
} satisfies Prisma.MyOrganizationSelect;
const translationActivitySelect = {
  id: true,
  translationKey: true,
  englishText: true,
  khmerText: true,
  module: true,
  page: true,
  parentId: true,
  isActive: true,
} satisfies Prisma.TranslationSelect;
const notificationSettingActivitySelect = {
  id: true,
  systemEnabled: true,
  unreadBadge: true,
  markReadOnDetail: true,
  gmailEnabled: true,
  gmailAddress: true,
} satisfies Prisma.NotificationSettingSelect;
const systemNotificationActivitySelect = {
  id: true,
  title: true,
  message: true,
  type: true,
  isRead: true,
  readAt: true,
  receiverUserId: true,
  receiverStakeholderId: true,
  deletedAt: true,
} satisfies Prisma.SystemNotificationSelect;
