import Link from 'next/link'
import { createAdminClient } from '@/lib/supabase/admin'
import { companyHasAdmin, isCompanySchemaMissing } from '@/lib/data/companies'
import { companyRoleLabel } from '@/lib/domain/company'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { formatFullDate } from '@/lib/format'
import { DecisionForm } from './decision-form'
import type { Company, CompanyClaim } from '@/types/db'

/**
 * Corporate approval page (Task 90; article §17–§18). The link in the
 * "Approve company access request" email lands here. Mirrors the trip
 * invite page: token → expiry check → one decision, idempotent.
 *
 * Not a signed-in page: the corporate contact usually has no HeavyHaul
 * account. They identify themselves by name + email, which is recorded with
 * the decision (§18 "approver name/email recorded, IP and timestamp").
 */
export default async function CompanyApprovalPage({
  params,
  searchParams,
}: {
  params: Promise<{ token: string }>
  searchParams: Promise<{ decision?: string }>
}) {
  const { token } = await params
  const { decision } = await searchParams
  const admin = createAdminClient()

  const { data: claimRow, error } = await admin
    .from('company_claims')
    .select('*')
    .eq('approval_token', token)
    .maybeSingle()
  if (isCompanySchemaMissing(error)) {
    return (
      <Shell>
        <CardHeader className="text-center">
          <CardTitle>Company verification is not set up yet</CardTitle>
          <CardDescription>Database migration 0013 has not been applied.</CardDescription>
        </CardHeader>
      </Shell>
    )
  }
  const claim = (claimRow ?? null) as CompanyClaim | null
  if (!claim || isExpired(claim.expires_at)) {
    return (
      <Shell>
        <CardHeader className="text-center">
          <CardTitle>This approval link has expired</CardTitle>
          <CardDescription>
            Ask the person who requested access to resend the request from their HeavyHaul
            Agent settings.
          </CardDescription>
        </CardHeader>
      </Shell>
    )
  }

  const [{ data: companyRow }, { data: requester }] = await Promise.all([
    admin.from('companies').select('*').eq('id', claim.company_id).maybeSingle(),
    admin.from('profiles').select('full_name, email, phone').eq('id', claim.user_id).maybeSingle(),
  ])
  const company = (companyRow ?? null) as Company | null
  const decided = claim.decided_at && claim.claim_status !== 'pending_corporate_approval'
  const hasAdmin = await companyHasAdmin(claim.company_id)

  return (
    <Shell>
      <CardHeader className="text-center">
        <CardTitle className="text-xl">Company access request</CardTitle>
        <CardDescription>
          A user is requesting permission to represent your company inside HeavyHaul Agent.
          Approve only if this person is authorized to create trips, manage permit intake, and
          interact with carriers on behalf of your company.
        </CardDescription>
      </CardHeader>
      <CardContent className="space-y-5">
        <dl className="grid grid-cols-[auto_1fr] gap-x-4 gap-y-1.5 rounded-xl border bg-neutral-50 p-4 text-sm">
          <dt className="text-neutral-500">Name</dt>
          <dd className="font-semibold">{requester?.full_name || '—'}</dd>
          <dt className="text-neutral-500">Email</dt>
          <dd className="font-semibold">{requester?.email || '—'}</dd>
          <dt className="text-neutral-500">Phone</dt>
          <dd className="font-semibold">{requester?.phone || '—'}</dd>
          <dt className="text-neutral-500">Company</dt>
          <dd className="font-semibold">
            {company?.display_name ?? '—'}
            {claim.mc_number ? ` · MC ${claim.mc_number}` : ''}
          </dd>
          <dt className="text-neutral-500">Requested role</dt>
          <dd className="font-semibold">{companyRoleLabel(claim.requested_role, company?.company_type)}</dd>
          <dt className="text-neutral-500">Access level</dt>
          <dd className="font-semibold">Create trips, send intake links, request permits</dd>
          <dt className="text-neutral-500">Requested</dt>
          <dd>{formatFullDate(claim.created_at)}</dd>
        </dl>

        {decided ? (
          <p className="rounded-xl border p-4 text-center text-sm">
            This request was already{' '}
            <span className="font-semibold">
              {claim.claim_status === 'approved'
                ? 'approved'
                : claim.claim_status === 'rejected'
                  ? 'denied'
                  : claim.claim_status === 'admin_review_required'
                    ? 'sent to HeavyHaul Agent for review'
                    : claim.claim_status}
            </span>
            {claim.approver_name ? ` by ${claim.approver_name}` : ''}
            {claim.decided_at ? ` on ${formatFullDate(claim.decided_at)}` : ''}.
          </p>
        ) : hasAdmin ? (
          // §18: once a company has an admin, only that admin (signed in) decides.
          <div className="rounded-xl border border-amber-200 bg-amber-50 p-4 text-sm text-amber-900">
            <p className="font-semibold">This company already has a Company Admin in HeavyHaul Agent.</p>
            <p className="mt-1">
              Requests are approved from the admin&apos;s <Link href="/company" className="underline">Company Access</Link>{' '}
              panel, not from this link.
            </p>
          </div>
        ) : (
          <DecisionForm token={token} initialDecision={decision} companyName={company?.display_name ?? 'your company'} />
        )}
      </CardContent>
    </Shell>
  )
}

function Shell({ children }: { children: React.ReactNode }) {
  return (
    <main className="min-h-screen bg-neutral-50 px-4 py-12">
      <div className="mx-auto max-w-lg">
        <p className="mb-4 text-center text-sm text-neutral-500">
          <span className="font-semibold text-neutral-900">HeavyHaul Agent</span> · company verification
        </p>
        <Card>{children}</Card>
      </div>
    </main>
  )
}

function isExpired(iso: string): boolean {
  return new Date(iso).getTime() < Date.now()
}
