import { hash } from 'bcryptjs';
import {
  AssessmentType,
  AssignmentStatus,
  CampaignStatus,
  PrismaClient,
  QuestionFieldType,
  UserStatus,
} from '@prisma/client';

const prisma = new PrismaClient();

const ACTOR = 'monthly-test-seed';
const MONTH = 3;
const YEAR = 2026;

type MonthlyQuestionSeed = {
  code: string;
  label: string;
  fieldType: QuestionFieldType;
  isRequired: boolean;
  optionsJson?: string[];
};

const monthlyQuestions: MonthlyQuestionSeed[] = [
  {
    code: 'MONTHLY_DESIGNATION',
    label: 'Designation',
    fieldType: QuestionFieldType.SHORT_TEXT,
    isRequired: true,
  },
  {
    code: 'MONTHLY_REPORTING_MANAGER',
    label: 'Reporting Manager',
    fieldType: QuestionFieldType.SHORT_TEXT,
    isRequired: true,
  },
  {
    code: 'MONTHLY_REPORT_MONTH',
    label: 'Which Month Report',
    fieldType: QuestionFieldType.SHORT_TEXT,
    isRequired: true,
  },
  {
    code: 'MONTHLY_WORK_SUMMARY',
    label: 'Brief Summary of Work Done in the Current Month',
    fieldType: QuestionFieldType.LONG_TEXT,
    isRequired: true,
  },
  {
    code: 'MONTHLY_MAJOR_TASKS',
    label: 'Major Tasks / Projects Completed this month',
    fieldType: QuestionFieldType.LONG_TEXT,
    isRequired: true,
  },
  {
    code: 'MONTHLY_VERTICAL_TIME',
    label: 'Which Vertical Worked on? and How much time it took to complete?',
    fieldType: QuestionFieldType.LONG_TEXT,
    isRequired: true,
  },
  {
    code: 'MONTHLY_KEY_ACHIEVEMENTS',
    label: 'Key Achievements / Deliverables',
    fieldType: QuestionFieldType.LONG_TEXT,
    isRequired: true,
  },
  {
    code: 'MONTHLY_TASKS_IN_PROGRESS',
    label: 'Tasks in Progress (to be continued next month)',
    fieldType: QuestionFieldType.LONG_TEXT,
    isRequired: true,
  },
  {
    code: 'MONTHLY_CHALLENGES',
    label: 'Challenges / Issues Faced (if any)',
    fieldType: QuestionFieldType.LONG_TEXT,
    isRequired: true,
  },
  {
    code: 'MONTHLY_CONFIRMATION',
    label:
      'I confirm that the information shared above is true and accurate to the best of my knowledge.',
    fieldType: QuestionFieldType.CHECKBOX,
    isRequired: true,
    optionsJson: ['Yes'],
  },
];

async function ensureRole(slug: string, name: string, description: string) {
  return prisma.role.upsert({
    where: { slug },
    update: {
      name,
      description,
      deletedAt: null,
      deletedBy: null,
      updatedBy: ACTOR,
    },
    create: {
      slug,
      name,
      description,
      createdBy: ACTOR,
      updatedBy: ACTOR,
    },
  });
}

async function ensureDepartment(code: string, name: string, description: string) {
  return prisma.department.upsert({
    where: { code },
    update: {
      name,
      description,
      deletedAt: null,
      deletedBy: null,
      updatedBy: ACTOR,
    },
    create: {
      code,
      name,
      description,
      createdBy: ACTOR,
      updatedBy: ACTOR,
    },
  });
}

