import { Injectable } from "@nestjs/common"
import { CompanyRepository } from "./repositories/company.repository"
import { Company } from "./entities/company.entity"
import { CompanyProfile } from "./entities/company-profile.entity"
import {
  CompanySubscription,
  DurationType,
  SubscriptionStatus,
} from "./entities/company-subscription.entity"
import { CompanySettingsRepository } from "./repositories/company-settings.repository"
import { CompanyProfileRepository } from "./repositories/company-profile.repository"
import { CompanySubscriptionRepository } from "./repositories/company-subscription.repository"
import { CompanySubscriptionHistoryRepository } from "./repositories/company-subscription-history.repository"
import { CompanySubscriptionHistoryService } from "./services/company-subscription-history.service"
import { failureResponse, successResponse } from "src/common/response/response"
import { code } from "src/common/response/response.code"
import {
  validationMessage,
  successMessage,
  errorMessage,
  sendEmailNotification,
  isEmpty,
} from "src/utils/helpers"
import { messageKey } from "src/constants/message-keys"
import { verifyJwtToken, generateJwtToken } from "src/utils/jwt"
import { CreateCompanySettingDto } from "./dto/create-company-settings.dto"
import { CreateCompanyDto } from "./dto/create-company.dto"
import { RegisterCompanyDto } from "./dto/register-company.dto"
import { UpdateCompanyDto } from "./dto/update-company.dto"
import { CompanyFiltersDto } from "./dto/company-filters.dto"
import { AuthRepository } from "../auth/repositories/auth.repository"
import { AuthService } from "../auth/auth.service"
import { RoleRepository } from "../role/repositories/role.repository"
import { RolePermissionRepository } from "../role-permissions/repositories/role-permission.repository"
import { PermissionsService } from "../permissions/permissions.service"
import { DataSource } from "typeorm"
import { Auth } from "../auth/entities/auth.entity"
import { Role } from "../role/entities/role.entity"
import { RolePermission } from "../role-permissions/entities/role-permission.entity"
import { mailSubject } from "../../common/emails/email-subjects"
import { companyAdminPasswordSetupEmail } from "../../common/emails/templates/company-admin-password-setup"
import { emailVerificationTemplate } from "../../common/emails/templates/email-verification"
import { AddressRepository } from "../address/repositories/address.repository"
import { Address } from "../address/entities/address.entity"
import { ActivityType } from "../activity-types/entities/activity-type.entity"
import { ActivityTypeRepository } from "../activity-types/repositories/activity-type.repository"
import { CompanySetting } from "./entities/company-settings.entity"
import { Department } from "../departments/entities/department.entity"
import { DepartmentRepository } from "../departments/repositories/department.repository"
import { LeaveType } from "../leave-types/entities/leave-type.entity"
import { LeaveTypeRepository } from "../leave-types/repositories/leave-type.repository"
import { SalarySettingRepository } from "../salary-settings/repositories/salary-setting.repository"
import {
  defaultLeaveTypes,
  defaultSalarySettings,
} from "src/common/constents/static-const"
import {
  hasSubscriptionDataChanged,
  determineSubscriptionStatus,
} from "../../utils/subscription-status.util"
import { fileStoreLocation } from "src/common/file-upload/file-store-location"

@Injectable()
export class CompanyService {
  constructor(
    private readonly companyRepository: CompanyRepository,
    private readonly companyProfileRepository: CompanyProfileRepository,
    private readonly companySubscriptionRepository: CompanySubscriptionRepository,
    private readonly companySubscriptionHistoryRepository: CompanySubscriptionHistoryRepository,
    private readonly companySettingRepository: CompanySettingsRepository,
    private readonly authRepository: AuthRepository,
    private readonly authService: AuthService,
    private readonly roleRepository: RoleRepository,
    private readonly rolePermissionRepository: RolePermissionRepository,
    private readonly permissionsService: PermissionsService,
    private readonly addressRepository: AddressRepository,
    private readonly dataSource: DataSource,
    private readonly activityTypeRepository: ActivityTypeRepository,
    private readonly departmentRepository: DepartmentRepository,
    private readonly leaveTypeRepository: LeaveTypeRepository,
    private readonly salarySettingRepository: SalarySettingRepository,
    private readonly subscriptionHistoryService: CompanySubscriptionHistoryService,
  ) {}

  async checkCompanyExist(name: string) {
    const company: any = await this.companyRepository.getByParams({
      where: {
        name: name,
      },
    })

    return company.length > 0
  }

  /**
   * Calculate subscription dates for financial year ending March 31st
   * @param startDate - The start date of subscription
   * @returns Object with endDate and duration in days
   */
  private calculateFinancialYearSubscription(startDate: Date) {
    const currentYear = startDate.getFullYear()
    const currentMonth = startDate.getMonth() + 1 // getMonth() returns 0-11

    // Determine the financial year end date
    let financialYearEnd: Date

    if (currentMonth <= 3) {
      // If current month is Jan, Feb, or Mar - use current year March 31st
      financialYearEnd = new Date(currentYear, 2, 31) // Month is 0-indexed, so 2 = March
    } else {
      // If current month is Apr-Dec - use next year March 31st
      financialYearEnd = new Date(currentYear + 1, 2, 31)
    }

    // Calculate the difference in days
    const timeDifference = financialYearEnd.getTime() - startDate.getTime()
    const daysDifference = Math.ceil(timeDifference / (1000 * 3600 * 24))

    return {
      endDate: financialYearEnd,
      duration: daysDifference,
    }
  }

  async create(company?: Company) {
    return this.companyRepository.save(company)
  }

