import { Injectable } from "@nestjs/common"
import { defaultCompanies } from "../../../config/app.config"
import { Company } from "../../../modules/company/entities/company.entity"
import { CompanyProfile } from "../../../modules/company/entities/company-profile.entity"
import {
  CompanySubscription,
  DurationType,
  SubscriptionStatus,
} from "../../../modules/company/entities/company-subscription.entity"
import { CompanyService } from "src/modules/company/company.service"
import { RoleService } from "../../../modules/role/role.service"
import { AuthService } from "../../../modules/auth/auth.service"
import { Role } from "../../../modules/role/entities/role.entity"
import { Auth } from "../../../modules/auth/entities/auth.entity"
import { RoleRepository } from "../../../modules/role/repositories/role.repository"
import { AuthRepository } from "../../../modules/auth/repositories/auth.repository"
import { CompanyProfileRepository } from "../../../modules/company/repositories/company-profile.repository"
import { CompanySubscriptionRepository } from "../../../modules/company/repositories/company-subscription.repository"
import { RolePermissionsService } from "../../../modules/role-permissions/role-permissions.service"
import { PermissionsService } from "../../../modules/permissions/permissions.service"
import { RolePermissionRepository } from "../../../modules/role-permissions/repositories/role-permission.repository"
import { RolePermission } from "../../../modules/role-permissions/entities/role-permission.entity"
import { PERMISSIONS } from "../../../constants/permissions.constant"

@Injectable()
export class CompanySeedService {
  constructor(
    private readonly companyService: CompanyService,
    private readonly roleService: RoleService,
    private readonly authService: AuthService,
    private readonly roleRepository: RoleRepository,
    private readonly authRepository: AuthRepository,
    private readonly companyProfileRepository: CompanyProfileRepository,
    private readonly companySubscriptionRepository: CompanySubscriptionRepository,
    private readonly rolePermissionsService: RolePermissionsService,
    private readonly permissionsService: PermissionsService,
    private readonly rolePermissionRepository: RolePermissionRepository,
  ) {}

  async run() {
    try {
      for (const companyData of defaultCompanies) {
        console.log(`Processing company: ${companyData.name}`)

        // Step 1: Check if company exists → create if not
        let createdCompany: Company
        const isCompanyExist = await this.companyService.checkCompanyExist(
          companyData.name,
        )

        if (!isCompanyExist) {
          const newCompany = new Company()
          newCompany.name = companyData.name
          newCompany.address_id = companyData.address_id || null

          createdCompany = await this.companyService.create(newCompany)
          console.log(`✓ Company created: ${companyData.name}`)
        } else {
          // Get existing company for further processing
          createdCompany = await this.companyService.findByName(
            companyData.name,
          )
          console.log(`✓ Company already exists: ${companyData.name}`)
        }

        // Step 2: Check if "Super Admin" role exists for that company → create if not
        let superAdminRole = await this.roleService.findRoleByNameAndCompany(
          "Super Admin",
          createdCompany.id,
        )

        if (!superAdminRole) {
          // Create role directly using repository since we need the actual entity
          const newRole = new Role()
          newRole.name = "Super Admin"
          newRole.company_id = createdCompany.id
          newRole.created_by = null // System user
          newRole.status = 1

          superAdminRole = await this.roleRepository.save(newRole)
          console.log(
            `✓ Super Admin role created for company: ${companyData.name}`,
          )
        } else {
          console.log(
            `✓ Super Admin role already exists for company: ${companyData.name}`,
          )
        }

        // Step 3: Assign all permissions to Super Admin role
        await this.assignAllPermissionsToSuperAdmin(
          superAdminRole.id,
          createdCompany.id,
          companyData.name,
        )

        // Step 4: Check if company profile exists → create if not
        const existingProfile = await this.companyProfileRepository.getByParams(
          {
            where: { company_id: createdCompany.id },
            findOne: true,
          },
        )

        if (!existingProfile) {
          const companyProfile = new CompanyProfile()
          companyProfile.company_id = createdCompany.id
          companyProfile.first_name = companyData.admin_first_name
          companyProfile.last_name = companyData.admin_last_name
          companyProfile.email = companyData.admin_email
          companyProfile.phone_number =
            (companyData as any).phone_number || null
          companyProfile.created_by = null

          await this.companyProfileRepository.save(companyProfile)
          console.log(
            `✓ Company profile created for company: ${companyData.name}`,
          )
        } else {
          console.log(
            `✓ Company profile already exists for company: ${companyData.name}`,
          )
        }

        // Step 5: Check if company subscription exists → create if not
        const existingSubscription =
          await this.companySubscriptionRepository.getByParams({
            where: { company_id: createdCompany.id },
            findOne: true,
          })

        if (!existingSubscription) {
          const subscription = new CompanySubscription()
          subscription.company_id = createdCompany.id
          subscription.subscription_start_date = new Date(
            (companyData as any).subscription_start_date || new Date(),
          )
          subscription.duration =
            (companyData as any).subscription_duration || 12
          subscription.duration_type =
            (companyData as any).subscription_duration_type ||
            DurationType.MONTHS
          subscription.subscription_amount =
            (companyData as any).subscription_amount || 1000
          subscription.status = SubscriptionStatus.ACTIVE
          subscription.created_by = null

          await this.companySubscriptionRepository.save(subscription)
          console.log(
            `✓ Company subscription created for company: ${companyData.name} with amount: ${subscription.subscription_amount}`,
          )
        } else {
          console.log(
            `✓ Company subscription already exists for company: ${companyData.name}`,
          )
        }

        // Step 6: Check if admin user exists → create if not
        const existingUser = await this.authRepository.getByParams({
          where: { email: companyData.admin_email },
          findOne: true,
        })

        if (!existingUser) {
          const superAdminUser = new Auth()
          superAdminUser.first_name = companyData.admin_first_name
          superAdminUser.last_name = companyData.admin_last_name
          superAdminUser.email = companyData.admin_email
          superAdminUser.password = companyData.admin_password
          superAdminUser.company_id = createdCompany.id
          superAdminUser.role_id = superAdminRole.id
          superAdminUser.status = 1
          superAdminUser.slug = "super_admin"

          await this.authRepository.save(superAdminUser)
          console.log(
            `✓ Super Admin user created: ${companyData.admin_email} for company: ${companyData.name}`,
          )
        } else {
          console.log(`✓ User already exists: ${companyData.admin_email}`)
        }

        console.log(
          `--- Completed processing for company: ${companyData.name} ---\n`,
        )
      }
      console.log("🎉 Company seeder has been run successfully!")
    } catch (error) {
      console.error("❌ Error running Company seeder:", error)
      throw error
    }
  }

