/**
 * AdminPage — /admin route (D-02: dedicated gated route, not SettingsSheet extension).
 *
 * Non-admin users are redirected to /calendar at the App.tsx route level (UX, D-03).
 * The server enforces 403 on every /api/admin/* request (Plan 03, requireAdmin).
 *
 * UI-SPEC §Surface 1 (/admin route):
 *   - "Admin Settings" heading (18px/600)
 *   - Centered content column, maxWidth 640px on desktop
 *   - var(--space-12) top/bottom padding, var(--space-6) horizontal padding
 *
 * UI-SPEC §Surface 2 (MEMBERS section):
 *   - 32px avatar swatch (var(--color-member-N)) + member name + credential status badge
 *   - "Rotate" or "Add credential" action button per hasCredential
 *   - Opens CredentialSheet in admin-rotate or admin-add mode
 *
 * UI-SPEC §Surface 5 (SHARED CALENDAR section):
 *   - Radio group, one row per synced calendar
 *   - "Currently shared" label on active selection
 *   - Two-tap Save (disabled until selection differs from saved)
 *   - Empty state when no calendars synced
 *
 * Security: client isAdmin gate is UX only. Server 403 is the real boundary (D-03).
 */

import { useState, useRef } from 'react';
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { CheckCircle, AlertCircle } from 'lucide-react';
import {
  fetchAdminMembers,
  fetchAdminCalendars,
  setSharedCalendar,
  type AdminMember,
  type AdminCalendar,
} from '../api/client.js';
import { CredentialSheet, type CredentialSheetMode } from '../components/CredentialSheet.js';

// ── Styles ─────────────────────────────────────────────────────────────────

const sectionLabelStyle: React.CSSProperties = {
  fontSize: 'var(--text-label-size, 13px)',
  fontWeight: 600,
  color: 'var(--color-text-muted)',
  textTransform: 'uppercase',
  letterSpacing: '0.06em',
  marginBottom: 'var(--space-2, 8px)',
};

// ── AdminPage ──────────────────────────────────────────────────────────────

