import { Router, type Request, type Response } from 'express'
import bcrypt from 'bcryptjs'
import { Prisma, type LicenseStatus } from '@prisma/client'
import { licenseProductName } from '../config.js'
import { prisma } from '../db.js'
import { generateStackLogicLicenseKey } from '../license/generator.js'
import { audit } from '../services/audit.js'
import { sendLicenseEmail } from '../services/email.js'
import {
  checkLoginRateLimit,
  clearLoginRateLimit,
  createAdminSession,
  destroyAdminSession,
  requireAdmin,
  requireCsrf,
  verifyPassword,
} from './auth.js'
import { dateTime, dollars, escapeHtml, layout, licenseStatusOptions, shortKey, statusBadge } from './html.js'

export const adminRouter = Router()

function csrf(request: Request) {
  return request.admin?.csrfToken ?? ''
}

function adminUser(request: Request) {
  return request.admin ? { id: request.admin.id, email: request.admin.email, name: request.admin.name } : undefined
}

function routeId(request: Request) {
  const id = request.params.id
  return Array.isArray(id) ? id[0] : id
}

adminRouter.get('/styles.css', (_request, response) => {
  response.type('text/css').send(`
    :root { color-scheme: light; font-family: Inter, Segoe UI, Arial, sans-serif; color: #0f172a; background: #eef3f8; }
    body { margin: 0; }
    .topbar { display: flex; justify-content: space-between; align-items: center; gap: 24px; padding: 22px 32px; background: #0f172a; color: white; }
    .topbar p { margin: 0 0 4px; color: #93c5fd; font-size: 12px; font-weight: 800; letter-spacing: .08em; text-transform: uppercase; }
    .topbar h1 { margin: 0; font-size: 24px; }
    nav { display: flex; align-items: center; gap: 12px; }
    nav a, nav button, .button { border: 1px solid #cbd5e1; border-radius: 6px; background: #fff; color: #0f172a; padding: 8px 11px; font-weight: 800; text-decoration: none; cursor: pointer; }
    main { padding: 24px 32px 42px; }
    .panel { border: 1px solid #cbd5e1; border-radius: 8px; background: #fff; padding: 18px; box-shadow: 0 14px 34px rgba(15,23,42,.08); }
    .grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; }
    .toolbar { display: flex; flex-wrap: wrap; align-items: end; gap: 12px; margin-bottom: 16px; }
    label { display: grid; gap: 5px; color: #475569; font-size: 12px; font-weight: 800; }
    input, select, textarea { box-sizing: border-box; width: 100%; border: 1px solid #cbd5e1; border-radius: 6px; padding: 9px; color: #0f172a; font: inherit; }
    textarea { min-height: 90px; resize: vertical; }
    table { width: 100%; border-collapse: collapse; background: white; }
    th, td { border: 1px solid #cbd5e1; padding: 8px; font-size: 13px; vertical-align: top; }
    th { background: #335a9b; color: white; text-align: left; position: sticky; top: 0; }
    td code { font-size: 11px; overflow-wrap: anywhere; }
    .muted { color: #64748b; }
    .actions { display: flex; flex-wrap: wrap; gap: 8px; }
    .actions form { display: inline; }
    .danger { border-color: #ef4444; color: #b91c1c; }
    .primary { border-color: #1d4ed8; background: #2563eb; color: white; }
    .badge { display: inline-block; border-radius: 999px; padding: 3px 8px; background: #e2e8f0; font-size: 12px; font-weight: 900; }
    .badge.active, .badge.sent { background: #dcfce7; color: #166534; }
    .badge.disabled, .badge.failed { background: #fee2e2; color: #991b1b; }
    .badge.replaced, .badge.archived, .badge.pending { background: #fef3c7; color: #92400e; }
    .detail { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
    dl { display: grid; grid-template-columns: 170px 1fr; gap: 8px 12px; margin: 0; }
    dt { color: #64748b; font-weight: 800; }
    dd { margin: 0; overflow-wrap: anywhere; }
    .error { border: 1px solid #fdba74; border-radius: 6px; background: #fff7ed; color: #9a3412; padding: 10px; margin-bottom: 12px; font-weight: 800; }
    @media (max-width: 900px) { .grid, .detail { grid-template-columns: 1fr; } .topbar { align-items: stretch; flex-direction: column; } }
  `)
})