  async createCompany(createCompanyDto: CreateCompanyDto) {
    const queryRunner = this.dataSource.createQueryRunner()

    await queryRunner.connect()
    await queryRunner.startTransaction()

    try {
      // Check if company with same name exists
      const existingCompany = await this.companyRepository.getByParams({
        where: { name: createCompanyDto.company_name },
        findOne: true,
      })

      if (existingCompany) {
        return failureResponse(
          code.VALIDATION,
          validationMessage(messageKey.already_exist, {
            ":data": "Company",
            ":field": "name",
          }),
        )
      }

      // Check if email already exists
      const existingUser = await this.authRepository.getByParams({
        where: { email: createCompanyDto.email },
        findOne: true,
      })

      if (existingUser) {
        return failureResponse(
          code.VALIDATION,
          validationMessage(messageKey.already_exist, {
            ":data": "User",
            ":field": "email",
          }),
        )
      }

      // Step 1: Create Address (if provided)
      let addressId = null
      if (createCompanyDto.address) {
        const address = new Address()
        address.address = createCompanyDto.address
        address.lat = createCompanyDto.lat || null
        address.long = createCompanyDto.long || null
        address.company_id = null // Will be updated after company creation
        address.created_by = null

        const savedAddress = await this.addressRepository.save(
          address,
          null,
          queryRunner.manager,
        )
        addressId = savedAddress.id
      }

      // Step 2: Create Company
      const company = new Company()
      company.name = createCompanyDto.company_name
      company.address_id = addressId

      company.created_by = null // System user for initial creation

      const savedCompany = await this.companyRepository.save(
        company,
        null,
        queryRunner.manager,
      )

      // Step 3: Update Address with company_id (if address was created)
      if (addressId) {
        await this.addressRepository.save(
          {
            id: addressId,
            company_id: savedCompany.id,
          },
          null,
          queryRunner.manager,
        )
      }

      // Step 4: Create Company Profile
      const companyProfile = new CompanyProfile()
      companyProfile.company_id = savedCompany.id
      companyProfile.first_name = createCompanyDto.first_name
      companyProfile.last_name = createCompanyDto.last_name
      companyProfile.email = createCompanyDto.email
      companyProfile.phone_number = createCompanyDto.phone_number || null
      companyProfile.country_code = createCompanyDto.country_code || null
      companyProfile.currency = createCompanyDto.currency || null
      companyProfile.created_by = null

      await this.companyProfileRepository.save(
        companyProfile,
        null,
        queryRunner.manager,
      )

      // Step 5: Create Company Subscription
      const subscription = new CompanySubscription()
      subscription.company_id = savedCompany.id
      subscription.subscription_start_date = new Date(
        createCompanyDto.subscription_start_date,
      )
      subscription.duration = createCompanyDto.subscription_duration
      subscription.duration_type = createCompanyDto.subscription_duration_type
      subscription.subscription_amount = createCompanyDto.subscription_amount
      subscription.status = SubscriptionStatus.ACTIVE
      subscription.created_by = null

      // Calculate end date will be done automatically by the entity hook
      const savedSubscription = await this.companySubscriptionRepository.save(
        subscription,
        null,
        queryRunner.manager,
      )

      // Step 5.1: Create Subscription History
      await this.subscriptionHistoryService.createSubscriptionHistory(
        {
          company_id: savedCompany.id,
          subscription_id: savedSubscription.id,
          subscription_start_date: savedSubscription.subscription_start_date,
          subscription_end_date: savedSubscription.subscription_end_date,
          duration: savedSubscription.duration,
          duration_type: savedSubscription.duration_type,
          subscription_amount: savedSubscription.subscription_amount,
        },
        null, // System user for initial creation
        queryRunner.manager,
      )

      // Step 6: Create Super Admin Role
      const superAdminRole = new Role()
      superAdminRole.name = "Super Admin"
      superAdminRole.company_id = savedCompany.id
      superAdminRole.status = 1
      superAdminRole.created_by = null

      const savedRole = await this.roleRepository.save(
        superAdminRole,
        null,
        queryRunner.manager,
      )

      // Step 7: Create Admin User
      const adminUser = new Auth()
      adminUser.first_name = createCompanyDto.first_name
      adminUser.last_name = createCompanyDto.last_name
      adminUser.email = createCompanyDto.email
      adminUser.phone = createCompanyDto.phone_number || null
      adminUser.password = null // No password initially
      adminUser.company_id = savedCompany.id
      adminUser.role_id = savedRole.id
      adminUser.status = 0 // Inactive until password is set
      adminUser.created_by = null
      adminUser.slug = "super_admin"

      const savedUser = await this.authRepository.save(
        adminUser,
        null,
        queryRunner.manager,
      )

      // Step 8: Assign all permissions to Super Admin role
      await this.assignAllPermissionsToSuperAdmin(
        savedRole.id,
        savedCompany.id,
        queryRunner.manager,
      )

      // Step 9: Craete Activity Type
      const activityType = new ActivityType()
      activityType.name = "Break"
      activityType.company_id = savedCompany.id
      activityType.status = 1
      activityType.created_by = savedUser.id
      activityType.location_required = 0

      await this.activityTypeRepository.save(
        activityType,
        null,
        queryRunner.manager,
      )

      // Step 10: Craete Basic salary company settings
      const companySettings = new CompanySetting()
      companySettings.company_id = savedCompany.id
      companySettings.basic_salary_percentage = "45"
      companySettings.created_by = savedUser.id
      companySettings.working_hours_per_day = 8
      companySettings.working_days_per_month = 22
      companySettings.break_minutes_per_day = 60

      await this.companySettingRepository.save(
        companySettings,
        null,
        queryRunner.manager,
      )

      // Step 11: Create default Departments
      const defaultDepartments = [
        {
          name: "Management",
          company_id: savedCompany.id,
          status: 1,
          created_by: savedUser.id,
        },
        {
          name: "Human Resources",
          company_id: savedCompany.id,
          status: 1,
          created_by: savedUser.id,
        },
      ]

      const departmentEntities: any = defaultDepartments.map((data) => {
        const department = new Department()
        department.name = data.name
        department.company_id = data.company_id
        department.status = data.status
        department.created_by = data.created_by
        return department
      })

      await this.departmentRepository.save(
        departmentEntities,
        null,
        queryRunner.manager,
      )

      // Step 12: Create default Roles
      const defaultRoles = [
        {
          name: "Manager",
          company_id: savedCompany.id,
          status: 1,
          created_by: savedUser.id,
        },
        {
          name: "HR",
          company_id: savedCompany.id,
          status: 1,
          created_by: savedUser.id,
        },
      ]

      const roleEntities: any = defaultRoles.map((data) => {
        const role = new Role()
        role.name = data.name
        role.company_id = data.company_id
        role.status = data.status
        role.created_by = data.created_by
        return role
      })

      await this.roleRepository.save(roleEntities, null, queryRunner.manager)

      // Step 13: Create Leave Types

      const leaveTypeEntities: any = defaultLeaveTypes.map((data) => {
        const leaveType = new LeaveType()
        leaveType.name = data.name
        leaveType.code = data.code
        leaveType.company_id = savedCompany.id
        leaveType.status = 1
        leaveType.annual_allowed_days = data.annual_entitlement
        leaveType.carry_forward = data.carry_forward
        leaveType.is_paid = data.is_paid
        leaveType.created_by = savedUser.id
        return leaveType
      })

      await this.leaveTypeRepository.save(
        leaveTypeEntities,
        null,
        queryRunner.manager,
      )

      // Step 14: Create default Salary Settings
      const salarySettingEntities = defaultSalarySettings.map((setting) => ({
        company_id: savedCompany.id,
        name: setting.name,
        code: setting.code,
        type: setting.type,
        type_value: setting.type_value,
        value: setting.value,
        is_taxable: setting.is_taxable,
        created_by: savedUser.id,
      }))

      for (const salarySettingEntity of salarySettingEntities) {
        await queryRunner.manager.save("salary_settings", salarySettingEntity)
      }

      // Commit transaction
      await queryRunner.commitTransaction()

      // Step 9: Send password setup email (outside transaction)
      try {
        await this.sendCompanyAdminPasswordSetupEmail(
          savedUser.id,
          `${createCompanyDto.first_name} ${createCompanyDto.last_name}`,
          createCompanyDto.company_name,
          createCompanyDto.email,
        )
      } catch (emailError) {
        console.error("Error sending password setup email:", emailError)
        // Don't fail the entire operation if email fails
      }

      return successResponse(
        code.SUCCESS,
        successMessage(messageKey.data_add, { ":data": "Company" }),
      )
    } catch (error) {
      await queryRunner.rollbackTransaction()
      console.error("Error creating company:", error)
      return failureResponse(
        code.VALIDATION,
        errorMessage(messageKey.exception),
      )
    } finally {
      await queryRunner.release()
    }
  }

