import { Router } from 'express'
import { z } from 'zod'
import bcrypt from 'bcryptjs'
import { prisma } from '../lib/prisma'
import { sendNotification } from '../services/notificationService'

const router = Router()

const signupSchema = z.object({
  firstName: z.string().min(1).max(80),
  lastName: z.string().min(1).max(80),
  email: z.string().email(),
  password: z.string().min(8).max(128),
  companyName: z.string().min(2).max(120),
  companyPhone: z.string().optional(),
  country: z.string().optional(),
  city: z.string().optional(),
  plan: z.enum(['STARTER', 'GROWTH', 'PRO']),
  billingPeriod: z.enum(['MONTHLY', 'ANNUAL']),
  currency: z.enum(['MAD', 'USD', 'EUR']),
  paymentProvider: z.enum(['AMANPAY', 'PAYPAL']),
})

type EmailDeliveryResult = {
  attempted: boolean
  success: boolean
  error: string | null
}

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

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

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

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

function addDays(date: Date, days: number) {
  return new Date(date.getTime() + days * 24 * 60 * 60 * 1000)
}

function buildSignupConfirmationEmail(opts: {
  firstName: string
  companyName: string
  plan: 'STARTER' | 'GROWTH' | 'PRO'
  billingPeriod: 'MONTHLY' | 'ANNUAL'
  currency: 'MAD' | 'USD' | 'EUR'
  paymentProvider: 'AMANPAY' | 'PAYPAL'
  trialEndAt: Date
}) {
  const greetingName = opts.firstName.trim() || 'there'

  return [
    `Hi ${greetingName},`,
    '',
    `Your RentalDriveGo workspace for ${opts.companyName} has been created successfully.`,
    `Plan: ${opts.plan} (${opts.billingPeriod.toLowerCase()})`,
    `Currency: ${opts.currency}`,
    `Primary payment provider: ${opts.paymentProvider}`,
    `Free trial ends on ${opts.trialEndAt.toLocaleDateString('en-US', {
      year: 'numeric',
      month: 'long',
      day: 'numeric',
    })}.`,
    '',
    'Your workspace is ready and you can sign in with the email address and password you chose during signup.',
    '',
    'RentalDriveGo',
  ].join('\n')
}

async function sendSignupEmailNotification(opts: Parameters<typeof sendNotification>[0]): Promise<EmailDeliveryResult> {
  const result = await sendNotification(opts)
  const emailResult = result.find((entry) => entry.channel === 'EMAIL')

  if (!emailResult) {
    return { attempted: false, success: false, error: null }
  }

  return {
    attempted: true,
    success: emailResult.success,
    error: emailResult.error ?? null,
  }
}

router.post('/signup', async (req, res, next) => {
  try {
    const body = signupSchema.parse(req.body)

    const existingCompany = await prisma.company.findUnique({ where: { email: body.email } })
    if (existingCompany) {
      return res.status(409).json({
        error: 'email_taken',
        message: 'A company account with this email already exists',
        statusCode: 409,
      })
    }

    const existingEmployee = await prisma.employee.findFirst({ where: { email: body.email } })
    if (existingEmployee) {
      return res.status(409).json({
        error: 'email_taken',
        message: 'An employee account with this email already exists',
        statusCode: 409,
      })
    }

    const slug = await generateUniqueSlug(body.companyName)
    const now = new Date()
    const trialEndAt = addDays(now, 14)
    const passwordHash = await bcrypt.hash(body.password, 12)

    const result = await prisma.$transaction(async (tx) => {
      const company = await tx.company.create({
        data: {
          name: body.companyName,
          slug,
          email: body.email,
          phone: body.companyPhone || null,
          status: 'TRIALING',
        },
      })

      await tx.brandSettings.create({
        data: {
          companyId: company.id,
          displayName: body.companyName,
          subdomain: slug,
          publicEmail: body.email,
          publicPhone: body.companyPhone || null,
          publicCountry: body.country || null,
          publicCity: body.city || null,
          defaultCurrency: body.currency,
        },
      })

      await tx.subscription.create({
        data: {
          companyId: company.id,
          plan: body.plan,
          billingPeriod: body.billingPeriod,
          currency: body.currency,
          status: 'TRIALING',
          trialStartAt: now,
          trialEndAt,
          currentPeriodStart: now,
          currentPeriodEnd: trialEndAt,
        },
      })

      const employee = await tx.employee.create({
        data: {
          companyId: company.id,
          clerkUserId: `local_owner_${company.id}`,
          firstName: body.firstName,
          lastName: body.lastName,
          email: body.email,
          phone: body.companyPhone || null,
          passwordHash,
          role: 'OWNER',
          isActive: true,
        },
      })

      return {
        company,
        employeeId: employee.id,
      }
    })

    const emailDelivery = await sendSignupEmailNotification({
      type: 'SUBSCRIPTION_TRIAL_ENDING',
      title: 'Your workspace is ready',
      body: buildSignupConfirmationEmail({
        firstName: body.firstName,
        companyName: body.companyName,
        plan: body.plan,
        billingPeriod: body.billingPeriod,
        currency: body.currency,
        paymentProvider: body.paymentProvider,
        trialEndAt,
      }),
      companyId: result.company.id,
      employeeId: result.employeeId,
      email: body.email,
      channels: ['EMAIL', 'IN_APP'],
    })

    res.status(201).json({
      data: {
        companyId: result.company.id,
        companyName: result.company.name,
        slug: result.company.slug,
        invitationId: null,
        trialEndsAt: trialEndAt.toISOString(),
        nextStep: 'workspace_created',
        emailDelivery,
      },
    })
  } catch (err) {
    next(err)
  }
})

router.post('/complete-signup', (_req, res) => {
  res.status(410).json({
    error: 'disabled',
    message: 'Clerk-based signup has been removed. Use /auth/company/signup instead.',
    statusCode: 410,
  })
})

router.post('/verify-email', (_req, res) => {
  res.status(410).json({
    error: 'disabled',
    message: 'Email verification resend via Clerk has been removed from this project.',
    statusCode: 410,
  })
})

export default router
