"use client";

import { Suspense, useMemo, useState } from "react";
import Link from "next/link";
import { AlertCircle, ArrowRight, Check, Copy, Crown, Globe, KeyRound, RefreshCw, UserPlus, X } from "lucide-react";
import { Alert, AlertDescription } from "@/components/ui/alert";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Card, CardAction, CardDescription, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog";
import { Field, FieldGroup, FieldLabel } from "@/components/ui/field";
import { InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput } from "@/components/ui/input-group";
import { Skeleton } from "@/components/ui/skeleton";
import { Spinner } from "@/components/ui/spinner";
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
import { DataTable } from "@/components/app/data-table";
import { SearchInput } from "@/components/app/filters";
import { FormErrorAlert, SelectField, TextField } from "@/components/app/form-fields";
import { ListPageSkeleton } from "@/components/app/page";
import { useAuth } from "../auth/auth-context";
import { unverifiedReason, useEmailVerified, VerifiedOnly } from "../auth/verified-only";
import { EmptyState, ErrorState, UnauthorizedState } from "../components/ui/page-states";
import StatusBadge from "../components/ui/status-badge";
import { formatDateTime } from "../lib/format";
import { useUnsavedChangesGuard } from "../lib/useUnsavedChangesGuard";
import { SampleBadge, TeachingEmptyState } from "../onboarding/teaching-empty-state";
import { SettingsFrame, SettingsShell } from "../settings/settings-layout";
import { departmentLabel, fallbackDepartmentOptions, roleLabel, useDepartments, useRoles, useTeamMemberForm, useTeamMembers, useTeamWorkspace } from "./useTeam";

export function TeamPage() {
  return <SettingsShell title="Team members">
    {/* useSearchParams (?new=1 from quick create) needs a Suspense boundary so the page can still be prerendered. */}
    <Suspense fallback={<ListPageSkeleton filters={0} />}><TeamWorkspace /></Suspense>
  </SettingsShell>;
}