  async registerCompany(registerCompanyDto: RegisterCompanyDto) {
    const queryRunner = this.dataSource.createQueryRunner()

    await queryRunner.connect()
    await queryRunner.startTransaction()

    try {
      // Check if company with same name exists
      const existingCompany = await this.companyRepository.getByParams({
        where: { name: registerCompanyDto.company_name },
        findOne: true,
      })

      if (existingCompany) {
        return failureResponse(
          code.VALIDATION,
          validationMessage(messageKey.already_exist, {
            ":data": "Company",
            ":field": "name",
          }),
        )
      }

      // Check if email already exists
      const existingUser = await this.authRepository.getByParams({
        where: { email: registerCompanyDto.email },
        findOne: true,
      })

      if (existingUser) {
        return failureResponse(
          code.VALIDATION,
          validationMessage(messageKey.already_exist, {
            ":data": "User",
            ":field": "email",
          }),
        )
      }

      // Step 1: Create Address (if provided)
      let addressId = null
      if (registerCompanyDto.address) {
        const address = new Address()
        address.address = registerCompanyDto.address
        address.lat = registerCompanyDto.lat || null
        address.long = registerCompanyDto.long || null
        address.company_id = null // Will be updated after company creation
        address.created_by = null

        const savedAddress = await this.addressRepository.save(
          address,
          null,
          queryRunner.manager,
        )
        addressId = savedAddress.id
      }

      // Step 2: Create Company
      const company = new Company()
      company.name = registerCompanyDto.company_name
      company.address_id = addressId
      company.created_by = null // System user for initial creation

      const savedCompany = await this.companyRepository.save(
        company,
        null,
        queryRunner.manager,
      )

      // Step 3: Update Address with company_id (if address was created)
      if (addressId) {
        await this.addressRepository.save(
          {
            id: addressId,
            company_id: savedCompany.id,
          },
          null,
          queryRunner.manager,
        )
      }

      // Step 4: Create Company Profile
      const companyProfile = new CompanyProfile()
      companyProfile.company_id = savedCompany.id
      companyProfile.first_name = registerCompanyDto.first_name
      companyProfile.last_name = registerCompanyDto.last_name
      companyProfile.email = registerCompanyDto.email
      companyProfile.phone_number = registerCompanyDto.phone_number || null
      companyProfile.country_code = registerCompanyDto.country_code || null
      companyProfile.currency = registerCompanyDto.currency || null
      companyProfile.created_by = null

      await this.companyProfileRepository.save(
        companyProfile,
        null,
        queryRunner.manager,
      )

      // Step 5: Calculate subscription dates for financial year
      const today = new Date()
      const subscriptionCalculation =
        this.calculateFinancialYearSubscription(today)

      // Create Company Subscription
      const subscription = new CompanySubscription()
      subscription.company_id = savedCompany.id
      subscription.subscription_start_date = today
      subscription.subscription_end_date = subscriptionCalculation.endDate
      subscription.duration = subscriptionCalculation.duration
      subscription.duration_type = DurationType.DAYS
      subscription.subscription_amount = 0
      subscription.status = SubscriptionStatus.ACTIVE
      subscription.created_by = null

      const savedSubscription = await this.companySubscriptionRepository.save(
        subscription,
        null,
        queryRunner.manager,
      )

      // Step 5.1: Create Subscription History
      await this.subscriptionHistoryService.createSubscriptionHistory(
        {
          company_id: savedCompany.id,
          subscription_id: savedSubscription.id,
          subscription_start_date: savedSubscription.subscription_start_date,
          subscription_end_date: savedSubscription.subscription_end_date,
          duration: savedSubscription.duration,
          duration_type: savedSubscription.duration_type,
          subscription_amount: savedSubscription.subscription_amount,
        },
        null, // System user for initial creation
        queryRunner.manager,
      )

      // Step 6: Create Super Admin Role
      const superAdminRole = new Role()
      superAdminRole.name = "Super Admin"
      superAdminRole.company_id = savedCompany.id
      superAdminRole.status = 1
      superAdminRole.created_by = null

      const savedRole = await this.roleRepository.save(
        superAdminRole,
        null,
        queryRunner.manager,
      )

      // Step 7: Create Admin User (password will be hashed by entity @BeforeInsert hook)
      const adminUser = new Auth()
      adminUser.first_name = registerCompanyDto.first_name
      adminUser.last_name = registerCompanyDto.last_name
      adminUser.email = registerCompanyDto.email
      adminUser.phone = registerCompanyDto.phone_number || null
      adminUser.password = registerCompanyDto.password // Raw password - will be hashed by entity
      adminUser.company_id = savedCompany.id
      adminUser.role_id = savedRole.id
      adminUser.status = 0 // Inactive until email verification
      adminUser.is_email_verified = false
      adminUser.created_by = null
      adminUser.slug = "super_admin"

      const savedUser = await this.authRepository.save(
        adminUser,
        null,
        queryRunner.manager,
      )

      // Generate email verification token with correct user_id
      const verificationToken = generateJwtToken(
        {
          user_id: savedUser.id,
          role_id: savedRole.id,
          company_id: savedCompany.id,
          employee_id: null,
        },
        false, // No expiration for verification token
      )

      // Update user with verification token
      await this.authRepository.save(
        {
          id: savedUser.id,
          email_verification_token: verificationToken,
        },
        null,
        queryRunner.manager,
      )

      // Step 8: Assign all permissions to Super Admin role
      await this.assignAllPermissionsToSuperAdmin(
        savedRole.id,
        savedCompany.id,
        queryRunner.manager,
      )

      // Step 9: Create Activity Type
      const activityType = new ActivityType()
      activityType.name = "Break"
      activityType.company_id = savedCompany.id
      activityType.status = 1
      activityType.created_by = savedUser.id
      activityType.location_required = 0

      await this.activityTypeRepository.save(
        activityType,
        null,
        queryRunner.manager,
      )

      // Step 10: Create Basic salary company settings
      const companySettings = new CompanySetting()
      companySettings.company_id = savedCompany.id
      companySettings.basic_salary_percentage = "45"
      companySettings.created_by = savedUser.id
      companySettings.working_hours_per_day = 8
      companySettings.working_days_per_month = 22
      companySettings.break_minutes_per_day = 60

      await this.companySettingRepository.save(
        companySettings,
        null,
        queryRunner.manager,
      )

      // Step 11: Create default Departments
      const defaultDepartments = [
        {
          name: "Management",
          company_id: savedCompany.id,
          status: 1,
          created_by: savedUser.id,
        },
        {
          name: "Human Resources",
          company_id: savedCompany.id,
          status: 1,
          created_by: savedUser.id,
        },
      ]

      const departmentEntities: any = defaultDepartments.map((data) => {
        const department = new Department()
        department.name = data.name
        department.company_id = data.company_id
        department.status = data.status
        department.created_by = data.created_by
        return department
      })

      await this.departmentRepository.save(
        departmentEntities,
        null,
        queryRunner.manager,
      )

      // Step 12: Create default Roles
      const defaultRoles = [
        {
          name: "Manager",
          company_id: savedCompany.id,
          status: 1,
          created_by: savedUser.id,
        },
        {
          name: "HR",
          company_id: savedCompany.id,
          status: 1,
          created_by: savedUser.id,
        },
      ]

      const roleEntities: any = defaultRoles.map((data) => {
        const role = new Role()
        role.name = data.name
        role.company_id = data.company_id
        role.status = data.status
        role.created_by = data.created_by
        return role
      })

      await this.roleRepository.save(roleEntities, null, queryRunner.manager)

      // Step 13: Create Leave Types
      const leaveTypeEntities: any = defaultLeaveTypes.map((data) => {
        const leaveType = new LeaveType()
        leaveType.name = data.name
        leaveType.code = data.code
        leaveType.company_id = savedCompany.id
        leaveType.status = 1
        leaveType.annual_allowed_days = data.annual_entitlement
        leaveType.carry_forward = data.carry_forward
        leaveType.is_paid = data.is_paid
        leaveType.created_by = savedUser.id
        return leaveType
      })

      await this.leaveTypeRepository.save(
        leaveTypeEntities,
        null,
        queryRunner.manager,
      )

      // Step 14: Create default Salary Settings
      const salarySettingEntities = defaultSalarySettings.map((setting) => ({
        company_id: savedCompany.id,
        name: setting.name,
        code: setting.code,
        type: setting.type,
        type_value: setting.type_value,
        value: setting.value,
        is_taxable: setting.is_taxable,
        created_by: savedUser.id,
      }))

      for (const salarySettingEntity of salarySettingEntities) {
        await queryRunner.manager.save("salary_settings", salarySettingEntity)
      }

      // Commit transaction
      await queryRunner.commitTransaction()

      // Step 15: Send email verification email (outside transaction)
      try {
        await this.sendEmailVerificationEmail(
          savedUser.id,
          `${registerCompanyDto.first_name} ${registerCompanyDto.last_name}`,
          registerCompanyDto.company_name,
          registerCompanyDto.email,
          verificationToken,
        )
      } catch (emailError) {
        console.error("Error sending email verification email:", emailError)
        // Don't fail the entire operation if email fails
      }

      return {
        success: true,
        code: code.SUCCESS,
        message: successMessage(messageKey.data_add, { ":data": "Company" }),
        data: {
          message:
            "Company registered successfully. Please check your email to verify your account.",
          company_id: savedCompany.id,
          user_id: savedUser.id,
        },
      }
    } catch (error) {
      await queryRunner.rollbackTransaction()
      console.error("Error registering company:", error)
      return failureResponse(
        code.VALIDATION,
        errorMessage(messageKey.exception),
      )
    } finally {
      await queryRunner.release()
    }
  }