adminRouter.get('/login', (request, response) => {
  response.send(layout({
    title: 'Admin Login',
    body: `<section class="panel" style="max-width:420px">
      ${request.query.error ? '<p class="error">Invalid login or too many attempts. Try again shortly.</p>' : ''}
      <form method="post" action="/admin/login">
        <label>Email<input name="email" type="email" autocomplete="username" required></label><br>
        <label>Password<input name="password" type="password" autocomplete="current-password" required></label><br>
        <button class="primary" type="submit">Sign In</button>
      </form>
    </section>`,
  }))
})

adminRouter.post('/login', async (request, response) => {
  if (!checkLoginRateLimit(request)) {
    response.redirect('/admin/login?error=1')
    return
  }

  const admin = await verifyPassword(String(request.body.email ?? ''), String(request.body.password ?? ''))
  if (!admin) {
    response.redirect('/admin/login?error=1')
    return
  }

  clearLoginRateLimit(request)
  await createAdminSession(response, admin.id)
  response.redirect('/admin/licenses')
})

adminRouter.post('/logout', requireAdmin, requireCsrf, async (request, response) => {
  await destroyAdminSession(request, response)
  response.redirect('/admin/login')
})

adminRouter.use(requireAdmin)

adminRouter.get('/', (_request, response) => response.redirect('/admin/licenses'))

adminRouter.get('/licenses', async (request, response) => {
  const query = String(request.query.q ?? '').trim()
  const status = String(request.query.status ?? 'all') as LicenseStatus | 'all'
  const where: Prisma.LicenseWhereInput = {}

  if (status !== 'all') where.status = status
  if (query) {
    where.OR = [
      { licenseKey: { contains: query, mode: 'insensitive' } },
      { customer: { fullName: { contains: query, mode: 'insensitive' } } },
      { customer: { email: { contains: query, mode: 'insensitive' } } },
      { customer: { companyName: { contains: query, mode: 'insensitive' } } },
      { order: { stripeCheckoutSessionId: { contains: query, mode: 'insensitive' } } },
      { order: { stripePaymentId: { contains: query, mode: 'insensitive' } } },
    ]
  }

  const licenses = await prisma.license.findMany({
    where,
    include: { customer: true, order: true },
    orderBy: { createdAt: 'desc' },
    take: 200,
  })

  response.send(layout({
    title: 'Licenses',
    admin: adminUser(request),
    csrfToken: csrf(request),
    body: `<section class="panel">
      <form class="toolbar" method="get" action="/admin/licenses">
        <label style="min-width:300px">Search
          <input name="q" value="${escapeHtml(query)}" placeholder="Name, email, company, license, Stripe ID">
        </label>
        <label>Status
          <select name="status">${licenseStatusOptions(status)}</select>
        </label>
        <button class="button" type="submit">Search</button>
        <a class="button primary" href="/admin/manual-license">Manual License</a>
      </form>
      <table>
        <thead><tr><th>Customer</th><th>Email</th><th>Company</th><th>License</th><th>Status</th><th>Purchase Date</th><th>Amount</th><th>Email Status</th><th>Actions</th></tr></thead>
        <tbody>${licenses.map((license) => `<tr>
          <td>${escapeHtml(license.customer.fullName || '-')}</td>
          <td>${escapeHtml(license.customer.email || '-')}</td>
          <td>${escapeHtml(license.customer.companyName || '-')}</td>
          <td><code>${escapeHtml(shortKey(license.licenseKey))}</code></td>
          <td>${statusBadge(license.status)}</td>
          <td>${dateTime(license.order?.purchaseDate)}</td>
          <td>${dollars(license.order?.purchaseAmount, license.order?.currency)}</td>
          <td>${statusBadge(license.emailStatus)}</td>
          <td><a class="button" href="/admin/licenses/${license.id}">View</a></td>
        </tr>`).join('')}</tbody>
      </table>
    </section>`,
  }))
})