export function AdminPage() {
  const queryClient = useQueryClient();

  // Credential sheet state
  const [sheetOpen, setSheetOpen] = useState(false);
  const [sheetMode, setSheetMode] = useState<CredentialSheetMode>('admin-add');
  const [sheetMember, setSheetMember] = useState<AdminMember | null>(null);
  const triggerRef = useRef<HTMLButtonElement>(null);

  // Shared calendar picker state
  const [selectedCalendarId, setSelectedCalendarId] = useState<number | null>(null);

  // Members query
  const membersQuery = useQuery({
    queryKey: ['admin', 'members'],
    queryFn: fetchAdminMembers,
    retry: false,
    staleTime: 60 * 1000,
  });

  // Calendars query
  const calendarsQuery = useQuery({
    queryKey: ['admin', 'calendars'],
    queryFn: fetchAdminCalendars,
    retry: false,
    staleTime: 60 * 1000,
  });

  // Derive current saved shared calendar id from the data
  const currentSharedId = calendarsQuery.data?.calendars.find((c) => c.isShared)?.id ?? null;

  // Effective selected = user pick OR fallback to current saved
  const effectiveSelected = selectedCalendarId ?? currentSharedId;

  // Save shared calendar mutation
  const sharedCalMutation = useMutation({
    mutationFn: (calId: number) => setSharedCalendar(calId),
    onSuccess: () => {
      void queryClient.invalidateQueries({ queryKey: ['admin', 'calendars'] });
      // Also invalidate events so the shared lane updates
      void queryClient.invalidateQueries({ queryKey: ['events'] });
      setSelectedCalendarId(null); // reset picker
    },
  });

  // Open credential sheet for a member
  function openSheet(member: AdminMember, buttonRef: React.RefObject<HTMLButtonElement | null>) {
    // Capture the button so focus can return on close
    (triggerRef as React.MutableRefObject<HTMLElement | null>).current = buttonRef.current;
    setSheetMember(member);
    setSheetMode(member.hasCredential ? 'admin-rotate' : 'admin-add');
    setSheetOpen(true);
  }

  const saveDisabled =
    sharedCalMutation.isPending ||
    effectiveSelected === null ||
    effectiveSelected === currentSharedId;

  return (
    <div
      style={{
        height: '100%',
        overflowY: 'auto',
        fontFamily: 'var(--font-family-base)',
        // Bottom padding to clear the 56px fixed tab bar on phone
        paddingBottom: 'calc(56px + env(safe-area-inset-bottom, 0px))',
      }}
    >
      <div
        style={{
          maxWidth: '640px',
          margin: '0 auto',
          padding: 'var(--space-12, 48px) var(--space-6, 24px)',
        }}
      >
        {/* Page heading */}
        <h1
          style={{
            margin: '0 0 var(--space-8, 32px) 0',
            fontSize: 'var(--text-heading-size, 18px)',
            fontWeight: 600,
            lineHeight: 'var(--text-heading-line-height, 1.25)',
            color: 'var(--color-text-primary)',
          }}
        >
          Admin Settings
        </h1>

        {/* ── MEMBERS section ─────────────────────────────────────────────── */}
        <section aria-label="Members" style={{ marginBottom: 'var(--space-8, 32px)' }}>
          <div style={sectionLabelStyle}>Members</div>

          {membersQuery.isLoading && (
            <div
              style={{
                padding: 'var(--space-4, 16px) 0',
                color: 'var(--color-text-muted)',
                fontSize: 'var(--text-body-size, 15px)',
              }}
            >
              Loading members…
            </div>
          )}

          {membersQuery.isError && (
            <div
              style={{
                color: 'var(--color-destructive)',
                fontSize: 'var(--text-body-size, 15px)',
                padding: 'var(--space-4, 16px) 0',
              }}
            >
              Could not load members.
            </div>
          )}

          {membersQuery.data && (
            <div>
              {membersQuery.data.members.map((member, idx) => (
                <MemberRow
                  key={member.id}
                  member={member}
                  colorIndex={idx}
                  onAction={(buttonRef) => openSheet(member, buttonRef)}
                />
              ))}
            </div>
          )}
        </section>

        {/* ── SHARED CALENDAR section ──────────────────────────────────────── */}
        <section aria-label="Shared Calendar">
          <div style={sectionLabelStyle}>Shared Calendar</div>

          <p
            style={{
              margin: '0 0 var(--space-4, 16px) 0',
              fontSize: 'var(--text-body-size, 15px)',
              fontWeight: 400,
              color: 'var(--color-text-secondary)',
              lineHeight: 1.5,
            }}
          >
            The shared family calendar is visible to all members in the same color lane.
          </p>

          {calendarsQuery.isLoading && (
            <div
              style={{
                color: 'var(--color-text-muted)',
                fontSize: 'var(--text-body-size, 15px)',
                padding: 'var(--space-2, 8px) 0',
              }}
            >
              Loading calendars…
            </div>
          )}

          {calendarsQuery.isError && (
            <div
              style={{
                color: 'var(--color-destructive)',
                fontSize: 'var(--text-body-size, 15px)',
                padding: 'var(--space-2, 8px) 0',
              }}
            >
              Could not load calendars.
            </div>
          )}

          {calendarsQuery.data && calendarsQuery.data.calendars.length === 0 && (
            <EmptyCalendarsState />
          )}

          {calendarsQuery.data && calendarsQuery.data.calendars.length > 0 && (
            <>
              <div
                role="radiogroup"
                aria-label="Select shared calendar"
                style={{ marginBottom: 'var(--space-4, 16px)' }}
              >
                {calendarsQuery.data.calendars.map((cal) => (
                  <CalendarRadioRow
                    key={cal.id}
                    calendar={cal}
                    isSelected={effectiveSelected === cal.id}
                    onSelect={() => setSelectedCalendarId(cal.id)}
                  />
                ))}
              </div>

              {/* Two-tap Save button */}
              <div style={{ display: 'flex', justifyContent: 'flex-end' }}>
                <button
                  type="button"
                  disabled={saveDisabled}
                  onClick={() => {
                    if (effectiveSelected !== null) {
                      sharedCalMutation.mutate(effectiveSelected);
                    }
                  }}
                  style={{
                    background: saveDisabled
                      ? 'var(--color-border, #E2E4E9)'
                      : 'var(--color-member-0, #4A90D9)',
                    color: '#ffffff',
                    border: 'none',
                    cursor: saveDisabled ? 'default' : 'pointer',
                    fontSize: 'var(--text-label-size, 13px)',
                    fontWeight: 600,
                    minHeight: '44px',
                    minWidth: '44px',
                    padding: '0 var(--space-6, 24px)',
                    borderRadius: 'var(--space-1, 4px)',
                    fontFamily: 'var(--font-family-base)',
                    transition: 'background 0.15s ease',
                  }}
                >
                  {sharedCalMutation.isPending ? 'Saving…' : 'Save'}
                </button>
              </div>

              {sharedCalMutation.isError && (
                <div
                  style={{
                    color: 'var(--color-destructive)',
                    fontSize: 'var(--text-label-size, 13px)',
                    marginTop: 'var(--space-2, 8px)',
                    textAlign: 'right',
                  }}
                >
                  Something went wrong. Please try again.
                </div>
              )}
            </>
          )}
        </section>
      </div>

      {/* Credential sheet — admin-rotate or admin-add */}
      {sheetMember && (
        <CredentialSheet
          isOpen={sheetOpen}
          onClose={() => setSheetOpen(false)}
          mode={sheetMode}
          memberName={sheetMember.displayName}
          memberId={sheetMember.id}
          triggerRef={triggerRef}
        />
      )}
    </div>
  );
}