  private async assignAllPermissionsToSuperAdmin(
    roleId: number,
    companyId: number,
    manager: any,
  ) {
    try {
      // Get all available permissions
      const allPermissions: any = await this.permissionsService.findAll(
        {},
        true,
      )

      if (!allPermissions?.data || allPermissions.data?.length === 0) {
        console.log("No permissions found to assign")
        return
      }

      const permissions = Array.isArray(allPermissions.data)
        ? allPermissions.data
        : [allPermissions.data]

      for (const permission of permissions) {
        const rolePermission = new RolePermission()
        rolePermission.role_id = roleId
        rolePermission.permission_id = permission.id
        rolePermission.company_id = companyId
        rolePermission.status = 1
        rolePermission.created_by = null

        await this.rolePermissionRepository.save(rolePermission, null, manager)
      }
    } catch (error) {
      console.error("Error assigning permissions to Super Admin:", error)
      throw error
    }
  }

  private async sendCompanyAdminPasswordSetupEmail(
    userId: number,
    adminName: string,
    companyName: string,
    email: string,
  ) {
    try {
      const token = await this.authService.generatePasswordSetupToken(userId)
      const setupLink = `${process.env.FRONT_URL}set-password/${token}`
      const emailContent = companyAdminPasswordSetupEmail(
        adminName,
        companyName,
        setupLink,
      )

      await sendEmailNotification(
        email,
        emailContent,
        mailSubject.companyAdminPasswordSetupSubject,
      )

      console.log(`Password setup email sent to ${email}`)
    } catch (error) {
      console.error("Error sending company admin password setup email:", error)
      throw error
    }
  }

