import bcrypt from 'bcryptjs'
import { prisma } from '../../lib/prisma'
import { signActorToken } from '../../security/tokens'

let counter = 0
function uid() {
  return `${Date.now()}-${++counter}-${Math.random().toString(36).slice(2, 7)}`
}

export async function createCompanyWithEmployee(overrides: {
  role?: 'OWNER' | 'MANAGER' | 'AGENT'
  companyStatus?: 'ACTIVE' | 'TRIALING' | 'PAST_DUE' | 'SUSPENDED' | 'PENDING'
} = {}) {
  const slug = `test-${uid()}`
  const company = await prisma.company.create({
    data: {
      name: `Test Company ${slug}`,
      slug,
      email: `company-${slug}@test.com`,
      status: (overrides.companyStatus ?? 'ACTIVE') as any,
      subscription: {
        create: { status: 'TRIALING', plan: 'STARTER' },
      },
    },
  })

  const employee = await prisma.employee.create({
    data: {
      companyId:   company.id,
      clerkUserId: `clerk_${uid()}`,
      firstName:   'Test',
      lastName:    'User',
      email:       `employee-${uid()}@test.com`,
      role:        overrides.role ?? 'OWNER',
    },
  })

  return { company, employee }
}

export async function createVehicle(companyId: string, overrides: Record<string, unknown> = {}) {
  return prisma.vehicle.create({
    data: {
      companyId,
      make:         'Toyota',
      model:        'Corolla',
      year:         2022,
      color:        'White',
      licensePlate: `PL-${uid()}`,
      dailyRate:    500,
      status:       'AVAILABLE',
      isPublished:  true,
      pickupLocations: ['Casablanca'],
      allowDifferentDropoff: false,
      dropoffLocations: [],
      ...overrides,
    } as any,
  })
}

export async function createCustomer(companyId: string, overrides: Record<string, unknown> = {}) {
  return prisma.customer.create({
    data: {
      companyId,
      firstName: 'Jane',
      lastName:  'Doe',
      email:     `customer-${uid()}@test.com`,
      ...overrides,
    },
  })
}

export async function createRenter(overrides: {
  firstName?: string
  lastName?: string
  email?: string
  password?: string
  isActive?: boolean
} = {}) {
  return prisma.renter.create({
    data: {
      firstName:    overrides.firstName ?? 'Renter',
      lastName:     overrides.lastName ?? 'User',
      email:        overrides.email ?? `renter-${uid()}@test.com`,
      passwordHash: await bcrypt.hash(overrides.password ?? 'RenterPass123!', 10),
      isActive:     overrides.isActive ?? true,
    },
  })
}

export async function createAdminUser(overrides: {
  email?: string
  firstName?: string
  lastName?: string
  password?: string
  role?: 'SUPER_ADMIN' | 'ADMIN' | 'SUPPORT' | 'FINANCE' | 'VIEWER'
  isActive?: boolean
  totpEnabled?: boolean
  totpSecret?: string | null
} = {}) {
  return prisma.adminUser.create({
    data: {
      email:        overrides.email ?? `admin-${uid()}@test.com`,
      firstName:    overrides.firstName ?? 'Admin',
      lastName:     overrides.lastName ?? 'User',
      passwordHash: await bcrypt.hash(overrides.password ?? 'AdminPass123!', 10),
      role:         (overrides.role ?? 'ADMIN') as any,
      isActive:     overrides.isActive ?? true,
      totpEnabled:  overrides.totpEnabled ?? false,
      totpSecret:   overrides.totpSecret ?? null,
    },
  })
}

export async function createReservation(
  companyId: string,
  vehicleId: string,
  customerId: string,
  overrides: Record<string, unknown> = {},
) {
  return prisma.reservation.create({
    data: {
      companyId,
      vehicleId,
      customerId,
      startDate:     new Date(Date.now() + 24 * 60 * 60 * 1000),
      endDate:       new Date(Date.now() + 4 * 24 * 60 * 60 * 1000),
      dailyRate:     500,
      totalDays:     3,
      totalAmount:   1500,
      depositAmount: 300,
      status:        'CONFIRMED',
      paymentStatus: 'UNPAID',
      paidAmount:    0,
      ...overrides,
    } as any,
  })
}

export async function createRentalPayment(
  companyId: string,
  reservationId: string,
  overrides: Record<string, unknown> = {},
) {
  return prisma.rentalPayment.create({
    data: {
      companyId,
      reservationId,
      amount:          500,
      currency:        'MAD',
      status:          'SUCCEEDED',
      type:            'CHARGE',
      paymentProvider: 'AMANPAY',
      amanpayTransactionId: `aman-${uid()}`,
      paidAt:          new Date(),
      ...overrides,
    } as any,
  })
}

export async function createSubscriptionInvoice(
  companyId: string,
  subscriptionId: string,
  overrides: Record<string, unknown> = {},
) {
  return prisma.subscriptionInvoice.create({
    data: {
      companyId,
      subscriptionId,
      amount:          2990,
      currency:        'MAD',
      status:          'PENDING',
      paymentProvider: 'AMANPAY',
      amanpayTransactionId: `sub-${uid()}`,
      ...overrides,
    } as any,
  })
}

export async function createCompanyNotification(
  companyId: string,
  employeeId?: string,
  overrides: Record<string, unknown> = {},
) {
  return prisma.notification.create({
    data: {
      companyId,
      employeeId,
      type:    'PAYMENT_RECEIVED',
      title:   'Payment received',
      body:    'A payment was recorded.',
      channel: 'IN_APP',
      status:  'PENDING',
      ...overrides,
    } as any,
  })
}

export async function createRenterNotification(
  renterId: string,
  overrides: Record<string, unknown> = {},
) {
  return prisma.notification.create({
    data: {
      renterId,
      type:    'BOOKING_CONFIRMED',
      title:   'Booking confirmed',
      body:    'Your booking is confirmed.',
      channel: 'IN_APP',
      status:  'PENDING',
      ...overrides,
    } as any,
  })
}

export function signEmployeeToken(employeeId: string, _companyId: string, _role: string = 'OWNER') {
  return signActorToken(employeeId, 'employee', { expiresIn: '1h' })
}

export function signAdminToken(adminId: string) {
  return signActorToken(adminId, 'admin', { expiresIn: '1h', last2faAt: Date.now() })
}

export function signRenterToken(renterId: string) {
  return signActorToken(renterId, 'renter', { expiresIn: '1h' })
}

export function authHeader(token: string) {
  return { Authorization: `Bearer ${token}` }
}