// ── MemberRow ──────────────────────────────────────────────────────────────

interface MemberRowProps {
  member: AdminMember;
  colorIndex: number;
  onAction: (buttonRef: React.RefObject<HTMLButtonElement | null>) => void;
}

function MemberRow({ member, colorIndex, onAction }: MemberRowProps) {
  const buttonRef = useRef<HTMLButtonElement>(null);

  return (
    <div
      style={{
        display: 'flex',
        alignItems: 'center',
        gap: 'var(--space-3, 12px)',
        minHeight: '44px',
        padding: 'var(--space-2, 8px) 0',
        borderBottom: '1px solid var(--color-border-subtle, var(--color-border))',
      }}
    >
      {/* Avatar swatch */}
      <div
        aria-hidden="true"
        style={{
          width: '32px',
          height: '32px',
          borderRadius: '50%',
          background: `var(--color-member-${colorIndex}, var(--color-member-0))`,
          flexShrink: 0,
        }}
      />

      {/* Name + status */}
      <div style={{ flex: 1, minWidth: 0 }}>
        <div
          style={{
            fontSize: 'var(--text-body-size, 15px)',
            fontWeight: 400,
            color: 'var(--color-text-primary)',
            overflow: 'hidden',
            textOverflow: 'ellipsis',
            whiteSpace: 'nowrap',
          }}
        >
          {member.displayName ?? 'Member'}
        </div>

        {/* Credential status badge */}
        <div
          style={{
            display: 'flex',
            alignItems: 'center',
            gap: 'var(--space-1, 4px)',
            marginTop: '2px',
          }}
        >
          {member.hasCredential ? (
            <>
              <CheckCircle
                size={16}
                aria-hidden="true"
                style={{ color: 'var(--color-text-secondary)', flexShrink: 0 }}
              />
              <span
                style={{
                  fontSize: 'var(--text-label-size, 13px)',
                  color: 'var(--color-text-secondary)',
                }}
              >
                Credential set
              </span>
            </>
          ) : (
            <>
              <AlertCircle
                size={16}
                aria-hidden="true"
                style={{ color: 'var(--color-text-muted)', flexShrink: 0 }}
              />
              <span
                style={{
                  fontSize: 'var(--text-label-size, 13px)',
                  color: 'var(--color-text-muted)',
                }}
              >
                No credential
              </span>
            </>
          )}
        </div>
      </div>

      {/* Action button */}
      <button
        ref={buttonRef}
        type="button"
        onClick={() => onAction(buttonRef)}
        style={{
          background: 'none',
          border: '1px solid var(--color-border)',
          borderRadius: 'var(--space-1, 4px)',
          cursor: 'pointer',
          fontSize: 'var(--text-label-size, 13px)',
          fontWeight: 600,
          color: 'var(--color-text-primary)',
          minHeight: '44px',
          minWidth: '44px',
          padding: '0 var(--space-3, 12px)',
          fontFamily: 'var(--font-family-base)',
          flexShrink: 0,
        }}
      >
        {member.hasCredential ? 'Rotate' : 'Add credential'}
      </button>
    </div>
  );
}