async function ensureUser(input: {
  email: string;
  password: string;
  employeeCode: string;
  name: string;
  designation: string;
  roleId: string;
  departmentId: string;
  managerId?: string | null;
}) {
  const passwordHash = await hash(input.password, 10);

  return prisma.user.upsert({
    where: { email: input.email },
    update: {
      employeeCode: input.employeeCode,
      name: input.name,
      passwordHash,
      roleId: input.roleId,
      departmentId: input.departmentId,
      designation: input.designation,
      managerId: input.managerId ?? null,
      status: UserStatus.ACTIVE,
      deletedAt: null,
      deletedBy: null,
      updatedBy: ACTOR,
    },
    create: {
      email: input.email,
      employeeCode: input.employeeCode,
      name: input.name,
      passwordHash,
      roleId: input.roleId,
      departmentId: input.departmentId,
      designation: input.designation,
      managerId: input.managerId ?? null,
      status: UserStatus.ACTIVE,
      createdBy: ACTOR,
      updatedBy: ACTOR,
    },
  });
}

async function main() {
  const [adminRole, employeeRole, department] = await Promise.all([
    ensureRole('admin', 'Admin', 'Full management access'),
    ensureRole('employee', 'Employee', 'Employee self-service access for assessments'),
    ensureDepartment(
      'OPS',
      'Operations',
      'Operations and delivery team for monthly assessment testing',
    ),
  ]);

  const adminUser = await ensureUser({
    email: 'shivam@aecbiz.in',
    password: 'Aec@1234',
    employeeCode: 'AEC-ADM-001',
    name: 'Shivam',
    designation: 'Admin',
    roleId: adminRole.id,
    departmentId: department.id,
  });

  const employeeUsers = await Promise.all([
    ensureUser({
      email: 'shivamv@shuraa.in',
      password: 'Aec@1234',
      employeeCode: 'AEC-EMP-002',
      name: 'Shivam V',
      designation: 'Employee',
      roleId: employeeRole.id,
      departmentId: department.id,
      managerId: adminUser.id,
    }),
    ensureUser({
      email: 'kishan@aecbiz.in',
      password: 'Aec@1234',
      employeeCode: 'AEC-EMP-003',
      name: 'Kishan A',
      designation: 'Employee',
      roleId: employeeRole.id,
      departmentId: department.id,
      managerId: adminUser.id,
    }),
    ensureUser({
      email: 'kishan@shuraa.in',
      password: 'Aec@1234',
      employeeCode: 'AEC-EMP-004',
      name: 'Kishan S',
      designation: 'Employee',
      roleId: employeeRole.id,
      departmentId: department.id,
      managerId: adminUser.id,
    }),
  ]);

  const questions = [];
  for (const [index, question] of monthlyQuestions.entries()) {
    const savedQuestion = await prisma.questionBank.upsert({
      where: { code: question.code },
      update: {
        label: question.label,
        fieldType: question.fieldType,
        isRequired: question.isRequired,
        isActive: true,
        optionsJson: question.optionsJson,
        validationJson: undefined,
        deletedAt: null,
        deletedBy: null,
        updatedBy: ACTOR,
      },
      create: {
        code: question.code,
        label: question.label,
        fieldType: question.fieldType,
        isRequired: question.isRequired,
        isActive: true,
        optionsJson: question.optionsJson,
        createdBy: ACTOR,
        updatedBy: ACTOR,
      },
    });

    questions.push({
      ...savedQuestion,
      sortOrder: index + 1,
    });
  }

  const template = await prisma.assessmentTemplate.upsert({
    where: { code: 'MONTHLY-SIMPLE-TEST' },
    update: {
      name: 'Monthly Assessment - Simple Test',
      description: 'Simple monthly assessment used for live portal testing',
      assessmentType: AssessmentType.MONTHLY,
      version: 1,
      isActive: true,
      deletedAt: null,
      deletedBy: null,
      updatedBy: ACTOR,
    },
    create: {
      code: 'MONTHLY-SIMPLE-TEST',
      name: 'Monthly Assessment - Simple Test',
      description: 'Simple monthly assessment used for live portal testing',
      assessmentType: AssessmentType.MONTHLY,
      version: 1,
      isActive: true,
      createdBy: ACTOR,
      updatedBy: ACTOR,
    },
  });

  for (const question of questions) {
    await prisma.assessmentTemplateQuestion.upsert({
      where: {
        templateId_questionId: {
          templateId: template.id,
          questionId: question.id,
        },
      },
      update: {
        sortOrder: question.sortOrder,
        sectionName: 'Monthly Self Review',
        isRequiredOverride: true,
        deletedAt: null,
        deletedBy: null,
        updatedBy: ACTOR,
      },
      create: {
        templateId: template.id,
        questionId: question.id,
        sortOrder: question.sortOrder,
        sectionName: 'Monthly Self Review',
        isRequiredOverride: true,
        createdBy: ACTOR,
        updatedBy: ACTOR,
      },
    });
  }

  await prisma.assessmentTemplateQuestion.updateMany({
    where: {
      templateId: template.id,
      questionId: { notIn: questions.map((question) => question.id) },
      deletedAt: null,
    },
    data: {
      deletedAt: new Date(),
      deletedBy: ACTOR,
      updatedBy: ACTOR,
    },
  });

  const campaignStart = new Date(Date.UTC(YEAR, MONTH - 1, 1, 0, 0, 0));
  const campaignEnd = new Date(Date.UTC(YEAR, MONTH - 1, 31, 23, 59, 59));

  const campaign = await prisma.assessmentCampaign.upsert({
    where: {
      assessmentType_periodMonth_periodYear: {
        assessmentType: AssessmentType.MONTHLY,
        periodMonth: MONTH,
        periodYear: YEAR,
      },
    },
    update: {
      title: 'Monthly Assessment - March 2026',
      templateId: template.id,
      startDate: campaignStart,
      endDate: campaignEnd,
      status: CampaignStatus.ACTIVE,
      isAutoGenerated: false,
      deletedAt: null,
      deletedBy: null,
      updatedBy: ACTOR,
    },
    create: {
      title: 'Monthly Assessment - March 2026',
      assessmentType: AssessmentType.MONTHLY,
      templateId: template.id,
      periodMonth: MONTH,
      periodYear: YEAR,
      startDate: campaignStart,
      endDate: campaignEnd,
      status: CampaignStatus.ACTIVE,
      isAutoGenerated: false,
      createdBy: ACTOR,
      updatedBy: ACTOR,
    },
  });

  const assignedUsers = [adminUser, ...employeeUsers];
  for (const assignedUser of assignedUsers) {
    await prisma.assessmentAssignment.upsert({
      where: {
        campaignId_employeeId: {
          campaignId: campaign.id,
          employeeId: assignedUser.id,
        },
      },
      update: {
        assignedBy: adminUser.id,
        isEnabled: true,
        enabledBy: adminUser.id,
        enabledAt: new Date(),
        status: AssignmentStatus.PENDING,
        deletedAt: null,
        deletedBy: null,
        updatedBy: ACTOR,
      },
      create: {
        campaignId: campaign.id,
        employeeId: assignedUser.id,
        assignedBy: adminUser.id,
        isEnabled: true,
        enabledBy: adminUser.id,
        enabledAt: new Date(),
        status: AssignmentStatus.PENDING,
        createdBy: ACTOR,
        updatedBy: ACTOR,
      },
    });
  }

  console.log('Monthly testing data seeded successfully.');
  console.log(`Template: ${template.name}`);
  console.log(`Campaign: ${campaign.title}`);
  console.log('Users:');
  console.log('- shivam@aecbiz.in / Aec@1234');
  console.log('- shivamv@shuraa.in / Aec@1234');
  console.log('- kishan@aecbiz.in / Aec@1234');
  console.log('- kishan@shuraa.in / Aec@1234');
}

main()
  .catch(async (error) => {
    console.error(error);
    process.exitCode = 1;
  })
  .finally(async () => {
    await prisma.$disconnect();
  });
