import 'server-only'

import { createAdminClient } from '@/lib/supabase/admin'
import { sendPlatformEmail } from '@/lib/email/send'
import { logTripEvent } from '@/lib/audit'
import { getCompanyContext } from '@/lib/data/companies'
import { SUPPORT_EMAIL } from '@/lib/app-url'
import { loadDocumentLocations, resolveDocumentUrl } from '@/lib/data/document-urls'
import {
  MAX_ATTACHMENT_BYTES, PERMIT_REQUEST_TEMPLATE, SYNCHRON_ORDER_EMAIL_DEFAULT, attachmentFileName, fitAttachments, permitRequestData, type AttachmentSummary, type RequesterInfo,
} from '@/lib/domain/permit-request-email'
import type { Permit, Trip, TripDocument, TripParticipant, TripUnit } from '@/types/db'

/**
 * Sends the permit request to Synchron Permits (Nash, 2026-09-23) with the
 * rate confirmation and the previous permit for that state attached, the
 * load / overall dimensions and the unit sheet in the body, and a copy to
 * the requester. Never throws into the request flow: the order is already
 * recorded; a failed email is logged on the trip.
 *
 * Recipient: SYNCHRON_ORDER_EMAIL, default synchronpermits@gmail.com.
 * Production AND development both deliver for real (Nash, 2026-09-23:
 * "allow production and development to send requests to this email, since
 * we already informed Synchron Permits that we'll be testing"). Point the
 * variable at a demo address (…@users.local) to stop delivery again.
 */
export function synchronOrderEmail(): string {
  return process.env.SYNCHRON_ORDER_EMAIL?.trim() || SYNCHRON_ORDER_EMAIL_DEFAULT
}

/** One email opens one Synchron order for a Workspace trip. Later state
 * requests reuse the same Workspace reference and must be added to that order. */
export async function sendInitialSynchronRequest(params: {
  trip: Trip
  rateCon: File
  rateConDocumentId: string
  brokerName: string
  brokerCompany: string
  dispatcherName: string
  dispatcherEmail: string
  dispatcherPhone: string
  payer: 'broker' | 'carrier' | null
  origin: string
}): Promise<{ status: string; reason?: string }> {
  const { trip } = params
  try {
    const [location] = await loadDocumentLocations([params.rateConDocumentId])
    const rateConUrl = location ? await resolveDocumentUrl(location, 60 * 60 * 24 * 7) : null
    if (!rateConUrl) throw new Error('The rate confirmation could not be shared with Synchron Permits')
    const attachments = params.rateCon.size <= MAX_ATTACHMENT_BYTES
      ? [{ name: attachmentFileName({ tripRef: trip.ref_code, label: 'rate confirmation', originalName: params.rateCon.name }), mimeType: params.rateCon.type || 'application/pdf', contentBase64: Buffer.from(await params.rateCon.arrayBuffer()).toString('base64') }]
      : []
    const to = synchronOrderEmail()
    const result = await sendPlatformEmail({
      templateKey: 'synchron_processing_request', to, userId: null,
      cc: params.dispatcherEmail.toLowerCase() === to.toLowerCase() ? [] : [params.dispatcherEmail],
      attachments,
      appendText: `Workspace trip reference: ${trip.ref_code}\nRate confirmation: ${rateConUrl}\nCreate or update exactly one Synchron order for this Workspace trip reference. Save the reference on your order and return it with every permit item.`,
      tags: { kind: 'synchron_processing_request', trip: trip.ref_code },
      data: {
        broker_name: params.brokerName, broker_company: params.brokerCompany,
        trip_id: trip.ref_code, pickup_location: trip.origin || 'Not yet extracted',
        delivery_location: trip.destination || 'Not yet extracted', load_number: trip.ref_code,
        carrier_company: trip.carrier_name, dispatcher_name: params.dispatcherName,
        dispatcher_email: params.dispatcherEmail, dispatcher_phone: params.dispatcherPhone,
        rate_confirmation_link: rateConUrl, workspace_link: `${params.origin}/trips/${trip.id}`,
        payment_responsible_party: params.payer || 'To be confirmed',
        route_inclusion_statement: 'Routes are included with Synchron-processed permits.',
        synchron_order_email: to, support_email: SUPPORT_EMAIL,
        created_datetime: new Date().toLocaleString('en-US', { timeZone: 'America/New_York' }) + ' ET',
      },
    })
    await logTripEvent({ tripId: trip.id, actorLabel: 'system', action: 'synchron_processing_request_emailed', detail: { email_status: result.status, rate_confirmation_document_id: params.rateConDocumentId, attachments: attachments.map((a) => a.name), ...(result.reason ? { reason: result.reason } : {}) } })
    return { status: result.status, reason: result.reason }
  } catch (error) {
    const reason = error instanceof Error ? error.message : String(error)
    await logTripEvent({ tripId: trip.id, actorLabel: 'system', action: 'synchron_processing_request_emailed', detail: { email_status: 'failed', reason } }).catch(() => undefined)
    return { status: 'failed', reason }
  }
}