// ── CalendarRadioRow ────────────────────────────────────────────────────────

interface CalendarRadioRowProps {
  calendar: AdminCalendar;
  isSelected: boolean;
  onSelect: () => void;
}

function CalendarRadioRow({ calendar, isSelected, onSelect }: CalendarRadioRowProps) {
  return (
    <div
      role="radio"
      aria-checked={isSelected}
      tabIndex={0}
      onClick={onSelect}
      onKeyDown={(e) => {
        if (e.key === 'Enter' || e.key === ' ') {
          e.preventDefault();
          onSelect();
        }
      }}
      style={{
        display: 'flex',
        alignItems: 'center',
        gap: 'var(--space-3, 12px)',
        minHeight: '44px',
        padding: 'var(--space-2, 8px) 0',
        cursor: 'pointer',
      }}
    >
      {/* Radio indicator: 20px circle */}
      <div
        aria-hidden="true"
        style={{
          width: '20px',
          height: '20px',
          borderRadius: '50%',
          flexShrink: 0,
          border: isSelected ? 'none' : '2px solid var(--color-border)',
          background: isSelected ? 'var(--color-member-0, #4A90D9)' : 'transparent',
          display: 'flex',
          alignItems: 'center',
          justifyContent: 'center',
        }}
      >
        {isSelected && (
          <div
            style={{
              width: '8px',
              height: '8px',
              borderRadius: '50%',
              background: '#ffffff',
            }}
          />
        )}
      </div>

      {/* Calendar name */}
      <span
        style={{
          fontSize: 'var(--text-body-size, 15px)',
          fontWeight: 400,
          color: 'var(--color-text-primary)',
          flex: 1,
        }}
      >
        {calendar.displayName}
      </span>

      {/* Currently shared label */}
      {calendar.isShared && (
        <span
          style={{
            fontSize: 'var(--text-label-size, 13px)',
            fontWeight: 400,
            color: 'var(--color-member-0, #4A90D9)',
          }}
        >
          Currently shared
        </span>
      )}
    </div>
  );
}

// ── EmptyCalendarsState ─────────────────────────────────────────────────────

function EmptyCalendarsState() {
  return (
    <div
      style={{
        padding: 'var(--space-8, 32px) 0',
        textAlign: 'center',
      }}
    >
      <div
        style={{
          fontSize: 'var(--text-body-size, 15px)',
          fontWeight: 600,
          color: 'var(--color-text-primary)',
          marginBottom: 'var(--space-2, 8px)',
        }}
      >
        No calendars synced yet
      </div>
      <div
        style={{
          fontSize: 'var(--text-label-size, 13px)',
          color: 'var(--color-text-secondary)',
          lineHeight: 1.5,
        }}
      >
        Calendars sync automatically. Check back after the first sync completes.
      </div>
    </div>
  );
}