function TeamWorkspace() {
  const { user, organization, can } = useAuth();
  const canView = can("users.view");
  const canCreate = can("users.create");
  const canToggle = can("users.deactivate");
  const team = useTeamMembers(canView);
  const roles = useRoles(canCreate);
  const departments = useDepartments(canView || canCreate);
  const verified = useEmailVerified();
  const workspace = useTeamWorkspace(canCreate, verified ? null : unverifiedReason("add team members"));

  const columns = useMemo(() => [
    {
      id: "name", accessorKey: "name", header: "Member", meta: { className: "min-w-56", mobile: "title" },
      cell: ({ row }) => {
        const member = row.original;
        return <div className="grid gap-0.5">
          <span className="flex flex-wrap items-center gap-1.5 font-medium">
            {member.name}
            {member.id === organization?.ownerId && <Badge variant="warning" title="Organization owner"><Crown /> Owner</Badge>}
            {member.id === user?.id && <span className="text-xs font-normal text-muted-foreground">(you)</span>}
            <SampleBadge record={member} />
          </span>
          <span className="text-xs text-muted-foreground">{member.email}</span>
        </div>;
      },
    },
    { id: "department", header: "Department", enableSorting: false, cell: ({ row }) => row.original.department ? departmentLabel(row.original.department, departments.departments) : <span className="text-muted-foreground">Not set</span> },
    {
      id: "roles", header: "Role", enableSorting: false,
      cell: ({ row }) => row.original.roles?.length
        ? <div className="flex flex-wrap gap-1">{row.original.roles.map((role) => <Badge key={role.id} variant="outline">{roleLabel(role)}</Badge>)}</div>
        : <span className="text-muted-foreground">No role</span>,
    },
    { id: "status", header: "Status", enableSorting: false, meta: { mobile: "badge" }, cell: ({ row }) => <StatusBadge status={row.original.is_active ? "active" : "inactive"} tone={row.original.is_active ? "success" : "neutral"} reason={row.original.is_active ? undefined : "Cannot sign in until reactivated"} /> },
    { id: "last_login_at", accessorKey: "last_login_at", header: "Last sign-in", cell: ({ row }) => <span className="whitespace-nowrap">{row.original.last_login_at ? formatDateTime(row.original.last_login_at) : <span className="text-muted-foreground">Never</span>}</span> },
    {
      id: "actions", header: () => <span className="sr-only">Actions</span>, enableSorting: false, meta: { align: "right" },
      cell: ({ row }) => <MemberToggle member={row.original} canToggle={canToggle} isOwner={row.original.id === organization?.ownerId} isSelf={row.original.id === user?.id} pending={team.pendingId === row.original.id} busy={Boolean(team.pendingId)} onToggle={team.setActive} />,
    },
  ], [organization?.ownerId, user?.id, departments.departments, canToggle, team.pendingId, team.setActive]);

  if (!canView) {
    return <SettingsFrame title="Team members">
      <Card className="py-0"><UnauthorizedState title="You do not have access to the team directory" permission="users.view" backHref="/settings" backLabel="Back to settings" /></Card>
    </SettingsFrame>;
  }

  const activeCount = team.members.filter((member) => member.is_active).length;
  // Only the signed-in person so far: teach what the team page is for below their own row.
  const soloOwner = !team.isLoading && !team.error && !team.search && team.total === 1 && team.members[0]?.id === user?.id;
  const initialLoad = team.isLoading && !team.members.length;
  const description = initialLoad
    ? `Loading members of ${organization?.name || "your organization"}…`
    : `${team.total} members in ${organization?.name || "your organization"}${team.lastPage > 1 ? "" : ` · ${activeCount} active`}. Only people in your organization can see its buyers, factories, and documents.`;
  const actions = canCreate
    ? <VerifiedOnly action="add team members"><Button size="sm" onClick={workspace.openForm}><UserPlus /> Add team member</Button></VerifiedOnly>
    : <Tooltip><TooltipTrigger asChild><span tabIndex={0}><Button size="sm" disabled><UserPlus /> Add team member</Button></span></TooltipTrigger><TooltipContent>Your role cannot add members. Ask an admin for the users.create permission.</TooltipContent></Tooltip>;

  return <SettingsFrame title="Team members" description={description} actions={actions}>
    {workspace.credentials && <CredentialsCallout credentials={workspace.credentials} onDismiss={workspace.dismissCredentials} />}

    <div className="flex flex-wrap items-center gap-3">
      <SearchInput value={team.search} onChange={team.setSearch} placeholder="Search name, email, department, or role" className="sm:w-80" />
      {team.lastPage > 1 && team.search && <span className="text-xs text-muted-foreground">Searching the {team.members.length} members on this page.</span>}
    </div>

    <DataTable
      columns={columns}
      data={team.visibleMembers}
      getRowId={(row) => String(row.id)}
      isLoading={initialLoad}
      isRefreshing={team.isLoading && team.members.length > 0}
      error={team.error}
      errorState={<ErrorState compact error={team.error} title="Team members could not be loaded" onRetry={team.refresh} />}
      emptyState={team.members.length
        ? <EmptyState filtered onClearFilters={() => team.setSearch("")} title="No members match that search" />
        : <EmptyState title="No team members yet" detail="Add merchandisers, QA/QC, and commercial staff so they can work in this organization." action={canCreate ? <VerifiedOnly action="add team members"><Button size="sm" onClick={workspace.openForm}><UserPlus /> Add team member</Button></VerifiedOnly> : null} />}
      pagination={team.pagination}
      onPageChange={(page) => team.setPage(page)}
      noun="members"
    />

    {soloOwner && <Card className="py-0"><TeachingEmptyState k="team" compact showSample={false} action={canCreate && <VerifiedOnly action="add team members"><Button size="sm" onClick={workspace.openForm}><UserPlus /> Add team member</Button></VerifiedOnly>} /></Card>}

    <p className="text-xs text-muted-foreground">Deactivated members are signed out immediately and cannot sign in. The organization owner and your own account cannot be deactivated. Times are shown in Asia/Dhaka.</p>

    {(can("portal.view") || can("portal.manage") || can("portal.invite")) && <div className="flex flex-wrap items-center gap-3 rounded-lg border bg-muted/30 px-4 py-3">
      <span className="grid size-9 shrink-0 place-items-center rounded-full bg-background text-muted-foreground"><Globe className="size-4" aria-hidden="true" /></span>
      <div className="grid min-w-0 flex-1 gap-0.5">
        <p className="text-sm font-medium">Looking for buyer or factory logins?</p>
        <p className="text-sm text-muted-foreground">Team members are your own staff. People at a buyer or a factory sign in to a separate portal and only see their own orders: turn it on in Portal access, then invite them from their buyer or factory page.</p>
      </div>
      <Button variant="outline" size="sm" asChild><Link href="/settings/portal">Portal access <ArrowRight /></Link></Button>
    </div>}

    {canCreate && <AddMemberDialog open={workspace.formOpen} onOpenChange={workspace.setFormOpen} roles={roles} departments={departments} onCreated={(result) => { workspace.handleCreated(result); team.refresh(); }} />}
  </SettingsFrame>;
}