interface FetchedFile extends AttachmentSummary { mimeType: string; contentBase64: string }

/**
 * Pulls one of THIS order's files out of storage and gives it a name Synchron
 * can read — "HH-KX9QG4 — NV permit 503912.pdf" rather than the raw storage
 * name (Nash, 2026-09-23).
 */
async function fetchDocument(doc: TripDocument, label: string, tripRef: string): Promise<FetchedFile | null> {
  const [loc] = await loadDocumentLocations([doc.id])
  const url = loc ? await resolveDocumentUrl(loc, 60 * 10) : null
  if (!url) return null
  const name = attachmentFileName({ tripRef, label, originalName: doc.file_name })
  const mimeType = doc.mime_type ?? (doc.file_name.toLowerCase().endsWith('.pdf') ? 'application/pdf' : 'application/octet-stream')
  try {
    const res = await fetch(url, { signal: AbortSignal.timeout(20_000) })
    if (!res.ok) return null
    const buf = Buffer.from(await res.arrayBuffer())
    if (buf.byteLength === 0 || buf.byteLength > MAX_ATTACHMENT_BYTES) return { name, label, sizeBytes: buf.byteLength, mimeType, contentBase64: '' }
    return { name, label, sizeBytes: buf.byteLength, mimeType, contentBase64: buf.toString('base64') }
  } catch {
    return null
  }
}