adminRouter.get('/licenses/:id', async (request, response) => {
  const license = await prisma.license.findUnique({
    where: { id: routeId(request) },
    include: {
      customer: true,
      order: true,
      replacements: { orderBy: { createdAt: 'desc' } },
      replacedLicense: true,
      auditEvents: { orderBy: { createdAt: 'desc' }, take: 50, include: { admin: true } },
    },
  })
  if (!license) {
    response.status(404).send('License not found')
    return
  }

  const csrfInput = `<input type="hidden" name="_csrf" value="${escapeHtml(csrf(request))}">`
  response.send(layout({
    title: 'License Detail',
    admin: adminUser(request),
    csrfToken: csrf(request),
    body: `<div class="detail">
      <section class="panel">
        <h2>Customer Information</h2>
        <form method="post" action="/admin/licenses/${license.id}/customer">
          ${csrfInput}
          <div class="grid">
            <label>Full Name<input name="fullName" value="${escapeHtml(license.customer.fullName)}"></label>
            <label>Email<input name="email" type="email" value="${escapeHtml(license.customer.email)}"></label>
            <label>Company<input name="companyName" value="${escapeHtml(license.customer.companyName)}"></label>
          </div>
          <label>Admin Notes<textarea name="adminNotes">${escapeHtml(license.customer.adminNotes)}</textarea></label>
          <button class="primary" type="submit">Save Customer</button>
        </form>
      </section>
      <section class="panel">
        <h2>Purchase Information</h2>
        <dl>
          <dt>Stripe Session</dt><dd>${escapeHtml(license.order?.stripeCheckoutSessionId || '-')}</dd>
          <dt>Stripe Payment</dt><dd>${escapeHtml(license.order?.stripePaymentId || '-')}</dd>
          <dt>Stripe Customer</dt><dd>${escapeHtml(license.order?.stripeCustomerId || '-')}</dd>
          <dt>Amount</dt><dd>${dollars(license.order?.purchaseAmount, license.order?.currency)}</dd>
          <dt>Purchase Date</dt><dd>${dateTime(license.order?.purchaseDate)}</dd>
          <dt>Payment Status</dt><dd>${escapeHtml(license.order?.paymentStatus || '-')}</dd>
        </dl>
      </section>
      <section class="panel">
        <h2>License Information</h2>
        <dl>
          <dt>Product</dt><dd>${escapeHtml(license.product)}</dd>
          <dt>Status</dt><dd>${statusBadge(license.status)}</dd>
          <dt>Created</dt><dd>${dateTime(license.createdAt)}</dd>
          <dt>Updated</dt><dd>${dateTime(license.updatedAt)}</dd>
          <dt>Replaced License</dt><dd>${license.replacedLicense ? `<a href="/admin/licenses/${license.replacedLicense.id}">${escapeHtml(shortKey(license.replacedLicense.licenseKey))}</a>` : '-'}</dd>
        </dl>
        <label>Current License Key<textarea readonly>${escapeHtml(license.licenseKey)}</textarea></label>
        <div class="actions">
          <form method="post" action="/admin/licenses/${license.id}/resend">${csrfInput}<button type="submit">Resend Email</button></form>
          <form method="post" action="/admin/licenses/${license.id}/replace">${csrfInput}<button type="submit">Regenerate / Replace</button></form>
          <form method="post" action="/admin/licenses/${license.id}/disable">${csrfInput}<button type="submit">Disable</button></form>
          <form method="post" action="/admin/licenses/${license.id}/enable">${csrfInput}<button type="submit">Re-enable</button></form>
          <form method="post" action="/admin/licenses/${license.id}/archive">${csrfInput}<button class="danger" type="submit">Archive</button></form>
        </div>
      </section>
      <section class="panel">
        <h2>Fulfillment</h2>
        <dl>
          <dt>Email Status</dt><dd>${statusBadge(license.emailStatus)}</dd>
          <dt>Email Sent</dt><dd>${dateTime(license.emailSentAt)}</dd>
          <dt>Last Email Error</dt><dd>${escapeHtml(license.lastEmailError || '-')}</dd>
        </dl>
        <h3>Replacement History</h3>
        ${license.replacements.length ? `<ul>${license.replacements.map((replacement) => `<li><a href="/admin/licenses/${replacement.id}">${escapeHtml(shortKey(replacement.licenseKey))}</a> ${statusBadge(replacement.status)} ${dateTime(replacement.createdAt)}</li>`).join('')}</ul>` : '<p class="muted">No replacement licenses.</p>'}
      </section>
    </div>
    <section class="panel" style="margin-top:16px">
      <h2>Audit History</h2>
      <table><thead><tr><th>Time</th><th>Action</th><th>Admin</th><th>Metadata</th></tr></thead>
      <tbody>${license.auditEvents.map((event) => `<tr>
        <td>${dateTime(event.createdAt)}</td>
        <td>${escapeHtml(event.action)}</td>
        <td>${escapeHtml(event.admin?.email || 'system')}</td>
        <td><code>${escapeHtml(JSON.stringify(event.metadata ?? {}))}</code></td>
      </tr>`).join('')}</tbody></table>
    </section>`,
  }))
})

