import Company from '../models/company.js'

export type CompanyResolutionErrorCode =
  | 'COMPANY_REQUIRED'
  | 'INVALID_COMPANY_ID'
  | 'COMPANY_NOT_FOUND'
  | 'COMPANY_MISMATCH'

export class CompanyResolutionError extends Error {
  declare code: CompanyResolutionErrorCode

  constructor(code: CompanyResolutionErrorCode, message?: string) {
    super(message ?? code)
    this.code = code
  }
}

interface ResolveCompanyOptions {
  companyIdInput?: unknown
  companyNameInput?: string | null
  requireCompany?: boolean
}

interface CompanyResolutionResult {
  companyId: number | null
  companyName: string | null
}

function sanitizeCompanyName(name: string | null | undefined): string | null {
  if (typeof name !== 'string') {
    return null
  }

  const trimmed = name.trim()
  return trimmed.length > 0 ? trimmed : null
}

function normalizeCompanyId(companyIdInput: unknown): number | null {
  if (companyIdInput === undefined || companyIdInput === null || companyIdInput === '') {
    return null
  }

  if (typeof companyIdInput === 'number' && Number.isInteger(companyIdInput)) {
    return companyIdInput
  }

  if (typeof companyIdInput === 'string') {
    const parsed = Number(companyIdInput)
    if (!Number.isNaN(parsed) && Number.isInteger(parsed)) {
      return parsed
    }
  }

  throw new CompanyResolutionError('INVALID_COMPANY_ID', 'Invalid company ID provided')
}

export async function resolveCompanyAssociation({
  companyIdInput,
  companyNameInput,
  requireCompany = false,
}: ResolveCompanyOptions): Promise<CompanyResolutionResult> {
  const sanitizedCompanyName = sanitizeCompanyName(companyNameInput)
  const normalizedCompanyId = normalizeCompanyId(companyIdInput as any)

  if (requireCompany && !normalizedCompanyId && !sanitizedCompanyName) {
    throw new CompanyResolutionError('COMPANY_REQUIRED', 'Company information is required for this user')
  }

  let company: Company | null = null

  if (normalizedCompanyId) {
    company = await Company.query().where('id', normalizedCompanyId).whereNull('deleted_at').first()
    if (!company) {
      throw new CompanyResolutionError('COMPANY_NOT_FOUND', 'Specified company was not found')
    }

    if (
      sanitizedCompanyName &&
      sanitizedCompanyName.toLowerCase() !== company.name.trim().toLowerCase()
    ) {
      throw new CompanyResolutionError(
        'COMPANY_MISMATCH',
        'Provided company name does not match the selected company'
      )
    }
  } else if (sanitizedCompanyName) {
    company = await Company.query()
      .whereRaw('LOWER(name) = ?', [sanitizedCompanyName.toLowerCase()])
      .whereNull('deleted_at')
      .first()

    if (!company) {
      company = await Company.create({
        name: sanitizedCompanyName,
      })
    }
  }

  if (!company) {
    return { companyId: null, companyName: null }
  }

  return { companyId: company.id, companyName: company.name }
}