function MemberToggle({ member, canToggle, isOwner, isSelf, pending, busy, onToggle }) {
  const reason = !canToggle ? "Your role cannot activate or deactivate members." : isOwner ? "The organization owner cannot be deactivated." : isSelf ? "You cannot deactivate your own account." : null;
  const label = member.is_active ? "Deactivate" : "Activate";

  if (reason) {
    return <Tooltip>
      <TooltipTrigger asChild><span tabIndex={0} className="inline-flex"><Button variant="ghost" size="sm" disabled>{label}</Button></span></TooltipTrigger>
      <TooltipContent>{reason}</TooltipContent>
    </Tooltip>;
  }

  return <Button variant="outline" size="sm" disabled={pending || busy} className={member.is_active ? "text-destructive hover:text-destructive" : undefined} onClick={() => onToggle(member, !member.is_active)}>
    {pending && <Spinner />} {label}
  </Button>;
}

// Stays until dismissed: the form is cleared after creating, so this is the only place the temporary password is shown.
function CredentialsCallout({ credentials, onDismiss }) {
  return <Card role="status" aria-label="New member sign-in details" className="gap-4 border-success/30 bg-success/5">
    <CardHeader>
      <CardTitle className="flex items-center gap-2 text-base"><KeyRound className="size-4 text-success" /> {credentials.name} can now sign in</CardTitle>
      <CardDescription>Share these details privately. The temporary password is not shown again after you dismiss this; they can change it under Settings, My profile.</CardDescription>
      <CardAction><Button variant="ghost" size="sm" onClick={onDismiss}><X /> Dismiss</Button></CardAction>
    </CardHeader>
    <CardContent className="grid gap-4 sm:grid-cols-2">
      <CopyField id="credential-email" label="Work email" value={credentials.email} />
      <CopyField id="credential-password" label="Temporary password" value={credentials.password} mono />
    </CardContent>
  </Card>;
}

function CopyField({ id, label, value, mono = false }) {
  const [copied, setCopied] = useState(false);
  const copy = async () => {
    try {
      await navigator.clipboard.writeText(value);
      setCopied(true);
      setTimeout(() => setCopied(false), 2000);
    } catch {
      setCopied(false);
    }
  };

  return <Field>
    <FieldLabel htmlFor={id}>{label}</FieldLabel>
    <InputGroup className="bg-background">
      <InputGroupInput id={id} value={value || ""} readOnly className={mono ? "font-mono" : undefined} onFocus={(event) => event.target.select()} />
      <InputGroupAddon align="inline-end">
        <InputGroupButton size="xs" onClick={copy} aria-label={`Copy ${label.toLowerCase()}`}>{copied ? <><Check /> Copied</> : <><Copy /> Copy</>}</InputGroupButton>
      </InputGroupAddon>
    </InputGroup>
  </Field>;
}