adminRouter.post('/licenses/:id/customer', requireCsrf, async (request, response) => {
  const license = await prisma.license.findUnique({ where: { id: routeId(request) } })
  if (!license) {
    response.status(404).send('License not found')
    return
  }

  await prisma.customer.update({
    where: { id: license.customerId },
    data: {
      fullName: String(request.body.fullName || '').trim() || null,
      email: String(request.body.email || '').trim().toLowerCase() || null,
      companyName: String(request.body.companyName || '').trim() || null,
      adminNotes: String(request.body.adminNotes || '').trim() || null,
    },
  })
  await audit('customer_information_edited', { adminId: request.admin?.id, customerId: license.customerId, licenseId: license.id })
  response.redirect(`/admin/licenses/${license.id}`)
})

async function licenseAction(request: Request, response: Response, status: LicenseStatus, action: string) {
  const license = await prisma.license.update({
    where: { id: routeId(request) },
    data: { status },
  })
  await audit(action, { adminId: request.admin?.id, customerId: license.customerId, orderId: license.orderId ?? undefined, licenseId: license.id })
  response.redirect(`/admin/licenses/${license.id}`)
}

adminRouter.post('/licenses/:id/disable', requireCsrf, (request, response) => licenseAction(request, response, 'disabled', 'license_disabled'))
adminRouter.post('/licenses/:id/enable', requireCsrf, (request, response) => licenseAction(request, response, 'active', 'license_re_enabled'))
adminRouter.post('/licenses/:id/archive', requireCsrf, (request, response) => licenseAction(request, response, 'archived', 'license_archived'))

adminRouter.post('/licenses/:id/resend', requireCsrf, async (request, response) => {
  const license = await prisma.license.findUnique({ where: { id: routeId(request) }, include: { customer: true } })
  if (!license) {
    response.status(404).send('License not found')
    return
  }
  await sendLicenseEmail({
    licenseId: license.id,
    customerEmail: license.customer.email,
    customerName: license.customer.fullName,
    licenseKey: license.licenseKey,
    adminId: request.admin?.id,
    resend: true,
  })
  response.redirect(`/admin/licenses/${license.id}`)
})

