// src/features/admin-user-detail/UserDetail.tsx
// Admin: user drill-down page - profile, activity, purchases, ratings, tickets, settings.

'use client';

import { useEffect, useState } from 'react';
import { cn } from '@/lib/cn';
import { getCsrfToken } from '@/lib/csrf';
import { useT, useLocale, LocaleProvider } from '@/lib/i18n/react';
import type { Locale } from '@/lib/i18n/index';
import { Button } from '@/components/ui/primitives/Button';
import { Stack } from '@/components/ui/layout/Stack';
import { Pill } from '@/components/ui/primitives/Pill';
import { AdminDetailPage, type TabDef } from '@/components/ui/domain/admin/AdminDetailPage';
import { AdminTable, type ColumnDef } from '@/components/ui/domain/admin/AdminTable';
import {
  AlertDialog,
  AlertDialogTrigger,
  AlertDialogContent,
  AlertDialogHeader,
  AlertDialogTitle,
  AlertDialogDescription,
  AlertDialogFooter,
  AlertDialogAction,
  AlertDialogCancel,
} from '@/components/ui/overlays/AlertDialog';
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogHeader,
  DialogTitle,
  DialogFooter,
} from '@/components/ui/overlays/Dialog';
import { Input } from '@/components/ui/primitives/Input';
import { Textarea } from '@/components/ui/primitives/Textarea';
import { Label } from '@/components/ui/primitives/Label';
import { FreezeDialog } from '@/components/ui/overlays/FreezeDialog';
import { captureCaught } from '@/lib/observability';
import { formatDate } from '@/lib/format';
import { formatAgorotLocale, formatShekelFloat } from '@/lib/money';
import { MetricTile } from '@/components/ui/domain/MetricTile';

// ─── Types ────────────────────────────────────────────────────────────────────

/** Serialised version of UserDetailUser (Dates → strings). */
export interface UserDetailUserData {
  id: string;
  displayName: string;
  avatarType: string;
  avatarValue: string;
  purchaseCount: number;
  accountState: string;
  isAdmin: boolean;
  createdAt: string;
  deletionRequestedAt: string | null;
  hasPhone: boolean;
  hasEmail: boolean;
}

/** Customer global LTV from GET /api/admin/users/[id] (`ltv` field). */
export interface UserDetailLtvData {
  netAgorot: number;
  orderCount: number;
  firstAt: string | null;
  lastAt: string | null;
}

export interface UserDetailPurchaseData {
  id: string;
  dealId: string;
  dealTitle: string;
  vendorId: string | null;
  quantity: number;
  amountPaid: string;
  paymentStatus: string;
  redemptionStatus: string | null;
  createdAt: string;
}

export interface UserDetailReviewData {
  id: string;
  vendorId: string;
  rating: number | null;
  body: string;
  reviewType: string;
  isVisible: boolean;
  createdAt: string;
}

export interface UserDetailTicketData {
  id: string;
  role: 'reporter' | 'target';
  targetType: string;
  targetId: string;
  reason: string;
  status: string;
  createdAt: string;
}

export interface UserDetailAdminActionData {
  id: string;
  adminId: string | null;
  action: string;
  note: string | null;
  createdAt: string;
}

export interface UserDetailProps {
  user: UserDetailUserData;
  /** When omitted, fetched client-side from GET /api/admin/users/[id]. */
  ltv?: UserDetailLtvData;
  purchases: UserDetailPurchaseData[];
  reviews: UserDetailReviewData[];
  tickets: UserDetailTicketData[];
  recentActions: UserDetailAdminActionData[];
  initialLocale: Locale;
}

const EMPTY_LTV: UserDetailLtvData = {
  netAgorot: 0,
  orderCount: 0,
  firstAt: null,
  lastAt: null,
};

// ─── Helpers ─────────────────────────────────────────────────────────────────

function InfoRow({ label, value }: { label: string; value: React.ReactNode }) {
  return (
    <div className="border-border-subtle grid grid-cols-2 gap-2 border-b py-2 last:border-0">
      <dt className="text-text-secondary text-sm">{label}</dt>
      <dd className="text-text-primary text-sm font-medium">{value ?? '—'}</dd>
    </div>
  );
}