  private async sendEmailVerificationEmail(
    userId: number,
    adminName: string,
    companyName: string,
    email: string,
    verificationToken: string,
  ) {
    try {
      const verificationLink = `${process.env.FRONT_URL}verify-email?token=${verificationToken}`
      const emailContent = emailVerificationTemplate(
        adminName,
        companyName,
        verificationLink,
      )

      await sendEmailNotification(
        email,
        emailContent,
        mailSubject.emailVerificationSubject,
      )

      console.log(`Email verification sent to ${email}`)
    } catch (error) {
      console.error("Error sending email verification email:", error)
      throw error
    }
  }

  async findByName(name: string): Promise<Company | null> {
    const companies: any = await this.companyRepository.getByParams({
      where: {
        name: name,
      },
    })

    return companies.length > 0 ? companies[0] : null
  }

  async updateCompany(
    id: number,
    updateCompanyDto: UpdateCompanyDto,
    token: string,
  ) {
    const queryRunner = this.dataSource.createQueryRunner()

    await queryRunner.connect()
    await queryRunner.startTransaction()

    try {
      const decoded = verifyJwtToken(token)
      if (!decoded) {
        return failureResponse(
          code.VALIDATION,
          validationMessage(messageKey.invalid_token),
        )
      }

      // Check if company exists
      const existingCompany: any = await this.companyRepository.getByParams({
        where: { id },
        findOne: true,
      })

      if (!existingCompany) {
        return failureResponse(
          code.VALIDATION,
          validationMessage(messageKey.not_found, { ":data": "Company" }),
        )
      }

      // Check if email already exists for another company (if email is being updated)
      if (updateCompanyDto.email) {
        const existingProfile: any =
          await this.companyProfileRepository.getByParams({
            where: {
              email: updateCompanyDto.email,
            },
            whereNotIn: { id: [existingCompany.id] },
            findOne: true,
          })

        if (existingProfile) {
          return failureResponse(
            code.VALIDATION,
            validationMessage(messageKey.already_exist, {
              ":data": "Email",
              ":field": "email",
            }),
          )
        }
      }

      // Check if company name already exists for another company (if name is being updated)
      if (updateCompanyDto.company_name) {
        const existingCompanyName: any =
          await this.companyRepository.getByParams({
            where: { name: updateCompanyDto.company_name },
            findOne: true,
          })

        if (existingCompanyName && existingCompanyName.id !== id) {
          return failureResponse(
            code.VALIDATION,
            validationMessage(messageKey.already_exist, {
              ":data": "Company",
              ":field": "name",
            }),
          )
        }
      }

      // Step 1: Handle Address update/creation
      let addressId = existingCompany.address_id
      if (updateCompanyDto.address) {
        if (existingCompany.address_id) {
          // Update existing address
          const addressUpdates = {
            id: existingCompany.address_id,
            address: updateCompanyDto.address,
            lat: updateCompanyDto.lat || null,
            long: updateCompanyDto.long || null,
            company_id: existingCompany.id,
            updated_by: decoded.user_id,
          }

          await this.addressRepository.save(
            addressUpdates,
            null,
            queryRunner.manager,
          )
        } else {
          // Create new address
          const address = new Address()
          address.address = updateCompanyDto.address
          address.lat = updateCompanyDto.lat || null
          address.long = updateCompanyDto.long || null
          address.company_id = existingCompany.id
          address.created_by = decoded.user_id

          const savedAddress = await this.addressRepository.save(
            address,
            null,
            queryRunner.manager,
          )

          addressId = savedAddress.id
        }
      }

      // Step 2: Update Company basic info
      if (
        updateCompanyDto.company_name ||
        addressId !== existingCompany.address_id
      ) {
        const companyUpdates = {
          id: existingCompany.id,
          name: updateCompanyDto.company_name || existingCompany.name,
          address_id: addressId,
          status: existingCompany.status,
          updated_by: decoded.user_id,
        }

        await this.companyRepository.save(
          companyUpdates,
          null,
          queryRunner.manager,
        )
      }

      // Step 3: Update Company Profile
      const existingProfile: any =
        await this.companyProfileRepository.getByParams({
          where: { company_id: id },
          findOne: true,
        })

      if (existingProfile) {
        const profileUpdates = {
          id: existingProfile.id,
          company_id: existingProfile.company_id,
          first_name: updateCompanyDto.first_name || existingProfile.first_name,
          last_name: updateCompanyDto.last_name || existingProfile.last_name,
          email: updateCompanyDto.email || existingProfile.email,
          phone_number:
            updateCompanyDto.phone_number || existingProfile.phone_number,
          country_code:
            updateCompanyDto.country_code || existingProfile.country_code,
          currency: updateCompanyDto.currency || existingProfile.currency,
          updated_by: decoded.user_id,
        }

        await this.companyProfileRepository.save(
          profileUpdates,
          null,
          queryRunner.manager,
        )
      }

      // Step 4: Update Company Subscription
      const existingSubscription: any =
        await this.companySubscriptionRepository.getByParams({
          where: { company_id: id },
          findOne: true,
        })

      if (existingSubscription) {
        // Check if subscription data has changed
        const subscriptionDataChanged = hasSubscriptionDataChanged(
          existingSubscription,
          updateCompanyDto,
        )

        if (subscriptionDataChanged) {
          // Step 4.1: Mark existing active histories as expired
          await this.subscriptionHistoryService.expireActiveHistories(
            id,
            decoded.user_id,
            queryRunner.manager,
          )
        }

        const subscriptionUpdates: any = {
          id: existingSubscription.id,
          company_id: existingSubscription.company_id,
          subscription_start_date: updateCompanyDto.subscription_start_date
            ? new Date(updateCompanyDto.subscription_start_date)
            : existingSubscription.subscription_start_date,
          duration:
            updateCompanyDto.subscription_duration ||
            existingSubscription.duration,
          duration_type:
            updateCompanyDto.subscription_duration_type ||
            existingSubscription.duration_type,
          subscription_amount:
            updateCompanyDto.subscription_amount ||
            existingSubscription.subscription_amount,
          status: existingSubscription.status,
          updated_by: decoded.user_id,
        }

        const startDate = new Date(updateCompanyDto.subscription_start_date)

        if (
          updateCompanyDto.subscription_duration_type === DurationType.MONTHS
        ) {
          startDate.setMonth(
            startDate.getMonth() + updateCompanyDto.subscription_duration,
          )
        } else if (
          updateCompanyDto.subscription_duration_type === DurationType.YEARS
        ) {
          startDate.setFullYear(
            startDate.getFullYear() + updateCompanyDto.subscription_duration,
          )
        } else if (
          updateCompanyDto.subscription_duration_type === DurationType.DAYS
        ) {
          startDate.setDate(
            startDate.getDate() + updateCompanyDto.subscription_duration,
          )
        }

        subscriptionUpdates.subscription_end_date = startDate
        // Save subscription (end date will be recalculated automatically by entity hook)
        const updatedSubscription =
          await this.companySubscriptionRepository.save(
            subscriptionUpdates,
            null,
            queryRunner.manager,
          )

        // Step 4.2: Create new subscription history if data changed
        if (subscriptionDataChanged) {
          await this.subscriptionHistoryService.createSubscriptionHistory(
            {
              company_id: id,
              subscription_id: updatedSubscription.id,
              subscription_start_date:
                updatedSubscription.subscription_start_date,
              subscription_end_date: updatedSubscription.subscription_end_date,
              duration: updatedSubscription.duration,
              duration_type: updatedSubscription.duration_type,
              subscription_amount: updatedSubscription.subscription_amount,
            },
            decoded.user_id,
            queryRunner.manager,
          )
        }
      }

      // Commit transaction
      await queryRunner.commitTransaction()

      // Step 5: Handle email logic (outside transaction)
      try {
        // Get the admin user for this company
        const adminUser: any = await this.authRepository.getByParams({
          where: {
            company_id: id,
            slug: "super_admin",
          },
          findOne: true,
        })

        if (adminUser) {
          const adminName =
            `${updateCompanyDto.first_name || existingProfile?.first_name} ${updateCompanyDto.last_name || existingProfile?.last_name}`.trim()

          const oldEmail = adminUser?.email

          // If user has no password, send password setup email
          if (!adminUser.password) {
            await this.sendCompanyAdminPasswordSetupEmail(
              adminUser.id,
              adminName,
              updateCompanyDto.company_name || existingCompany.name,
              updateCompanyDto.email || existingProfile?.email,
            )
          }

          // If email is being changed, send email change request
          else if (
            updateCompanyDto.email &&
            oldEmail &&
            updateCompanyDto.email.trim().toLowerCase() !==
              oldEmail.trim().toLowerCase()
          ) {
            await this.authService.sendEmailChangeRequestEmail(
              adminUser.id,
              adminName,
              oldEmail,
              updateCompanyDto.email,
            )
          }
        }
      } catch (emailError) {
        console.error("Error handling email notifications:", emailError)
        // Don't fail the entire operation if email fails
      }

      return successResponse(
        code.SUCCESS,
        successMessage(messageKey.data_update, { ":data": "Company" }),
      )
    } catch (error) {
      await queryRunner.rollbackTransaction()
      console.error("Error updating company:", error)
      return failureResponse(
        code.VALIDATION,
        errorMessage(messageKey.exception),
      )
    } finally {
      await queryRunner.release()
    }
  }