adminRouter.post('/licenses/:id/replace', requireCsrf, async (request, response) => {
  const previous = await prisma.license.findUnique({ where: { id: routeId(request) }, include: { customer: true } })
  if (!previous) {
    response.status(404).send('License not found')
    return
  }

  const issuedTo = previous.customer.fullName || previous.customer.email || 'Licensed User'
  const { licenseKey } = generateStackLogicLicenseKey({ issuedTo })
  const replacement = await prisma.$transaction(async (tx) => {
    await tx.license.update({ where: { id: previous.id }, data: { status: 'replaced' } })
    const created = await tx.license.create({
      data: {
        customerId: previous.customerId,
        orderId: previous.orderId,
        replacedLicenseId: previous.id,
        licenseKey,
        product: previous.product,
        status: 'active',
        source: 'replacement',
        emailStatus: 'pending',
      },
    })
    await tx.auditEvent.create({
      data: {
        action: 'license_replaced',
        adminId: request.admin?.id,
        customerId: previous.customerId,
        orderId: previous.orderId,
        licenseId: created.id,
        metadata: { replacedLicenseId: previous.id },
      },
    })
    return created
  })

  response.redirect(`/admin/licenses/${replacement.id}`)
})

adminRouter.get('/manual-license', (request, response) => {
  response.send(layout({
    title: 'Manual License',
    admin: adminUser(request),
    csrfToken: csrf(request),
    body: `<section class="panel" style="max-width:760px">
      <form method="post" action="/admin/manual-license">
        <input type="hidden" name="_csrf" value="${escapeHtml(csrf(request))}">
        <div class="grid">
          <label>Customer Full Name<input name="fullName" required></label>
          <label>Customer Email<input name="email" type="email"></label>
          <label>Company<input name="companyName"></label>
          <label>Reason / Type<input name="reason" placeholder="complimentary, replacement, test, offline sale"></label>
        </div>
        <label>Admin Notes<textarea name="adminNotes"></textarea></label>
        <button class="primary" type="submit">Create Manual License</button>
      </form>
    </section>`,
  }))
})

adminRouter.post('/manual-license', requireCsrf, async (request, response) => {
  const fullName = String(request.body.fullName || '').trim()
  const email = String(request.body.email || '').trim().toLowerCase() || null
  const companyName = String(request.body.companyName || '').trim() || null
  const reason = String(request.body.reason || '').trim() || 'manual'
  const adminNotes = String(request.body.adminNotes || '').trim() || null
  const { licenseKey } = generateStackLogicLicenseKey({ issuedTo: fullName || email || 'Licensed User' })

  const license = await prisma.$transaction(async (tx) => {
    const customer = email
      ? await tx.customer.upsert({
        where: { email },
        create: { fullName, email, companyName, adminNotes },
        update: { fullName: fullName || undefined, companyName: companyName || undefined, adminNotes: adminNotes || undefined },
      })
      : await tx.customer.create({ data: { fullName, companyName, adminNotes } })

    const createdLicense = await tx.license.create({
      data: {
        customerId: customer.id,
        licenseKey,
        product: licenseProductName,
        status: 'active',
        source: 'manual',
        emailStatus: email ? 'pending' : 'skipped',
        adminNotes: reason,
      },
    })

    await tx.auditEvent.create({
      data: {
        action: 'manual_license_created',
        adminId: request.admin?.id,
        customerId: customer.id,
        licenseId: createdLicense.id,
        metadata: { reason, adminNotes },
      },
    })
    return createdLicense
  })

  response.redirect(`/admin/licenses/${license.id}`)
})

export async function ensureInitialAdmin() {
  const email = process.env.ADMIN_INITIAL_EMAIL?.toLowerCase()
  const password = process.env.ADMIN_INITIAL_PASSWORD
  if (!email || !password) return

  const existing = await prisma.adminUser.findUnique({ where: { email } })
  if (existing) return

  await prisma.adminUser.create({
    data: {
      email,
      name: process.env.ADMIN_INITIAL_NAME || 'StackLogic Admin',
      passwordHash: await bcrypt.hash(password, 12),
    },
  })
}
