'use client'

import { useState } from 'react'
import Link from 'next/link'
import { useRouter } from 'next/navigation'
import { toast } from 'sonner'
import { Badge } from '@/components/ui/badge'
import { Button } from '@/components/ui/button'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { Input } from '@/components/ui/input'
import { formatFullDate } from '@/lib/format'
import type { PlatformUser } from '@/lib/data/users'
import type { UserRole } from '@/types/db'

/**
 * Admin user management (2026-09-11).
 *
 * Requirement: "Add an admin user management panel with password reset and
 * the ability to change user roles."
 *
 * The list answers support's first question on a call — "what account are you
 * using, and can you even sign in?" Both actions are real: they are stored in
 * `auth_accounts`, take precedence over AUTH_USERS at sign-in, and end the
 * person's existing sessions.
 */

const ROLES: UserRole[] = ['broker', 'dispatcher', 'driver', 'admin']
const ROLE_LABEL: Record<UserRole, string> = {
  broker: 'Broker',
  dispatcher: 'Carrier / Dispatcher',
  driver: 'Driver',
  admin: 'Admin',
}

export function UsersConsole({
  users,
  meId,
  roleSwitchOn,
  accountsReady,
}: {
  users: PlatformUser[]
  meId: string
  /** AUTH_ROLE_SWITCH — worth flagging, it changes what a login can become. */
  roleSwitchOn: boolean
  /** Migration 0015 applied — without it neither action can be stored. */
  accountsReady: boolean
}) {
  const router = useRouter()
  const [query, setQuery] = useState('')
  const [selectedId, setSelectedId] = useState<string | null>(users[0]?.id ?? null)
  const [busy, setBusy] = useState(false)
  // The new password, shown once and then gone. Kept per person so switching
  // the selection never shows one user's password beside another's name.
  const [issued, setIssued] = useState<{ userId: string; username: string; password: string } | null>(null)
  const [customPassword, setCustomPassword] = useState('')
  // The role picked in the dropdown but not saved yet. Tied to one person, so
  // selecting someone else never carries an unsaved choice across.
  const [draftRole, setDraftRole] = useState<{ userId: string; role: UserRole } | null>(null)

  const term = query.trim().toLowerCase()
  const shown = term
    ? users.filter(
        (u) =>
          u.name.toLowerCase().includes(term) ||
          u.email.toLowerCase().includes(term) ||
          (u.username ?? '').toLowerCase().includes(term),
      )
    : users
  const selected = users.find((u) => u.id === selectedId) ?? null

  async function call(body: Record<string, unknown>) {
    setBusy(true)
    try {
      const res = await fetch('/api/admin/users', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(body),
      })
      const json = await res.json().catch(() => ({}))
      if (!res.ok) {
        toast.error(json.error ?? 'Action failed')
        return null
      }
      router.refresh()
      return json
    } finally {
      setBusy(false)
    }
  }

  const logins = users.filter((u) => u.hasLogin).length

  return (
    <div className="mt-6">
      {!accountsReady && (
        <div className="mb-4 rounded-xl border border-amber-300 bg-amber-50 p-4 text-sm text-amber-900">
          <span className="font-semibold">Password reset and role change are not active yet.</span>{' '}
          Apply <span className="font-mono">supabase/migrations/0015_auth_accounts.sql</span> in the
          Supabase SQL editor. Until then logins use AUTH_USERS exactly as before.
        </div>
      )}
      <div className="flex flex-wrap items-center justify-between gap-3">
        <p className="text-xs text-neutral-500">
          {users.length} people · {logins} can sign in
          {roleSwitchOn && (
            <span className="ml-2 rounded-full bg-amber-100 px-2 py-0.5 font-semibold text-amber-900">
              Pilot role switching is ON
            </span>
          )}
        </p>
        <Input
          value={query}
          onChange={(e) => setQuery(e.target.value)}
          placeholder="Search name, email or username"
          className="w-64"
        />
      </div>

      <div className="mt-4 grid gap-4 lg:grid-cols-[minmax(0,1fr)_360px]">
        {/* List */}
        <div className="overflow-x-auto rounded-2xl border bg-white">
          <table className="w-full min-w-[620px] text-sm">
            <thead>
              <tr className="border-b text-left text-[11px] font-bold uppercase tracking-wide text-neutral-500">
                <th className="px-4 py-3">Name</th>
                <th className="px-4 py-3">Role</th>
                <th className="px-4 py-3">Sign-in</th>
                <th className="px-4 py-3">Trips</th>
              </tr>
            </thead>
            <tbody>
              {shown.map((u) => (
                <tr
                  key={u.id}
                  onClick={() => setSelectedId(u.id)}
                  className={`cursor-pointer border-b last:border-0 transition hover:bg-neutral-50 ${
                    u.id === selectedId ? 'bg-neutral-50' : ''
                  }`}
                >
                  <td className="px-4 py-3">
                    <p className="font-semibold">{u.name}</p>
                    <p className="text-xs text-neutral-500">{u.email}</p>
                  </td>
                  <td className="px-4 py-3 text-xs">{ROLE_LABEL[u.role]}</td>
                  <td className="px-4 py-3">
                    {u.hasLogin ? (
                      <Badge variant="secondary">Has a login</Badge>
                    ) : (
                      <span
                        className="text-xs text-neutral-400"
                        title="Referenced by a trip but has no AUTH_USERS entry, so cannot sign in yet"
                      >
                        No login
                      </span>
                    )}
                  </td>
                  <td className="px-4 py-3 text-xs">{u.tripCount}</td>
                </tr>
              ))}
              {shown.length === 0 && (
                <tr>
                  <td colSpan={4} className="px-4 py-10 text-center text-neutral-500">
                    Nobody matches “{query}”.
                  </td>
                </tr>
              )}
            </tbody>
          </table>
        </div>

        {/* Detail */}
        {selected ? (
          <div className="space-y-4">
            <Card>
              <CardHeader>
                <CardTitle className="text-base">{selected.name}</CardTitle>
                <CardDescription>{selected.email}</CardDescription>
              </CardHeader>
              <CardContent className="space-y-3 text-sm">
                <Row label="Can sign in">
                  {selected.hasLogin ? (
                    <>
                      Yes — username <span className="font-mono">{selected.username}</span>
                    </>
                  ) : (
                    'No — no AUTH_USERS entry'
                  )}
                </Row>
                <Row label="Role">{ROLE_LABEL[selected.role]}</Row>
                {selected.company && <Row label="Company">{selected.company}</Row>}
                {selected.phone && <Row label="Phone">{selected.phone}</Row>}
                <Row label="Trips">{selected.tripCount}</Row>
                {selected.createdAt && (
                  <Row label="First seen">{formatFullDate(selected.createdAt)}</Row>
                )}
                <Row label="Company access">
                  {selected.company_membership ? (
                    <span className="flex flex-wrap items-center gap-2">
                      {selected.company_membership.companyName}
                      <Badge
                        variant={
                          selected.company_membership.status === 'approved' ? 'secondary' : 'outline'
                        }
                      >
                        {selected.company_membership.status}
                      </Badge>
                    </span>
                  ) : (
                    <span className="text-neutral-500">None</span>
                  )}
                </Row>
              </CardContent>
            </Card>

            <Card>
              <CardHeader>
                <CardTitle className="text-base">Support actions</CardTitle>
                <CardDescription>Every action here is recorded in the audit log.</CardDescription>
              </CardHeader>
              <CardContent className="space-y-4">
                <div className="space-y-1.5">
                  <p className="text-xs font-bold uppercase tracking-wide text-neutral-500">
                    Change role
                  </p>
                  {(() => {
                    // Picking a role only SELECTS it; "Save role" applies it.
                    // (It used to save the instant the dropdown changed, with
                    // no button — easy to miss, easy to trigger by accident.)
                    const draft = draftRole?.userId === selected.id ? draftRole.role : selected.role
                    const changed = draft !== selected.role
                    const demotingSelf = selected.id === meId && draft !== 'admin'
                    const locked = busy || !selected.hasLogin || !accountsReady
                    return (
                      <>
                        <div className="flex flex-wrap items-center gap-2">
                          <select
                            value={draft}
                            disabled={locked}
                            onChange={(e) =>
                              setDraftRole({ userId: selected.id, role: e.target.value as UserRole })
                            }
                            className="min-w-0 flex-1 rounded-lg border px-3 py-2 text-sm disabled:opacity-60"
                            aria-label={`Role for ${selected.name}`}
                          >
                            {ROLES.map((r) => (
                              <option key={r} value={r}>
                                {ROLE_LABEL[r]}
                              </option>
                            ))}
                          </select>
                          <Button
                            size="sm"
                            disabled={locked || !changed || demotingSelf}
                            onClick={async () => {
                              const json = await call({ op: 'role', user_id: selected.id, role: draft })
                              if (json) {
                                setDraftRole(null)
                                toast.success(json.note ?? `Saved — ${selected.name} is now ${ROLE_LABEL[draft]}`)
                              }
                            }}
                          >
                            {busy && changed ? 'Saving…' : 'Save role'}
                          </Button>
                          {changed && (
                            <Button
                              size="sm"
                              variant="ghost"
                              disabled={busy}
                              onClick={() => setDraftRole(null)}
                            >
                              Cancel
                            </Button>
                          )}
                        </div>
                        {changed && !demotingSelf && (
                          <p className="text-[11px] leading-relaxed text-amber-800">
                            Saving changes {selected.name} from {ROLE_LABEL[selected.role]} to{' '}
                            <span className="font-semibold">{ROLE_LABEL[draft]}</span>. They are signed out
                            everywhere and get the new role the next time they sign in.
                          </p>
                        )}
                        {demotingSelf && (
                          <p className="text-[11px] font-semibold text-red-700">
                            You cannot remove your own admin role. Ask another admin to do it.
                          </p>
                        )}
                      </>
                    )
                  })()}
                  {selected.roleOverridden && (
                    <p className="text-[11px] text-neutral-500">
                      Set by an admin — overrides the role in AUTH_USERS.
                    </p>
                  )}
                  {!selected.hasLogin && (
                    <p className="text-[11px] text-neutral-500">
                      No login — a role only matters for someone who can sign in.
                    </p>
                  )}
                  {selected.id === meId && !(draftRole?.userId === selected.id) && (
                    <p className="text-[11px] text-neutral-500">This is you.</p>
                  )}
                </div>

                {selected.company_membership && (
                  <div className="space-y-1.5">
                    <p className="text-xs font-bold uppercase tracking-wide text-neutral-500">
                      Company access
                    </p>
                    <div className="flex flex-wrap gap-2">
                      <Link
                        href="/admin/company-review"
                        className="rounded-lg border px-3 py-1.5 text-xs font-semibold hover:bg-neutral-50"
                      >
                        Open company review
                      </Link>
                      {selected.company_membership.status !== 'revoked' && (
                        <Button
                          size="sm"
                          variant="outline"
                          disabled={busy}
                          className="text-red-700"
                          onClick={async () => {
                            if (
                              !confirm(
                                `Remove ${selected.name}'s access to ${selected.company_membership!.companyName}?`,
                              )
                            )
                              return
                            const json = await call({
                              op: 'revoke_company',
                              membership_id: selected.company_membership!.membershipId,
                            })
                            if (json) toast.success('Company access removed')
                          }}
                        >
                          Remove company access
                        </Button>
                      )}
                    </div>
                  </div>
                )}

                <div className="space-y-2">
                  <p className="text-xs font-bold uppercase tracking-wide text-neutral-500">
                    Password
                  </p>
                  {!selected.hasLogin ? (
                    <p className="text-[11px] text-neutral-500">
                      No login to reset — add this person to AUTH_USERS first.
                    </p>
                  ) : (
                    <>
                      <p className="text-[11px] leading-relaxed text-neutral-600">
                        {selected.passwordSetAt
                          ? `Last set by an admin ${formatFullDate(selected.passwordSetAt)}.`
                          : 'Currently the password from AUTH_USERS.'}{' '}
                        A reset replaces it and signs them out everywhere.
                        {selected.id === meId && ' This is your own account — you will be signed out too.'}
                      </p>
                      <div className="flex flex-wrap gap-2">
                        <Button
                          size="sm"
                          disabled={busy || !accountsReady}
                          onClick={async () => {
                            if (!confirm(`Reset ${selected.name}'s password to a new temporary one?`)) return
                            const json = await call({ op: 'password_reset', user_id: selected.id })
                            if (json) {
                              setIssued({ userId: selected.id, username: json.username, password: json.password })
                              toast.success('Password reset')
                            }
                          }}
                        >
                          Generate a temporary password
                        </Button>
                      </div>
                      <form
                        onSubmit={async (e) => {
                          e.preventDefault()
                          if (!customPassword) return
                          if (!confirm(`Set ${selected.name}'s password to the one you typed?`)) return
                          const json = await call({
                            op: 'password_reset',
                            user_id: selected.id,
                            password: customPassword,
                          })
                          if (json) {
                            setIssued({ userId: selected.id, username: json.username, password: json.password })
                            setCustomPassword('')
                            toast.success('Password set')
                          }
                        }}
                        className="flex flex-wrap gap-2"
                      >
                        <Input
                          type="text"
                          autoComplete="new-password"
                          value={customPassword}
                          onChange={(e) => setCustomPassword(e.target.value)}
                          placeholder="…or type one (10+ characters, a letter and a number)"
                          disabled={busy || !accountsReady}
                          className="min-w-0 flex-1 text-sm"
                        />
                        <Button size="sm" variant="outline" type="submit" disabled={busy || !customPassword || !accountsReady}>
                          Set
                        </Button>
                      </form>
                      {issued && issued.userId === selected.id && (
                        <div className="rounded-lg border border-amber-300 bg-amber-50 p-3 text-xs text-amber-900">
                          <p className="font-semibold">Give these to the user now — the password will not be shown again.</p>
                          <p className="mt-2">
                            Username <span className="font-mono font-semibold">{issued.username}</span>
                          </p>
                          <p className="mt-1 flex flex-wrap items-center gap-2">
                            Password{' '}
                            <span className="rounded bg-white px-2 py-0.5 font-mono text-sm font-bold tracking-wide ring-1 ring-amber-200">
                              {issued.password}
                            </span>
                            <button
                              type="button"
                              onClick={() => {
                                navigator.clipboard.writeText(issued.password)
                                toast.success('Password copied')
                              }}
                              className="font-semibold underline"
                            >
                              Copy
                            </button>
                            <button
                              type="button"
                              onClick={() => setIssued(null)}
                              className="font-semibold underline"
                            >
                              Done — hide it
                            </button>
                          </p>
                        </div>
                      )}
                    </>
                  )}
                </div>
              </CardContent>
            </Card>
          </div>
        ) : (
          <div className="rounded-2xl border border-dashed p-10 text-center text-sm text-neutral-500">
            Select a person to see their account.
          </div>
        )}
      </div>
    </div>
  )
}

function Row({ label, children }: { label: string; children: React.ReactNode }) {
  return (
    <div className="flex flex-wrap items-start justify-between gap-3 border-b pb-2 last:border-0 last:pb-0">
      <span className="text-xs text-neutral-500">{label}</span>
      <span className="text-right text-sm font-medium">{children}</span>
    </div>
  )
}