  private mapCompanyRawResult(raw: any) {
    // Calculate dynamic subscription status based on current date
    let dynamicStatus = raw.cs_status
    if (raw.cs_subscription_start_date && raw.cs_subscription_end_date) {
      dynamicStatus = determineSubscriptionStatus(
        new Date(raw.cs_subscription_start_date),
        new Date(raw.cs_subscription_end_date),
      )
    }

    return {
      id: raw.c_id,
      company_name: raw.c_name,
      first_name: raw.cp_first_name,
      last_name: raw.cp_last_name,
      email: raw.cp_email,
      phone_number: raw.cp_phone_number,
      country_code: raw.cp_country_code,
      currency: raw.cp_currency,
      subscription_start_date: raw.cs_subscription_start_date,
      subscription_end_date: raw.cs_subscription_end_date,
      subscription_duration: raw.cs_duration,
      subscription_duration_type: raw.cs_duration_type,
      subscription_amount: Number(raw.cs_subscription_amount),
      subscription_status: dynamicStatus,
      address_id: raw.c_address_id,
      address: raw.a_address,
      lat: raw.a_lat,
      long: raw.a_long,
      total_employees: Number(raw.total_employees) || 0,
      total_roles: Number(raw.total_roles) || 0,
      created_at: raw.c_created_at,
      updated_at: raw.c_updated_at,
    }
  }