  private async assignAllPermissionsToSuperAdmin(
    roleId: number,
    companyId: number,
    companyName: string,
  ) {
    try {
      console.log(
        `🔐 Assigning permissions to Super Admin role for company: ${companyName}`,
      )

      // Get all available permissions
      const allPermissions: any = await this.permissionsService.findAll({})

      if (!allPermissions?.data || allPermissions.data?.length === 0) {
        console.log(
          `⚠️  No permissions found to assign for company: ${companyName}`,
        )
        return
      }

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

      let assignedCount = 0
      let skippedCount = 0

      // Define COMPANY permissions that should only be assigned to master_admin
      const companyOnlyPermissions = [
        PERMISSIONS.COMPANY.VIEW,
        PERMISSIONS.COMPANY.MANAGE,
      ]

      for (const permission of permissions) {
        // Skip COMPANY permissions for Super Admin roles (they should only be for master_admin)
        if (companyOnlyPermissions.includes(permission.permission_key)) {
          skippedCount++
          continue
        }
        // Check if role-permission already exists
        const existingRolePermission: any =
          await this.rolePermissionRepository.getByParams({
            where: {
              role_id: roleId,
              permission_id: permission.id,
              company_id: companyId,
            },
            whereNull: ["deleted_at"],
            findOne: true,
          })

        if (!existingRolePermission) {
          // Create new role-permission assignment
          const rolePermission = new RolePermission()
          rolePermission.role_id = roleId
          rolePermission.permission_id = permission.id
          rolePermission.company_id = companyId
          rolePermission.status = 1
          rolePermission.created_by = null // System user

          await this.rolePermissionRepository.save(rolePermission)
          assignedCount++
        } else {
          // Update status if it's inactive
          if (existingRolePermission.status !== 1) {
            existingRolePermission.status = 1
            await this.rolePermissionRepository.save(existingRolePermission)
            assignedCount++
          } else {
            skippedCount++
          }
        }
      }

      console.log(
        `✅ Permissions assignment completed for ${companyName}: ${assignedCount} assigned, ${skippedCount} already existed`,
      )
    } catch (error) {
      console.error(
        `❌ Error assigning permissions to Super Admin for company ${companyName}:`,
        error,
      )
      throw error
    }
  }
}
