'use client';
import { formatErrorBanner } from '@/lib/api/toast-error';

import { useState, useEffect } from 'react';
import Link from 'next/link';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from '@/components/ui/select';
import { Switch } from '@/components/ui/switch';
import { Sheet, SheetContent, SheetHeader, SheetTitle, SheetFooter } from '@/components/ui/sheet';
import {
  AlertDialog,
  AlertDialogAction,
  AlertDialogCancel,
  AlertDialogContent,
  AlertDialogDescription,
  AlertDialogFooter,
  AlertDialogHeader,
  AlertDialogTitle,
} from '@/components/ui/alert-dialog';
import { PhoneInput, type PhoneInputValue } from '@/components/shared/phone-input';
import { useUIStore } from '@/stores/ui-store';
import { apiFetch } from '@/lib/api/client';
import { formatRole } from '@/lib/constants';

interface Role {
  id: string;
  name: string;
}

interface UserFormProps {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  user?: {
    userId: string;
    displayName: string;
    fullName?: string | null;
    firstName?: string | null;
    lastName?: string | null;
    email: string;
    phone: string | null;
    isActive: boolean;
    role: { id: string; name: string };
    residentialAccess?: boolean;
  } | null;
  onSuccess: () => void;
}

export function UserForm({ open, onOpenChange, user, onSuccess }: UserFormProps) {
  const [roles, setRoles] = useState<Role[]>([]);
  const [firstName, setFirstName] = useState('');
  const [lastName, setLastName] = useState('');
  const [email, setEmail] = useState('');
  const [originalEmail, setOriginalEmail] = useState('');
  const [emailConfirmOpen, setEmailConfirmOpen] = useState(false);
  const [password, setPassword] = useState('');
  const [displayName, setDisplayName] = useState('');
  const [phoneValue, setPhoneValue] = useState<PhoneInputValue | null>(null);
  const [roleId, setRoleId] = useState('');
  const [isActive, setIsActive] = useState(true);
  const [residentialAccess, setResidentialAccess] = useState(false);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);

  const portSlug = useUIStore((s) => s.currentPortSlug);
  const isEdit = !!user;
  const fullName = `${firstName} ${lastName}`.trim();

  useEffect(() => {
    if (open) {
      void apiFetch<{ data: Role[] }>('/api/v1/admin/roles').then((res) => setRoles(res.data));
    }
  }, [open]);

  useEffect(() => {
    if (open) {
      if (user) {
        // Prefer canonical first/last from the API; fall back to a best-
        // effort split of displayName for older records that pre-date the
        // first_name/last_name columns.
        const first = user.firstName ?? '';
        const last = user.lastName ?? '';
        if (first || last) {
          setFirstName(first);
          setLastName(last);
        } else if (user.fullName) {
          const parts = user.fullName.split(/\s+/);
          setFirstName(parts[0] ?? '');
          setLastName(parts.slice(1).join(' '));
        } else {
          const parts = user.displayName.split(/\s+/);
          setFirstName(parts[0] ?? '');
          setLastName(parts.slice(1).join(' '));
        }
        setEmail(user.email);
        setOriginalEmail(user.email);
        setDisplayName(user.displayName);
        setPhoneValue(user.phone ? { e164: user.phone, country: 'US' } : null);
        setRoleId(user.role.id);
        setIsActive(user.isActive);
        setResidentialAccess(user.residentialAccess ?? false);
        setPassword('');
      } else {
        setFirstName('');
        setLastName('');
        setEmail('');
        setOriginalEmail('');
        setDisplayName('');
        setPhoneValue(null);
        setRoleId('');
        setIsActive(true);
        setResidentialAccess(false);
        setPassword('');
      }
      setError(null);
    }
  }, [open, user]);

  function handleSubmit(e: React.FormEvent) {
    e.preventDefault();
    // Admin email change for an existing user goes through a confirmation
    // dialog because it locks the original sign-in identity out — the
    // submit path runs after the admin acknowledges. New-user creation
    // and same-email saves go straight through.
    if (isEdit && email.trim().toLowerCase() !== originalEmail.toLowerCase()) {
      setEmailConfirmOpen(true);
      return;
    }
    void persist();
  }

  async function persist() {
    setError(null);
    setLoading(true);
    const phoneE164 = phoneValue?.e164 ?? null;

    try {
      if (isEdit) {
        const emailChanged = email.trim().toLowerCase() !== originalEmail.toLowerCase();
        await apiFetch(`/api/v1/admin/users/${user.userId}`, {
          method: 'PATCH',
          body: {
            firstName: firstName || null,
            lastName: lastName || null,
            fullName: fullName || displayName,
            displayName,
            email: emailChanged ? email.trim() : undefined,
            phone: phoneE164,
            roleId,
            isActive,
            residentialAccess,
            notifyEmailChange: emailChanged ? true : undefined,
          },
        });
      } else {
        await apiFetch('/api/v1/admin/users', {
          method: 'POST',
          body: {
            name: fullName || displayName,
            firstName: firstName || null,
            lastName: lastName || null,
            email,
            password,
            displayName,
            phone: phoneE164 ?? undefined,
            roleId,
            residentialAccess,
          },
        });
      }
      onSuccess();
      onOpenChange(false);
    } catch (err: unknown) {
      const message = formatErrorBanner(err);
      setError(message);
    } finally {
      setLoading(false);
    }
  }

  return (
    <Sheet open={open} onOpenChange={onOpenChange}>
      <SheetContent className="overflow-y-auto">
        <SheetHeader>
          <SheetTitle>{isEdit ? 'Edit User' : 'New User'}</SheetTitle>
        </SheetHeader>

        <form onSubmit={handleSubmit} className="mt-6 space-y-4">
          <div className="grid grid-cols-2 gap-3">
            <div className="space-y-2">
              <Label htmlFor="user-first-name">First name</Label>
              <Input
                id="user-first-name"
                value={firstName}
                onChange={(e) => setFirstName(e.target.value)}
                placeholder="Jane"
                required
              />
            </div>
            <div className="space-y-2">
              <Label htmlFor="user-last-name">Last name</Label>
              <Input
                id="user-last-name"
                value={lastName}
                onChange={(e) => setLastName(e.target.value)}
                placeholder="Doe"
                required
              />
            </div>
          </div>

          <div className="space-y-2">
            <Label htmlFor="user-display-name">Display name</Label>
            <Input
              id="user-display-name"
              value={displayName}
              onChange={(e) => setDisplayName(e.target.value)}
              placeholder={fullName || 'Jane Doe'}
              required
            />
            <p className="text-xs text-muted-foreground">
              How this user appears across the app — usually their full name, but they can pick a
              nickname.
            </p>
          </div>

          <div className="space-y-2">
            <Label htmlFor="user-email">Email</Label>
            <Input
              id="user-email"
              type="email"
              value={email}
              onChange={(e) => setEmail(e.target.value)}
              placeholder="user@example.com"
              required
            />
            {isEdit && email.trim().toLowerCase() !== originalEmail.toLowerCase() ? (
              <p className="text-xs text-amber-600">
                You&apos;ll be asked to confirm — the original address will receive an automated
                notice that you, the admin, changed their sign-in email.
              </p>
            ) : isEdit ? (
              <p className="text-xs text-muted-foreground">
                Changing this address is an admin-only override; the user will be notified at the
                old address.
              </p>
            ) : null}
          </div>

          {!isEdit && (
            <div className="space-y-2">
              <Label htmlFor="user-password">Password</Label>
              <Input
                id="user-password"
                type="password"
                value={password}
                onChange={(e) => setPassword(e.target.value)}
                placeholder="Min 12 characters"
                minLength={12}
                required
              />
            </div>
          )}

          <div className="space-y-2">
            <Label htmlFor="user-phone">Phone</Label>
            <PhoneInput
              id="user-phone"
              value={phoneValue}
              onChange={setPhoneValue}
              placeholder="Phone number"
            />
          </div>

          <div className="space-y-2">
            <Label htmlFor="user-role">Role</Label>
            <Select value={roleId} onValueChange={setRoleId} required>
              <SelectTrigger id="user-role">
                <SelectValue placeholder="Select a role" />
              </SelectTrigger>
              <SelectContent>
                {roles.map((r) => (
                  <SelectItem key={r.id} value={r.id}>
                    {formatRole(r.name)}
                  </SelectItem>
                ))}
              </SelectContent>
            </Select>
          </div>

          <div className="flex items-center justify-between rounded-lg border p-3">
            <div>
              <Label htmlFor="user-residential">Residential access</Label>
              <p className="text-xs text-muted-foreground">
                Grant this user access to residential clients and interests in addition to their
                primary role.
              </p>
            </div>
            <Switch
              id="user-residential"
              checked={residentialAccess}
              onCheckedChange={setResidentialAccess}
            />
          </div>

          {isEdit && (
            <div className="flex items-center justify-between rounded-lg border p-3">
              <div>
                <Label htmlFor="user-active">Account active</Label>
                <p className="text-xs text-muted-foreground">Disabled users cannot sign in.</p>
              </div>
              <Switch id="user-active" checked={isActive} onCheckedChange={setIsActive} />
            </div>
          )}

          {isEdit && portSlug && (
            <div className="rounded-lg border bg-muted/30 p-3">
              <p className="text-sm font-medium">Fine-tuned permissions</p>
              <p className="text-xs text-muted-foreground">
                The selected role grants a baseline. To add or remove a specific permission for
                this user only, open the role &amp; permissions page.
              </p>
              <Link
                /* eslint-disable-next-line @typescript-eslint/no-explicit-any */
                href={`/${portSlug}/admin/roles?focusUser=${user.userId}` as any}
                className="mt-2 inline-block text-xs font-medium text-primary hover:underline"
              >
                Manage permissions →
              </Link>
            </div>
          )}

          {error && <p className="whitespace-pre-line text-sm text-destructive">{error}</p>}

          <SheetFooter>
            <Button
              type="button"
              variant="outline"
              onClick={() => onOpenChange(false)}
              disabled={loading}
            >
              Cancel
            </Button>
            <Button type="submit" disabled={loading || !displayName.trim() || !roleId}>
              {loading ? 'Saving...' : isEdit ? 'Save changes' : 'Create user'}
            </Button>
          </SheetFooter>
        </form>

        <AlertDialog open={emailConfirmOpen} onOpenChange={setEmailConfirmOpen}>
          <AlertDialogContent>
            <AlertDialogHeader>
              <AlertDialogTitle>Change this user&apos;s sign-in email?</AlertDialogTitle>
              <AlertDialogDescription>
                You&apos;re about to change <span className="font-medium">{originalEmail}</span> to{' '}
                <span className="font-medium">{email}</span>. From now on, they must sign in with
                the new address. The original address will receive an automated notification
                explaining that an administrator made the change.
              </AlertDialogDescription>
            </AlertDialogHeader>
            <AlertDialogFooter>
              <AlertDialogCancel disabled={loading}>Cancel</AlertDialogCancel>
              <AlertDialogAction
                onClick={(e) => {
                  e.preventDefault();
                  setEmailConfirmOpen(false);
                  void persist();
                }}
                disabled={loading}
              >
                Confirm change
              </AlertDialogAction>
            </AlertDialogFooter>
          </AlertDialogContent>
        </AlertDialog>
      </SheetContent>
    </Sheet>
  );
}