  async findAll(filters: CompanyFiltersDto) {
    try {
      const {
        search,
        subscription_status,
        page = 1,
        limit = 10,
        column_name,
        order = "DESC",
      } = filters

      const offset = (page - 1) * limit
      const orderDirection = isEmpty(order) ? "DESC" : order.toUpperCase()

      const qb = this.dataSource
        .createQueryBuilder("companies", "c")
        .leftJoin("company_profiles", "cp", "c.id = cp.company_id")
        .leftJoin("company_subscriptions", "cs", "c.id = cs.company_id")
        .leftJoin("addresses", "a", "c.address_id = a.id")
        .leftJoin(
          "employees",
          "e",
          "c.id = e.company_id AND e.deleted_at IS NULL",
        )
        .leftJoin("roles", "r", "c.id = r.company_id AND r.deleted_at IS NULL")
        .select([
          "c.id",
          "c.name",
          "c.address_id",
          "c.created_at",
          "c.updated_at",
          "cp.first_name",
          "cp.last_name",
          "cp.email",
          "cp.phone_number",
          "cp.country_code",
          "cp.currency",
          "cs.subscription_start_date",
          "cs.subscription_end_date",
          "cs.duration",
          "cs.duration_type",
          "cs.subscription_amount",
          "cs.status",
          "a.address",
          "a.lat",
          "a.long",
          "COUNT(DISTINCT e.id) as total_employees",
          "COUNT(DISTINCT r.id) as total_roles",
        ])
        .groupBy("c.id, cp.id, cs.id, a.id")
        .where("c.deleted_at IS NULL")

      if (search) {
        qb.andWhere(
          "(c.name ILIKE :search OR cp.first_name ILIKE :search OR cp.last_name ILIKE :search)",
          { search: `%${search}%` },
        )
      }

      if (subscription_status) {
        // Handle dynamic subscription status filtering based on current date
        const today = new Date()
        today.setHours(0, 0, 0, 0)

        switch (subscription_status) {
          case SubscriptionStatus.ACTIVE:
            qb.andWhere(
              "cs.subscription_start_date <= :today AND cs.subscription_end_date >= :today",
              { today },
            )
            break
          case SubscriptionStatus.EXPIRED:
            qb.andWhere("cs.subscription_end_date < :today", { today })
            break
          case SubscriptionStatus.UPCOMING:
            qb.andWhere("cs.subscription_start_date > :today", { today })
            break
          default:
            qb.andWhere("cs.status = :status", { status: subscription_status })
        }
      }

      // 👉 Get total BEFORE pagination - create a separate count query without GROUP BY
      const countQb = this.dataSource
        .createQueryBuilder("companies", "c")
        .leftJoin("company_profiles", "cp", "c.id = cp.company_id")
        .leftJoin("company_subscriptions", "cs", "c.id = cs.company_id")
        .where("c.deleted_at IS NULL")

      if (search) {
        countQb.andWhere(
          "(c.name ILIKE :search OR cp.first_name ILIKE :search OR cp.last_name ILIKE :search)",
          { search: `%${search}%` },
        )
      }

      if (subscription_status) {
        // Handle dynamic subscription status filtering based on current date
        const today = new Date()
        today.setHours(0, 0, 0, 0)

        switch (subscription_status) {
          case SubscriptionStatus.ACTIVE:
            countQb.andWhere(
              "cs.subscription_start_date <= :today AND cs.subscription_end_date >= :today",
              { today },
            )
            break
          case SubscriptionStatus.EXPIRED:
            countQb.andWhere("cs.subscription_end_date < :today", { today })
            break
          case SubscriptionStatus.UPCOMING:
            countQb.andWhere("cs.subscription_start_date > :today", { today })
            break
          default:
            countQb.andWhere("cs.status = :status", {
              status: subscription_status,
            })
        }
      }

      const total = await countQb.getCount()

      // 👉 Apply dynamic sorting based on column_name
      let orderByField: string = "c.created_at"

      if (!isEmpty(column_name)) {
        switch (column_name) {
          case "name":
          case "company_name":
            orderByField = "c.name"
            break

          case "subscription_amount":
            orderByField = "cs.subscription_amount"
            break

          case "subscription_start_date":
            orderByField = "cs.subscription_start_date"
            break

          case "subscription_end_date":
            orderByField = "cs.subscription_end_date"
            break

          case "subscription_duration":
            orderByField = `
        CASE
          WHEN cs.duration_type = 'Days'
            THEN cs.subscription_start_date + (cs.duration || ' days')::interval
          WHEN cs.duration_type = 'Months'
            THEN cs.subscription_start_date + (cs.duration || ' months')::interval
          WHEN cs.duration_type = 'Years'
            THEN cs.subscription_start_date + (cs.duration || ' years')::interval
        END
      `
            break

          case "created_at":
          default:
            orderByField = "c.created_at"
            break
        }
      }

      // 👉 Apply sorting + pagination AFTER count
      qb.orderBy(orderByField, orderDirection as "ASC" | "DESC")
        .limit(limit)
        .offset(offset)

      const companies = await qb.getRawMany()

      const formattedCompanies = companies.map((row) =>
        this.mapCompanyRawResult(row),
      )

      return successResponse(
        code.SUCCESS,
        successMessage(messageKey.data_retrieve, { ":data": "Companies" }),
        {
          total,
          page,
          limit,
          data: formattedCompanies,
        } as any,
      )
    } catch (error) {
      console.error("Error fetching companies:", error)
      return failureResponse(
        code.VALIDATION,
        errorMessage(messageKey.exception),
      )
    }
  }

  async findOne(id: number) {
    try {
      const qb = this.dataSource
        .createQueryBuilder("companies", "c")
        .leftJoin("company_profiles", "cp", "c.id = cp.company_id")
        .leftJoin("company_subscriptions", "cs", "c.id = cs.company_id")
        .leftJoin("addresses", "a", "c.address_id = a.id")
        .select([
          "c.id",
          "c.name",
          "c.address_id",
          "c.created_at",
          "c.updated_at",
          "cp.first_name",
          "cp.last_name",
          "cp.email",
          "cp.phone_number",
          "cp.country_code",
          "cp.currency",
          "cs.subscription_start_date",
          "cs.subscription_end_date",
          "cs.duration",
          "cs.duration_type",
          "cs.subscription_amount",
          "cs.status",
          "a.address",
          "a.lat",
          "a.long",
        ])
        .where("c.id = :id", { id })
        .andWhere("c.deleted_at IS NULL")

      const company = await qb.getRawOne()

      if (!company) {
        return failureResponse(
          code.VALIDATION,
          validationMessage(messageKey.not_found, { ":data": "Company" }),
        )
      }

      return successResponse(
        code.SUCCESS,
        successMessage(messageKey.data_retrieve, { ":data": "Company" }),
        company,
      )
    } catch (error) {
      console.error("Error fetching company:", error)
      return failureResponse(
        code.VALIDATION,
        errorMessage(messageKey.exception),
      )
    }
  }

  async activeInactive(id: number, token: string) {
    try {
      const decoded = verifyJwtToken(token)
      if (!decoded) {
        return failureResponse(
          code.VALIDATION,
          validationMessage(messageKey.invalid_token),
        )
      }

      const company: any = await this.companyRepository.getByParams({
        where: { id },
        findOne: true,
      })

      if (!company) {
        return failureResponse(
          code.VALIDATION,
          validationMessage(messageKey.not_found, { ":data": "Company" }),
        )
      }

      // Toggle status (assuming companies have a status field, if not we'll add it)
      const currentStatus = company.status || 1
      const newStatus = currentStatus === 1 ? 0 : 1

      // Update company status
      await this.companyRepository.save({
        ...company,
        status: newStatus,
        updated_by: decoded.user_id,
      })

      const statusText = newStatus === 1 ? "activated" : "deactivated"

      return successResponse(
        code.SUCCESS,
        successMessage(messageKey.data_update, {
          ":data": `Company ${statusText}`,
        }),
      )
    } catch (error) {
      console.error("Error updating company status:", error)
      return failureResponse(
        code.VALIDATION,
        errorMessage(messageKey.exception),
      )
    }
  }