function SectionTitle({ children }: { children: React.ReactNode }) {
  return <h2 className="text-text-primary mb-3 text-base font-semibold">{children}</h2>;
}

function Card({ children }: { children: React.ReactNode }) {
  return <div className="bg-surface-default rounded-2xl p-4 shadow-md">{children}</div>;
}

// ─── Component ────────────────────────────────────────────────────────────────

export function UserDetail({ initialLocale, ...props }: UserDetailProps) {
  return (
    <LocaleProvider locale={initialLocale}>
      <UserDetailInner {...props} />
    </LocaleProvider>
  );
}

function UserDetailInner({
  user: initialUser,
  ltv: ltvProp,
  purchases,
  reviews,
  tickets,
  recentActions,
}: Omit<UserDetailProps, 'initialLocale'>) {
  const t = useT('admin_user_detail');
  const tCommon = useT('common');
  const { locale } = useLocale();

  const [user, setUser] = useState<UserDetailUserData>(initialUser);
  const [fetchedLtv, setFetchedLtv] = useState<UserDetailLtvData | undefined>(undefined);
  const [ltvLoading, setLtvLoading] = useState(ltvProp === undefined);
  const [loading, setLoading] = useState<string | null>(null);
  const [error, setError] = useState<string | null>(null);

  const ltv = ltvProp ?? fetchedLtv ?? EMPTY_LTV;

  useEffect(() => {
    if (ltvProp !== undefined) return;

    let cancelled = false;
    void (async () => {
      try {
        const res = await fetch(`/api/admin/users/${user.id}`);
        if (!res.ok) return;
        const json = (await res.json().catch((err) => {
          captureCaught(err, {
            scope: 'features.admin-user-detail.UserDetail.ltv',
            severity: 'info',
          });
          return {};
        })) as { data?: { ltv?: UserDetailLtvData } };
        if (cancelled || !json.data?.ltv) return;
        setFetchedLtv({
          netAgorot: json.data.ltv.netAgorot,
          orderCount: json.data.ltv.orderCount,
          firstAt: json.data.ltv.firstAt,
          lastAt: json.data.ltv.lastAt,
        });
      } catch (err) {
        captureCaught(err, {
          scope: 'features.admin-user-detail.UserDetail.ltv',
          severity: 'warning',
        });
      } finally {
        if (!cancelled) setLtvLoading(false);
      }
    })();

    return () => {
      cancelled = true;
    };
  }, [user.id, ltvProp]);

  // Admin flag confirmation dialog
  const [adminFlagDialogOpen, setAdminFlagDialogOpen] = useState(false);
  const [adminFlagReason, setAdminFlagReason] = useState('');

  // Freeze / Unfreeze dialogs
  const [freezeDialogOpen, setFreezeDialogOpen] = useState(false);
  const [unfreezeDialogOpen, setUnfreezeDialogOpen] = useState(false);
  const [unfreezeReason, setUnfreezeReason] = useState('');

  // ── Admin flag toggle ─────────────────────────────────────────────────────

  async function handleAdminFlagToggle() {
    setLoading('admin_flag');
    setError(null);
    try {
      const res = await fetch(`/api/admin/users/${user.id}/admin-flag`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json', 'x-csrf-token': getCsrfToken() },
        body: JSON.stringify({
          isAdmin: !user.isAdmin,
          reason: adminFlagReason.trim() || undefined,
        }),
      });
      if (!res.ok) {
        const json = (await res.json().catch((err) => {
          captureCaught(err, { scope: 'features.admin-user-detail.UserDetail', severity: 'info' });
          return {};
        })) as Record<string, unknown>;
        throw new Error((json.error as string) || `HTTP ${res.status}`);
      }
      setUser((prev) => ({ ...prev, isAdmin: !prev.isAdmin }));
      setAdminFlagDialogOpen(false);
      setAdminFlagReason('');
    } catch (err) {
      setError(err instanceof Error ? err.message : String(err));
    } finally {
      setLoading(null);
    }
  }

  // ── Unfreeze ──────────────────────────────────────────────────────────────

  async function handleUnfreezeSubmit() {
    if (!unfreezeReason.trim()) return;
    setLoading('unfreeze');
    setError(null);
    try {
      const res = await fetch(`/api/admin/users/${user.id}/unfreeze`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json', 'x-csrf-token': getCsrfToken() },
        body: JSON.stringify({ reason: unfreezeReason.trim() }),
      });
      if (!res.ok) {
        const json = (await res.json().catch((err) => {
          captureCaught(err, { scope: 'features.admin-user-detail.UserDetail', severity: 'info' });
          return {};
        })) as Record<string, unknown>;
        throw new Error((json.error as string) || `HTTP ${res.status}`);
      }
      setUser((prev) => ({ ...prev, accountState: 'ACTIVE' }));
      setUnfreezeDialogOpen(false);
      setUnfreezeReason('');
    } catch (err) {
      setError(err instanceof Error ? err.message : String(err));
    } finally {
      setLoading(null);
    }
  }

  // ── State badge ───────────────────────────────────────────────────────────

  const stateToneMap: Record<string, 'success' | 'warning' | 'danger' | 'neutral'> = {
    ACTIVE: 'success',
    FROZEN: 'warning',
    DELETED_PENDING: 'danger',
    DELETED: 'neutral',
  };
  const stateLabelMap: Record<string, string> = {
    ACTIVE: t('state_active'),
    FROZEN: t('state_frozen'),
    DELETED_PENDING: t('state_deleted_pending'),
    DELETED: t('state_deleted'),
  };

  // ── Summary card (sidebar) ────────────────────────────────────────────────

  const summaryCard = (
    <Card>
      <Stack gap="3">
        <div>
          <p className="text-text-primary text-lg font-semibold" data-diag="" data-user-displayname>
            {user.displayName || '—'}
          </p>
          <p
            className="text-text-secondary font-mono text-xs"
            title={user.id}
            data-id={user.id}
            data-diag=""
          >
            {user.id.slice(0, 8)}…
          </p>
        </div>
        <div className="flex flex-wrap gap-2">
          <Pill tone={stateToneMap[user.accountState] ?? 'neutral'} size="sm">
            {stateLabelMap[user.accountState] ?? user.accountState}
          </Pill>
          {user.isAdmin && (
            <Pill tone="info" size="sm">
              {t('admin_badge')}
            </Pill>
          )}
        </div>
        <dl>
          <InfoRow label={t('field_purchase_count')} value={user.purchaseCount} />
          <InfoRow label={t('field_created_at')} value={formatDate(user.createdAt, locale)} />
          {user.deletionRequestedAt && (
            <InfoRow
              label={t('field_deletion_requested_at')}
              value={formatDate(user.deletionRequestedAt, locale)}
            />
          )}
        </dl>
        {error && (
          <p role="alert" className="text-danger-600 text-sm">
            {error}
          </p>
        )}
      </Stack>
    </Card>
  );

  // ── Tab: Profile ──────────────────────────────────────────────────────────

  const ltvSection = (
    <Card>
      <SectionTitle>{t('ltv_section_title')}</SectionTitle>
      <div
        className="grid grid-cols-2 gap-4 sm:grid-cols-4"
        data-ltv-net-agorot={ltv.netAgorot}
        data-ltv-order-count={ltv.orderCount}
        data-ltv-first-at={ltv.firstAt ?? ''}
        data-ltv-last-at={ltv.lastAt ?? ''}
      >
        <MetricTile
          label={t('ltv_net_spend')}
          value={formatAgorotLocale(ltv.netAgorot, locale)}
          loading={ltvLoading}
        />
        <MetricTile label={t('ltv_order_count')} value={ltv.orderCount} loading={ltvLoading} />
        <MetricTile
          label={t('ltv_first_purchase')}
          value={ltv.firstAt ? formatDate(ltv.firstAt, locale) : '—'}
          loading={ltvLoading}
        />
        <MetricTile
          label={t('ltv_last_purchase')}
          value={ltv.lastAt ? formatDate(ltv.lastAt, locale) : '—'}
          loading={ltvLoading}
        />
      </div>
    </Card>
  );

  const profileTab = (
    <Stack gap="4">
      {ltvSection}
      <Card>
        <SectionTitle>{t('tab_profile')}</SectionTitle>
        <dl>
          <InfoRow
            label={t('field_display_name')}
            value={user.displayName ? <span data-user-displayname>{user.displayName}</span> : '—'}
          />
          <InfoRow
            label={t('field_state')}
            value={
              <Pill tone={stateToneMap[user.accountState] ?? 'neutral'} size="sm">
                {stateLabelMap[user.accountState] ?? user.accountState}
              </Pill>
            }
          />
          <InfoRow
            label={t('field_is_admin')}
            value={
              <Pill tone={user.isAdmin ? 'info' : 'neutral'} size="sm">
                {user.isAdmin ? t('admin_badge') : t('not_admin_badge')}
              </Pill>
            }
          />
          <InfoRow label={t('field_purchase_count')} value={user.purchaseCount} />
          <InfoRow label={t('field_created_at')} value={formatDate(user.createdAt, locale)} />
          {user.deletionRequestedAt && (
            <InfoRow
              label={t('field_deletion_requested_at')}
              value={formatDate(user.deletionRequestedAt, locale)}
            />
          )}
          <InfoRow label={t('field_phone')} value={user.hasPhone ? t('pii_encrypted') : '—'} />
          <InfoRow label={t('field_email')} value={user.hasEmail ? t('pii_encrypted') : '—'} />
        </dl>
      </Card>
    </Stack>
  );

  // ── Tab: Activity (recent admin actions) ──────────────────────────────────

  const activityColumns: ColumnDef<UserDetailAdminActionData>[] = [
    {
      key: 'action',
      label: t('col_action'),
      render: (r) => (
        <span className="text-sm font-medium">
          {(t as (k: string) => string)(`action_${r.action}`) || r.action}
        </span>
      ),
    },
    {
      key: 'adminId',
      label: t('col_actor'),
      render: (r) => (
        <span className="text-text-secondary text-sm">{r.adminId ?? t('actor_system')}</span>
      ),
    },
    {
      key: 'note',
      label: t('col_note'),
      render: (r) => <span className="text-text-secondary text-sm">{r.note ?? '—'}</span>,
    },
    {
      key: 'createdAt',
      label: t('col_date'),
      render: (r) => formatDate(r.createdAt, locale),
    },
  ];

  const activityTab =
    recentActions.length === 0 ? (
      <p className="text-text-secondary py-8 text-center text-sm">{t('no_actions')}</p>
    ) : (
      <AdminTable<UserDetailAdminActionData>
        columns={activityColumns}
        rows={recentActions}
        loading={false}
      />
    );

  // ── Tab: Purchases ────────────────────────────────────────────────────────

  const purchasesColumns: ColumnDef<UserDetailPurchaseData>[] = [
    {
      key: 'dealTitle',
      label: t('col_deal'),
      render: (r) => (
        <a
          href={`/admin/deals/${r.dealId}`}
          className={cn(
            'text-primary-600 text-sm hover:underline',
            'focus-visible:ring-brand-primary-500 rounded focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none',
          )}
        >
          {r.dealTitle}
        </a>
      ),
    },
    {
      key: 'amountPaid',
      label: t('col_amount'),
      align: 'end',
      render: (r) => formatShekelFloat(r.amountPaid),
    },
    {
      key: 'paymentStatus',
      label: t('col_payment_status'),
      render: (r) => (
        <span className="text-text-secondary text-sm">
          {(t as (k: string) => string)(`payment_${r.paymentStatus}`) || r.paymentStatus}
        </span>
      ),
    },
    {
      key: 'redemptionStatus',
      label: t('col_redemption_status'),
      render: (r) => (
        <span className="text-text-secondary text-sm">
          {(t as (k: string) => string)(`redemption_${r.redemptionStatus}`) || r.redemptionStatus}
        </span>
      ),
    },
    {
      key: 'createdAt',
      label: t('col_date'),
      render: (r) => formatDate(r.createdAt, locale),
    },
  ];

  const purchasesTab =
    purchases.length === 0 ? (
      <p className="text-text-secondary py-8 text-center text-sm">{t('no_purchases')}</p>
    ) : (
      <AdminTable<UserDetailPurchaseData>
        columns={purchasesColumns}
        rows={purchases}
        loading={false}
      />
    );

  // ── Tab: Ratings ──────────────────────────────────────────────────────────

  const ratingsColumns: ColumnDef<UserDetailReviewData>[] = [
    {
      key: 'rating',
      label: t('col_rating'),
      align: 'center',
      render: (r) => (r.rating !== null ? `${r.rating}/5` : '—'),
    },
    {
      key: 'body',
      label: t('col_body'),
      render: (r) => <span className="text-text-secondary line-clamp-2 text-sm">{r.body}</span>,
    },
    {
      key: 'isVisible',
      label: t('col_visible'),
      align: 'center',
      render: (r) => (
        <Pill tone={r.isVisible ? 'success' : 'neutral'} size="sm">
          {r.isVisible ? t('visible_yes') : t('visible_no')}
        </Pill>
      ),
    },
    {
      key: 'createdAt',
      label: t('col_date'),
      render: (r) => formatDate(r.createdAt, locale),
    },
  ];

  const ratingsTab =
    reviews.length === 0 ? (
      <p className="text-text-secondary py-8 text-center text-sm">{t('no_reviews')}</p>
    ) : (
      <AdminTable<UserDetailReviewData> columns={ratingsColumns} rows={reviews} loading={false} />
    );

  // ── Tab: Tickets ──────────────────────────────────────────────────────────

  const ticketsColumns: ColumnDef<UserDetailTicketData>[] = [
    {
      key: 'role',
      label: t('col_role'),
      render: (r) => (
        <Pill tone={r.role === 'reporter' ? 'neutral' : 'warning'} size="sm">
          {r.role === 'reporter' ? t('role_reporter') : t('role_target')}
        </Pill>
      ),
    },
    {
      key: 'targetType',
      label: t('col_target_type'),
      render: (r) => (
        <span className="text-text-secondary text-sm">
          {(t as (k: string) => string)(`target_${r.targetType}`) || r.targetType}
        </span>
      ),
    },
    {
      key: 'reason',
      label: t('col_reason'),
      render: (r) => (
        <span className="text-text-secondary text-sm">
          {(t as (k: string) => string)(`reason_${r.reason}`) || r.reason}
        </span>
      ),
    },
    {
      key: 'status',
      label: t('col_status'),
      render: (r) => (
        <span className="text-text-secondary text-sm">
          {(t as (k: string) => string)(`report_status_${r.status}`) || r.status}
        </span>
      ),
    },
    {
      key: 'createdAt',
      label: t('col_date'),
      render: (r) => formatDate(r.createdAt, locale),
    },
  ];

  const ticketsTab =
    tickets.length === 0 ? (
      <p className="text-text-secondary py-8 text-center text-sm">{t('no_tickets')}</p>
    ) : (
      <AdminTable<UserDetailTicketData> columns={ticketsColumns} rows={tickets} loading={false} />
    );

  // ── Tab: Settings (freeze / unfreeze + admin flag) ────────────────────────

  const settingsTab = (
    <Card>
      <Stack gap="4">
        <SectionTitle>{t('tab_settings')}</SectionTitle>

        {/* Freeze / Unfreeze */}
        <div className="flex gap-3">
          {user.accountState !== 'FROZEN' ? (
            <Button
              variant="secondary"
              size="sm"
              disabled={
                loading !== null ||
                user.accountState === 'DELETED' ||
                user.accountState === 'DELETED_PENDING'
              }
              onClick={() => {
                setFreezeDialogOpen(true);
              }}
            >
              {t('freeze')}
            </Button>
          ) : (
            <Button
              variant="secondary"
              size="sm"
              disabled={loading !== null}
              onClick={() => {
                setUnfreezeReason('');
                setUnfreezeDialogOpen(true);
              }}
            >
              {t('unfreeze')}
            </Button>
          )}
        </div>

        {/* Admin flag toggle - wrapped in AlertDialog for confirmation */}
        <div>
          <AlertDialog open={adminFlagDialogOpen} onOpenChange={setAdminFlagDialogOpen}>
            <AlertDialogTrigger asChild>
              <Button
                variant={user.isAdmin ? 'danger' : 'secondary'}
                size="sm"
                disabled={loading !== null}
              >
                {user.isAdmin ? t('revoke_admin_confirm') : t('grant_admin_confirm')}
              </Button>
            </AlertDialogTrigger>
            <AlertDialogContent>
              <AlertDialogHeader>
                <AlertDialogTitle>
                  {user.isAdmin ? t('revoke_admin_title') : t('grant_admin_title')}
                </AlertDialogTitle>
                <AlertDialogDescription>
                  {user.isAdmin ? t('revoke_admin_desc') : t('grant_admin_desc')}
                </AlertDialogDescription>
              </AlertDialogHeader>
              <Stack gap="3" className="py-2">
                <div>
                  <Label htmlFor="admin-flag-reason">{t('admin_flag_reason_label')}</Label>
                  <Input
                    id="admin-flag-reason"
                    value={adminFlagReason}
                    onChange={(e) => setAdminFlagReason(e.target.value)}
                    placeholder={t('admin_flag_reason_placeholder')}
                  />
                </div>
              </Stack>
              <AlertDialogFooter>
                <AlertDialogAction
                  onClick={handleAdminFlagToggle}
                  disabled={loading === 'admin_flag'}
                >
                  {user.isAdmin ? t('revoke_admin_confirm') : t('grant_admin_confirm')}
                </AlertDialogAction>
                <AlertDialogCancel>{tCommon('cancel')}</AlertDialogCancel>
              </AlertDialogFooter>
            </AlertDialogContent>
          </AlertDialog>
        </div>
      </Stack>
    </Card>
  );

  // ── Tabs array ────────────────────────────────────────────────────────────

  const tabs: TabDef[] = [
    { key: 'profile', label: t('tab_profile'), content: profileTab },
    { key: 'activity', label: t('tab_activity'), content: activityTab },
    { key: 'purchases', label: t('tab_purchases'), content: purchasesTab },
    { key: 'ratings', label: t('tab_ratings'), content: ratingsTab },
    { key: 'tickets', label: t('tab_tickets'), content: ticketsTab },
    { key: 'settings', label: t('tab_settings'), content: settingsTab },
  ];

  return (
    <>
      <AdminDetailPage summary={summaryCard} tabs={tabs} defaultTab="profile" />

      {/* Freeze Dialog */}
      <FreezeDialog
        entityType="user"
        entityId={user.id}
        isOpen={freezeDialogOpen}
        onClose={() => setFreezeDialogOpen(false)}
        onSuccess={() => {
          setUser((prev) => ({ ...prev, accountState: 'FROZEN' }));
          setFreezeDialogOpen(false);
        }}
        title={t('freeze_dialog_title')}
        description={t('freeze_dialog_description')}
      />

      {/* Unfreeze Dialog */}
      <Dialog
        open={unfreezeDialogOpen}
        onOpenChange={(open) => {
          if (!open) {
            setUnfreezeDialogOpen(false);
            setUnfreezeReason('');
          }
        }}
      >
        <DialogContent>
          <DialogHeader>
            <DialogTitle>{t('unfreeze_dialog_title')}</DialogTitle>
            <DialogDescription>{t('unfreeze_dialog_description')}</DialogDescription>
          </DialogHeader>
          <Stack gap="4">
            <div>
              <Label htmlFor="unfreeze-reason">{t('reason_label')}</Label>
              <Textarea
                id="unfreeze-reason"
                rows={3}
                value={unfreezeReason}
                onChange={(e) => setUnfreezeReason(e.target.value)}
                placeholder={t('unfreeze_reason_placeholder')}
              />
            </div>
          </Stack>
          <DialogFooter>
            <Button
              variant="primary"
              loading={loading === 'unfreeze'}
              disabled={!unfreezeReason.trim()}
              onClick={handleUnfreezeSubmit}
            >
              {t('confirm_unfreeze')}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </>
  );
}
