'use client';

import { useEffect, useState } from 'react';
import type { Position, StoreMember, StoreRole } from '@alqove/api-client';
import { STORE_ROLE_LABEL, STORE_ROLE_RANK } from '@alqove/api-client';
import {
  Dialog,
  DialogContent,
  DialogFooter,
  DialogHeader,
  DialogTitle,
  DialogTrigger,
} from '@/components/ui/dialog';
import { useTerminateMember, useUpdateMember } from '@/lib/queries/use-team';
import { apiErrorMessage } from '@/lib/api-error';
import { assignableRoles } from './invite-member-dialog';

const cls = 'w-full rounded border border-forest/20 bg-white px-2 py-1.5 text-sm';

/**
 * Role / position / status editing for one roster row. Mirrors the server's
 * target-rank rules (Port 00 §2) so the UI doesn't offer what the API will
 * refuse: the owner is immutable, you only act on ranks below your own, and
 * rehire is owner-only. The server enforces all of it regardless.
 */
export function EditMemberDialog({
  storeId,
  member,
  actorRank,
  positions,
  trigger,
}: {
  storeId: string;
  member: StoreMember;
  actorRank: number;
  positions: Position[];
  trigger: React.ReactNode;
}) {
  const [open, setOpen] = useState(false);
  const [role, setRole] = useState<StoreRole>(member.role);
  const [positionId, setPositionId] = useState(member.default_position_id ?? '');
  const [confirmTerminate, setConfirmTerminate] = useState(false);

  useEffect(() => {
    // eslint-disable-next-line react-hooks/set-state-in-effect -- resyncing local form state when the dialog target changes
    setRole(member.role);
    setPositionId(member.default_position_id ?? '');
    setConfirmTerminate(false);
  }, [member, open]);

  const update = useUpdateMember();
  const terminate = useTerminateMember();

  const targetRank = STORE_ROLE_RANK[member.role];
  const isOwner = member.role === 'owner';
  const canAct = !isOwner && targetRank < actorRank;
  const isTerminated = member.status === 'terminated';
  const canRehire = isTerminated && actorRank >= STORE_ROLE_RANK.owner;
  const roles = assignableRoles(actorRank);

  const save = () =>
    update.mutate(
      {
        storeId,
        membershipId: member.id,
        input: {
          ...(role !== member.role ? { role } : {}),
          ...(positionId !== (member.default_position_id ?? '')
            ? { default_position_id: positionId || null }
            : {}),
        },
      },
      { onSuccess: () => setOpen(false) },
    );

  const rehire = () =>
    update.mutate(
      { storeId, membershipId: member.id, input: { status: 'active' } },
      { onSuccess: () => setOpen(false) },
    );

  const doTerminate = () =>
    terminate.mutate({ storeId, membershipId: member.id }, { onSuccess: () => setOpen(false) });

  const error = update.error ?? terminate.error;
  const busy = update.isPending || terminate.isPending;

  return (
    <Dialog open={open} onOpenChange={setOpen}>
      <DialogTrigger asChild>{trigger}</DialogTrigger>
      <DialogContent>
        <DialogHeader>
          <DialogTitle>{member.name ?? 'Team member'}</DialogTitle>
        </DialogHeader>

        {isOwner && (
          <p className="text-sm text-ink/60" data-testid="edit-owner-locked">
            The store owner&apos;s membership can&apos;t be changed.
          </p>
        )}
        {!isOwner && !canAct && (
          <p className="text-sm text-ink/60" data-testid="edit-rank-locked">
            You can only manage members ranked below you.
          </p>
        )}

        {canAct && (
          <div className="space-y-3">
            <Field label="Role">
              <select
                data-testid="edit-role"
                value={role}
                onChange={(e) => setRole(e.target.value as StoreRole)}
                className={cls}
                disabled={isTerminated}
              >
                {roles.map((r) => (
                  <option key={r} value={r}>
                    {STORE_ROLE_LABEL[r]}
                  </option>
                ))}
              </select>
            </Field>
            <Field label="Default position">
              <select
                data-testid="edit-position"
                value={positionId}
                onChange={(e) => setPositionId(e.target.value)}
                className={cls}
                disabled={isTerminated}
              >
                <option value="">None</option>
                {positions.map((p) => (
                  <option key={p.id} value={p.id}>
                    {p.name}
                  </option>
                ))}
              </select>
            </Field>

            {isTerminated && (
              <div className="rounded border border-forest/10 bg-bone/40 p-3 text-sm">
                <p className="text-ink/70">
                  This member was terminated
                  {member.terminated_at
                    ? ` on ${new Date(member.terminated_at).toLocaleDateString()}`
                    : ''}
                  .
                </p>
                {canRehire ? (
                  <button
                    type="button"
                    data-testid="edit-rehire"
                    onClick={rehire}
                    disabled={busy}
                    className="mt-2 rounded bg-forest px-3 py-1.5 text-sm font-semibold text-white hover:bg-forest/90 disabled:opacity-50"
                  >
                    {update.isPending ? 'Rehiring…' : 'Rehire'}
                  </button>
                ) : (
                  <p className="mt-1 text-xs text-ink/60">Only the store owner can rehire.</p>
                )}
              </div>
            )}

            {!isTerminated && (
              <div className="rounded border border-terracotta/30 bg-terracotta/5 p-3 text-sm">
                {!confirmTerminate ? (
                  <button
                    type="button"
                    data-testid="edit-terminate"
                    onClick={() => setConfirmTerminate(true)}
                    className="text-terracotta hover:underline"
                  >
                    Terminate membership…
                  </button>
                ) : (
                  <div className="flex items-center gap-3">
                    <span className="text-ink/80">Terminate this member?</span>
                    <button
                      type="button"
                      data-testid="edit-terminate-confirm"
                      onClick={doTerminate}
                      disabled={busy}
                      className="rounded bg-terracotta px-3 py-1 text-sm font-semibold text-white hover:bg-terracotta/90 disabled:opacity-50"
                    >
                      {terminate.isPending ? 'Terminating…' : 'Yes, terminate'}
                    </button>
                    <button
                      type="button"
                      onClick={() => setConfirmTerminate(false)}
                      className="text-sm text-ink/60 hover:underline"
                    >
                      Keep
                    </button>
                  </div>
                )}
              </div>
            )}

            {error && (
              <p className="text-sm text-terracotta" data-testid="edit-error">
                {apiErrorMessage(error, 'Failed to save changes.')}
              </p>
            )}
          </div>
        )}

        <DialogFooter>
          <button
            type="button"
            onClick={() => setOpen(false)}
            className="rounded px-3 py-1.5 text-sm text-ink/70 hover:bg-bone"
          >
            Close
          </button>
          {canAct && !isTerminated && (
            <button
              type="button"
              data-testid="edit-save"
              onClick={save}
              disabled={
                busy ||
                (role === member.role && positionId === (member.default_position_id ?? ''))
              }
              className="rounded bg-forest px-3 py-1.5 text-sm font-semibold text-white hover:bg-forest/90 disabled:opacity-50"
            >
              {update.isPending ? 'Saving…' : 'Save'}
            </button>
          )}
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}

function Field({ label, children }: { label: string; children: React.ReactNode }) {
  return (
    <label className="flex flex-col gap-1 text-sm">
      <span className="text-xs uppercase tracking-wide text-ink/60">{label}</span>
      {children}
    </label>
  );
}