function AddMemberDialog({ open, onOpenChange, roles, departments, onCreated }) {
  const { form, submit, cancel } = useTeamMemberForm({ roles: roles.roles, onCreated });
  const { isSubmitting } = form.formState;
  const roleOptions = roles.roles.map((role) => ({ value: role.name, label: roleLabel(role) }));
  // What the chosen role may do, in the organization's own words (system roles come with a description).
  const chosenRole = form.watch("role");
  const roleDescription = roles.roles.find((role) => role.name === chosenRole)?.description || "";
  const activeDepartments = departments.departments.filter((department) => department.is_active);
  const departmentOptions = activeDepartments.length ? activeDepartments.map((department) => ({ value: department.key, label: department.name })) : fallbackDepartmentOptions;
  const rolesUnavailable = !roles.isLoading && (roles.error || !roles.roles.length);

  const guard = useUnsavedChangesGuard(open && form.formState.isDirty, { interceptLinks: false, message: "The new member's details have not been saved." });

  const close = async (next) => {
    if (!next && isSubmitting) return;
    if (!next && !(await guard.confirmDiscard())) return;
    if (!next) cancel();
    onOpenChange(next);
  };

  return <Dialog open={open} onOpenChange={close}>
    <DialogContent className="sm:max-w-lg">
      <form onSubmit={submit} className="grid gap-5" noValidate>
        <DialogHeader>
          <DialogTitle>Add team member</DialogTitle>
          <DialogDescription>They join your organization only. You will see a temporary password to share with them after adding.</DialogDescription>
        </DialogHeader>
        <FormErrorAlert form={form} />
        {rolesUnavailable && <Alert variant="destructive">
          <AlertCircle />
          <AlertDescription className="flex flex-wrap items-center gap-x-3 gap-y-2">
            <span>Roles could not be loaded{roles.error ? `: ${roles.error.message}` : "."} A member needs a role before they can be added.</span>
            <Button type="button" variant="outline" size="sm" onClick={roles.retry}><RefreshCw /> Retry</Button>
          </AlertDescription>
        </Alert>}
        <FieldGroup className="grid gap-5 sm:grid-cols-2">
          <TextField control={form.control} name="name" label="Full name" className="sm:col-span-2" inputProps={{ autoComplete: "off", autoFocus: true }} />
          <TextField control={form.control} name="email" label="Work email" type="email" description="Used to sign in. Must not already have an account." className="sm:col-span-2" inputProps={{ autoComplete: "off" }} />
          <SelectField control={form.control} name="department" label="Department" options={departmentOptions} description={departments.error ? "Custom departments could not be loaded; showing the standard ones." : undefined} />
          {roles.isLoading
            ? <Field><FieldLabel>Role</FieldLabel><Skeleton className="h-9 w-full" /></Field>
            : <SelectField control={form.control} name="role" label="Role" options={roleOptions} disabled={Boolean(rolesUnavailable)} placeholder={rolesUnavailable ? "Unavailable until roles load" : "Select a role"} description={roleDescription || "Decides what they can view, create, and approve."} />}
          <TextField control={form.control} name="password" label="Temporary password" type="password" description="Shown once after adding so you can share it; they can change it later." className="sm:col-span-2" inputProps={{ autoComplete: "new-password" }} />
        </FieldGroup>
        <DialogFooter>
          <Button type="button" variant="outline" disabled={isSubmitting} onClick={() => close(false)}>Cancel</Button>
          <Button type="submit" disabled={isSubmitting || roles.isLoading || Boolean(rolesUnavailable)}>{isSubmitting && <Spinner />} Add member</Button>
        </DialogFooter>
      </form>
    </DialogContent>
  </Dialog>;
}