  async saveCompanySettings(
    dto: CreateCompanySettingDto,
    refreshToken: string,
    logoFile?: Express.Multer.File,
  ) {
    try {
      const decoded = verifyJwtToken(refreshToken)

      const {
        working_hours_per_day,
        working_days_per_month,
        break_minutes_per_day,
        notes,
        basic_salary_percentage,
        company_name,
        website,
        hr_email,
        address,
        footer,
        logo,
        final_approval_by,
        last_day_to_fill_mis_report,
      } = dto

      if (!decoded) {
        return failureResponse(
          code.VALIDATION,
          validationMessage(messageKey.invalid_token),
        )
      }

      // Extract user id from token
      const userId = decoded?.user_id
      const companyId = decoded?.company_id

      const company: any = await this.companyRepository.getByParams({
        where: { id: companyId },
        findOne: true,
      })

      if (!company) {
        return failureResponse(
          code.VALIDATION,
          validationMessage(messageKey.not_found, { ":data": "Company" }),
        )
      }

      // Update company name if provided
      if (company && company_name) {
        company.name = company_name
        company.updated_by = userId

        await this.companyRepository.save(company)
      }

      // Handle address saving/updating
      if (address) {
        if (company && company.address_id && address) {
          // Update existing address
          const existingAddress: any = await this.addressRepository.getByParams(
            {
              where: { id: company.address_id },
              findOne: true,
            },
          )

          if (existingAddress) {
            existingAddress.address = address
            existingAddress.updated_by = userId
            await this.addressRepository.save(existingAddress)
          }
        } else {
          // Create new address
          const newAddress = {
            address: address,
            company_id: companyId,
            created_by: userId,
          }

          const savedAddress = await this.addressRepository.save(newAddress)

          // Update company with address_id
          if (company && savedAddress) {
            company.address_id = savedAddress.id
            company.updated_by = userId
            await this.companyRepository.save(company)
          }
        }
      }

      // Handle logo file upload
      let logoPath = logo

      if (logoFile) {
        logoPath = `${fileStoreLocation.company_logo}/${logoFile.filename}`
      }

      // Update company profile fields if provided
      if (website || hr_email || footer || logoPath) {
        const companyProfile: any =
          await this.companyProfileRepository.getByParams({
            where: { company_id: companyId },
            findOne: true,
          })

        if (companyProfile) {
          // Update existing profile
          if (website) companyProfile.website = website
          if (hr_email) companyProfile.hr_email = hr_email
          if (footer) companyProfile.footer = footer
          if (logoPath) companyProfile.logo = logoPath

          companyProfile.updated_by = userId

          await this.companyProfileRepository.save(companyProfile)
        } else {
          // Create new profile if it doesn't exist
          const newProfile = {
            company_id: companyId,
            website: website || null,
            hr_email: hr_email || null,
            footer: footer || null,
            logo: logoPath || null,
            created_by: userId,
          }

          await this.companyProfileRepository.save(newProfile)
        }
      }

      // ✅ Check if settings exist for company
      const existingSettings: any =
        await this.companySettingRepository.getByParams({
          where: { company_id: companyId },
          findOne: true,
        })

      if (existingSettings) {
        // Update
        existingSettings.working_hours_per_day = working_hours_per_day
        existingSettings.working_days_per_month = working_days_per_month
        existingSettings.break_minutes_per_day = break_minutes_per_day
        existingSettings.notes = notes
        existingSettings.basic_salary_percentage = basic_salary_percentage
        existingSettings.final_approval_by = final_approval_by
        existingSettings.last_day_to_fill_mis_report =
          last_day_to_fill_mis_report || null
        existingSettings.updated_by = userId

        return await this.companySettingRepository.save(existingSettings)
      }

      // Insert new
      const newSettings = {
        company_id: companyId,
        working_hours_per_day: dto.working_hours_per_day,
        working_days_per_month: dto.working_days_per_month,
        break_minutes_per_day: dto.break_minutes_per_day,
        notes: dto.notes,
        basic_salary_percentage: basic_salary_percentage,
        final_approval_by: final_approval_by,
        last_day_to_fill_mis_report: last_day_to_fill_mis_report || null,
        created_by: userId,
      }

      return await this.companySettingRepository.save(newSettings)
    } catch (error) {
      return failureResponse(
        code.VALIDATION,
        errorMessage(messageKey.exception),
      )
    }
  }

  async getCompanySettings(token: string) {
    try {
      const decoded = verifyJwtToken(token)

      if (!decoded) {
        return failureResponse(
          code.VALIDATION,
          validationMessage(messageKey.invalid_token),
        )
      }

      const companyId = decoded.company_id

      // Get company settings
      const companySettings: any =
        await this.companySettingRepository.getByParams({
          where: { company_id: companyId },
          findOne: true,
        })

      // Get company information
      const company: any = await this.companyRepository.getByParams({
        where: { id: companyId },
        findOne: true,
      })

      // Get company profile
      const companyProfile: any =
        await this.companyProfileRepository.getByParams({
          where: { company_id: companyId },
          findOne: true,
        })

      // Get company address
      let companyAddress = null

      if (company?.address_id) {
        const addressData: any = await this.addressRepository.getByParams({
          where: { id: company.address_id },
          findOne: true,
        })

        companyAddress = addressData?.address || null
      }

      // Get final approval user name
      let finalApproval = null

      if (companySettings?.final_approval_by) {
        const approvalUser: any = await this.authRepository.getByParams({
          where: { id: companySettings.final_approval_by },
          relations: ["role"],
          findOne: true,
        })

        if (approvalUser) {
          finalApproval = {
            id: approvalUser.role?.id || null,
            name: approvalUser.role?.name || null,
          }
        }
      }

      // Combine all data
      const combinedSettings = {
        ...companySettings,
        company_name: company?.name || null,
        website: companyProfile?.website || null,
        hr_email: companyProfile?.hr_email || null,
        footer: companyProfile?.footer || null,
        logo: companyProfile?.logo || null,
        address: companyAddress,
        final_approval: finalApproval,
      }

      return successResponse(
        code.SUCCESS,
        successMessage(messageKey.data_retrieve, {
          ":data": "Company settings",
        }),
        combinedSettings,
      )
    } catch (error) {
      return failureResponse(
        code.VALIDATION,
        errorMessage(messageKey.exception),
      )
    }
  }

  async deleteCompany(id: number, token: string) {
    try {
      const decoded = verifyJwtToken(token)

      if (!decoded) {
        return failureResponse(
          code.VALIDATION,
          validationMessage(messageKey.invalid_token),
        )
      }

      // Check if company exists
      const company: any = await this.companyRepository.getByParams({
        where: { id },
        findOne: true,
      })

      if (isEmpty(company)) {
        return failureResponse(
          code.VALIDATION,
          errorMessage(messageKey.data_not_found, { ":data": "Company" }),
        )
      }

      // Delete company (soft delete or hard delete based on repository config)
      await this.companyRepository.remove({ id: company.id })

      await this.companyRepository.save({
        id: company.id,
        deleted_by: decoded.user_id,
      })

      return successResponse(
        code.SUCCESS,
        successMessage(messageKey.data_removed, { ":data": "Company" }),
      )
    } catch (error) {
      return failureResponse(code.ERROR, errorMessage(messageKey.exception))
    }
  }
}