export async function sendPermitRequestToSynchron(params: {
  trip: Trip
  requestId: string
  stateCode: string
  replacedPermit: Permit | null
  participant: TripParticipant
  user: { id: string; email: string; name: string }
  payer: 'requester' | 'broker' | 'carrier' | null
  notes: string | null
  orderNumber: string | null
  origin: string
}): Promise<{ status: string; reason?: string; attachments: string[] }> {
  const admin = createAdminClient()
  const { trip } = params
  const stateCode = params.stateCode.toUpperCase()
  try {
    // 1. the unit sheet, the previous permit for that state, the rate confirmation
    const [{ data: unitRow }, { data: permitRows }, { data: docRows }] = await Promise.all([
      admin.from('trip_units').select('*').eq('trip_id', trip.id).maybeSingle(),
      admin.from('permits').select('*').eq('trip_id', trip.id).eq('state_code', stateCode).order('created_at', { ascending: false }),
      admin.from('documents').select('*').eq('trip_id', trip.id).order('created_at', { ascending: false }),
    ])
    const unit = (unitRow ?? null) as TripUnit | null
    const permits = (permitRows ?? []) as Permit[]
    const previous = params.replacedPermit ?? permits[0] ?? null
    const docs = (docRows ?? []) as TripDocument[]
    const rateCon = docs.find((d) => d.kind === 'rate_confirmation') ?? null
    if (!rateCon) throw new Error('A rate confirmation is required before requesting permits')
    const [rateConLocation] = await loadDocumentLocations([rateCon.id])
    const rateConUrl = rateConLocation ? await resolveDocumentUrl(rateConLocation, 60 * 60 * 24 * 7) : null
    if (!rateConUrl) throw new Error('The rate confirmation could not be shared with Synchron Permits')
    // The permit PDF for the state being re-ordered: the exact permit clicked, else any
    // other permit on file for that same state (a row can lose its document link).
    const permitDoc =
      (previous?.document_id ? docs.find((d) => d.id === previous.document_id) : null) ??
      docs.find((d) => permits.some((p) => p.document_id === d.id)) ??
      null

    // 2. requester identity: participant → profile phone → their company
    const { data: prof } = await admin.from('profiles').select('phone, full_name').eq('id', params.user.id).maybeSingle()
    const ctx = await getCompanyContext(params.user.id).catch(() => null)
    const company = ctx?.membership?.status === 'approved' ? ctx.company : null
    const requester: RequesterInfo = {
      name: params.participant.name || params.user.name || params.user.email,
      email: params.user.email || params.participant.email,
      phone: params.participant.phone ? `${params.participant.phone}${params.participant.phone_ext ? ` ext. ${params.participant.phone_ext}` : ''}` : ((prof as { phone?: string | null } | null)?.phone ?? null),
      role: params.participant.role,
      company: company?.display_name ?? null,
      companyMc: company?.mc_number ?? null,
    }

    // 3. files
    const permitLabel = `${stateCode} permit${previous?.permit_number ? ` ${previous.permit_number}` : ''}`
    const fetched = (await Promise.all([
      rateCon ? fetchDocument(rateCon, 'rate confirmation', trip.ref_code) : null,
      permitDoc ? fetchDocument(permitDoc, permitLabel, trip.ref_code) : null,
    ])).filter((f): f is FetchedFile => !!f)
    const { kept, dropped } = fitAttachments(fetched.filter((f) => f.contentBase64))
    const tooBig = fetched.filter((f) => !f.contentBase64)

    const to = synchronOrderEmail()
    const data = permitRequestData({
      trip, unit, stateCode, previousPermit: previous, requester, payer: params.payer, notes: params.notes, orderNumber: params.orderNumber,
      attachments: kept, workspaceLink: `${params.origin}/trips/${trip.id}`, synchronEmail: to, rateConUrl,
    })
    if (dropped.length || tooBig.length) data.attachments_list += `\n- Not attached (too large for email): ${[...dropped, ...tooBig].map((f) => f.name).join(', ')} — open them from the workspace link.`

    // 4. send: transactional stream, Synchron + a copy to the requester
    const r = await sendPlatformEmail({
      templateKey: PERMIT_REQUEST_TEMPLATE, to, data, userId: null, actorUserId: params.user.id, origin: params.origin,
      cc: requester.email && requester.email.toLowerCase() !== to.toLowerCase() ? [requester.email] : [],
      attachments: kept.map((f) => ({ name: f.name, mimeType: f.mimeType, contentBase64: f.contentBase64 })),
      appendText: `Workspace trip reference: ${trip.ref_code}\nSynchron order token: ${params.orderNumber || 'not assigned yet'}\nRate confirmation: ${rateConUrl}\nAdd ${stateCode} to the existing Synchron order for this Workspace trip when one exists; do not create a second order.`,
      tags: { kind: 'permit_request', trip: trip.ref_code, state: stateCode, request: params.requestId },
    })
    await logTripEvent({
      tripId: trip.id, actorId: params.user.id, actorLabel: requester.name, action: 'permit_request_emailed',
      detail: { to, cc: requester.email, state_code: stateCode, request_id: params.requestId, email_status: r.status, attachments: kept.map((f) => f.name), not_attached: [...dropped, ...tooBig].map((f) => f.name), ...(r.reason ? { reason: r.reason } : {}) },
    })
    return { status: r.status, reason: r.reason, attachments: kept.map((f) => f.name) }
  } catch (e) {
    const reason = e instanceof Error ? e.message : String(e)
    await logTripEvent({ tripId: trip.id, actorId: params.user.id, actorLabel: params.participant.name || params.user.email, action: 'permit_request_emailed', detail: { state_code: stateCode, request_id: params.requestId, email_status: 'failed', reason } }).catch(() => undefined)
    return { status: 'failed', reason, attachments: [] }
  }
}
