import bcrypt from 'bcryptjs'
import { AppError } from '../../http/errors'
import { prisma } from '../../lib/prisma'
import { sendNotification } from '../../services/notificationService'
import {
  coerceNotificationLocale,
  localizeBillingPeriod,
  localizePlanName,
} from '../../services/notificationLocalizationService'
import { presentCompanySignup } from './auth.presenter'
import * as repo from './auth.company.repo'
import { companySignupSchema } from './auth.company.schemas'
import type { output } from 'zod'

type CompanySignupInput = output<typeof companySignupSchema>
const TRIAL_PERIOD_DAYS = 30

function slugify(value: string) {
  return value.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '').slice(0, 50) || 'company'
}

async function generateUniqueSlug(baseName: string) {
  const base = slugify(baseName)

  for (let attempt = 0; attempt < 25; attempt++) {
    const slug = attempt === 0 ? base : `${base}-${attempt + 1}`
    const existing = await repo.findCompanyBySlug(slug)
    if (!existing) return slug
  }

  return `${base}-${Date.now().toString(36)}`
}

export async function signup(body: CompanySignupInput) {
  if (await repo.findCompanyByEmail(body.companyEmail)) {
    throw new AppError('A company account with this contact email already exists', 409, 'company_email_taken')
  }

  if (await repo.findEmployeeByEmail(body.email)) {
    throw new AppError('An employee account with this owner email already exists', 409, 'owner_email_taken')
  }

  const slug = await generateUniqueSlug(body.companyName)
  const now = new Date()
  const trialEndAt = new Date(now.getTime() + TRIAL_PERIOD_DAYS * 24 * 60 * 60 * 1000)
  const passwordHash = await bcrypt.hash(body.password, 12)

  const result = await prisma.$transaction((tx: any) => repo.createCompanySignup(tx, {
    companyName: body.companyName,
    legalName: body.legalName,
    slug,
    ownerEmail: body.email,
    companyEmail: body.companyEmail,
    companyPhone: body.companyPhone,
    streetAddress: body.streetAddress,
    city: body.city,
    country: body.country,
    zipCode: body.zipCode,
    legalForm: body.legalForm,
    managerName: `${body.firstName} ${body.lastName}`.trim(),
    iceNumber: body.iceNumber,
    taxId: body.taxId,
    operatingLicenseNumber: body.operatingLicenseNumber,
    operatingLicenseIssuedAt: body.operatingLicenseIssuedAt,
    operatingLicenseIssuedBy: body.operatingLicenseIssuedBy,
    fax: body.fax,
    yearsActive: body.yearsActive,
    representativeName: body.representativeName,
    representativeTitle: body.representativeTitle,
    responsibleName: body.responsibleName,
    responsibleRole: body.responsibleRole,
    responsibleIdentityNumber: body.responsibleIdentityNumber,
    responsibleQualification: body.responsibleQualification,
    responsiblePhone: body.responsiblePhone,
    responsibleEmail: body.responsibleEmail,
    currency: body.currency,
    registrationNumber: body.registrationNumber,
    plan: body.plan,
    billingPeriod: body.billingPeriod,
    preferredLanguage: body.preferredLanguage,
    firstName: body.firstName,
    lastName: body.lastName,
    passwordHash,
    now,
    trialEndAt,
  }))

  const lang = coerceNotificationLocale(body.preferredLanguage)
  const emailResult = await sendNotification({
    type: 'ACCOUNT_CREATED',
    companyId: result.company.id,
    employeeId: result.employee.id,
    email: body.email,
    channels: ['EMAIL', 'IN_APP'],
    locale: lang,
    templateKey: 'account.created',
    templateVariables: {
      firstName: body.firstName,
      companyName: body.companyName,
      planName: localizePlanName(body.plan, lang),
      billingPeriodLabel: localizeBillingPeriod(body.billingPeriod, lang),
      currency: body.currency,
      paymentProvider: body.paymentProvider,
      trialEndDate: trialEndAt,
    },
  }).catch(() => [])

  const emailDelivery = (emailResult as Array<{ channel?: string }>).find((entry) => entry.channel === 'EMAIL')

  return presentCompanySignup({
    company: result.company,
    trialEndAt,
    emailDelivery,
  })
}

export function completeSignupDisabled() {
  throw new AppError('Clerk-based signup has been removed. Use /auth/company/signup instead.', 410, 'disabled')
}

export function verifyEmailDisabled() {
  throw new AppError('Email verification resend via Clerk has been removed from this project.', 410, 'disabled')
}
