import { useState, type ReactNode } from 'react';
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { formatDate } from '@/lib/format';
import { useLocale, useT } from '@/lib/i18n/react';
import { Button } from '@/components/ui/primitives/Button';
import {
  AlertDialog,
  AlertDialogContent,
  AlertDialogHeader,
  AlertDialogTitle,
  AlertDialogDescription,
  AlertDialogFooter,
  AlertDialogAction,
  AlertDialogCancel,
} from '@/components/ui/overlays/AlertDialog';
import { Input } from '@/components/ui/primitives/Input';
import { NumberInput } from '@/components/ui/primitives/NumberInput';
import { AdminMoneyInput } from '@/components/ui/admin/AdminMoneyInput';
import { Textarea } from '@/components/ui/primitives/Textarea';
import { Label } from '@/components/ui/primitives/Label';
import { StatusBadge } from '@/components/ui/domain/StatusBadge';
import {
  Tooltip,
  TooltipContent,
  TooltipProvider,
  TooltipTrigger,
} from '@/components/ui/overlays/Tooltip';
import { formatAgorotShekels, formatAgorotSigned } from '@/lib/money';
import { getCsrfToken } from '@/lib/csrf';
import { HydratedIsland } from '@/components/HydratedIsland';
import { EmptyState } from '@/components/ui/feedback/EmptyState';
import {
  AffiliateLtvMarginValue,
  AffiliateTotalPayoutsValue,
  type AffiliateLtvData,
} from './affiliateLtvUi';

type AffiliateDetailData = {
  id: string;
  user_id: string;
  email: string | null;
  status: 'active' | 'suspended' | 'revoked';
  pct: number | null;
  enrolled_at: string;
  suspended_at: string | null;
  suspended_reason: string | null;
  stripe_account_id: string | null;
  stripe_status: string;
  stripe_payouts_enabled: boolean;
  pending_agorot: number | null;
  matured_agorot: number | null;
  carried_debt_agorot: number | null;
  ltv?: AffiliateLtvData;
};

type PayoutRow = {
  id: string;
  amountAgorot: number;
  status: string;
  createdAt: string;
};

type CommissionRow = {
  id: string;
  amountAgorot: number;
  dealTitle: string;
  createdAt: string;
};

type Props = {
  enrollmentId: string;
};

const AFFILIATE_STATUS_MAP = {
  active: { tone: 'success' as const, labelKey: 'status_active' },
  suspended: { tone: 'warning' as const, labelKey: 'status_suspended' },
  revoked: { tone: 'danger' as const, labelKey: 'status_revoked' },
};

function DetailLabel({ children, tooltip }: { children: ReactNode; tooltip?: string }) {
  if (!tooltip) {
    return <dt className="text-xs text-(--color-text-muted)">{children}</dt>;
  }
  return (
    <dt className="text-xs text-(--color-text-muted)">
      <Tooltip>
        <TooltipTrigger asChild>
          <span className="cursor-help border-b border-dotted border-(--color-border)">
            {children}
          </span>
        </TooltipTrigger>
        <TooltipContent>{tooltip}</TooltipContent>
      </Tooltip>
    </dt>
  );
}

function stripeStatusLabel(status: string, t: ReturnType<typeof useT<'admin_affiliates'>>): string {
  const key = `stripe_status_${status}` as Parameters<typeof t>[0];
  const translated = t(key);
  return translated === key ? status : translated;
}

function payoutStatusLabel(status: string, t: ReturnType<typeof useT<'admin_affiliates'>>): string {
  const key = `payout_status_${status}` as Parameters<typeof t>[0];
  const translated = t(key);
  return translated === key ? status : translated;
}

function AffiliateDetailInner({ enrollmentId }: Props) {
  const t = useT('admin_affiliates');
  const tCommon = useT('common');
  const { locale } = useLocale();
  const [revokeConfirmOpen, setRevokeConfirmOpen] = useState(false);
  const qc = useQueryClient();

  // ─── Main detail query ────────────────────────────────────────────────────
  const { data, isLoading } = useQuery<AffiliateDetailData>({
    queryKey: ['admin-affiliate', enrollmentId],
    queryFn: async () => {
      const res = await fetch(`/api/admin/affiliates/${enrollmentId}`);
      if (!res.ok) throw new Error(await res.text());
      const json = (await res.json()) as { data: AffiliateDetailData };
      return json.data;
    },
  });

  // ─── Status action mutation ───────────────────────────────────────────────
  const action = useMutation({
    mutationFn: async (payload: { action: string; reason?: string; pct?: number }) => {
      const res = await fetch(`/api/admin/affiliates/${enrollmentId}/action`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json', 'x-csrf-token': getCsrfToken() },
        body: JSON.stringify(payload),
      });
      if (!res.ok) throw new Error(await res.text());
      return res.json();
    },
    onSuccess: () => {
      void qc.invalidateQueries({ queryKey: ['admin-affiliate', enrollmentId] });
      void qc.invalidateQueries({ queryKey: ['admin-affiliates'] });
    },
  });

  // ─── Payout list query ────────────────────────────────────────────────────
  const { data: payouts, isLoading: payoutsLoading } = useQuery<PayoutRow[]>({
    queryKey: ['admin-affiliate-payouts', enrollmentId],
    queryFn: async () => {
      const res = await fetch(`/api/admin/affiliates/${enrollmentId}/payouts`);
      if (!res.ok) return [];
      const json = (await res.json()) as { data: PayoutRow[] };
      return json.data ?? [];
    },
  });

  // ─── Payout action mutation ───────────────────────────────────────────────
  const [payoutActionError, setPayoutActionError] = useState<string | null>(null);
  const payoutAction = useMutation({
    mutationFn: async ({
      payoutId,
      action: act,
    }: {
      payoutId: string;
      action: 'approve' | 'mark-paid';
    }) => {
      const res = await fetch(`/api/admin/affiliates/payouts/${payoutId}/${act}`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json', 'x-csrf-token': getCsrfToken() },
      });
      if (!res.ok) throw new Error(await res.text());
      return res.json();
    },
    onSuccess: () => {
      setPayoutActionError(null);
      void qc.invalidateQueries({ queryKey: ['admin-affiliate-payouts', enrollmentId] });
    },
    onError: (err) => setPayoutActionError(String(err)),
  });

  // ─── Commission edit ──────────────────────────────────────────────────────
  const [commissionDraft, setCommissionDraft] = useState<number | undefined>(undefined);
  const [commissionMsg, setCommissionMsg] = useState<string | null>(null);
  const commissionPct = commissionDraft ?? data?.pct ?? 0;
  const commissionMutation = useMutation({
    mutationFn: async (pct: number) => {
      const res = await fetch(`/api/admin/affiliates/${enrollmentId}/commission`, {
        method: 'PATCH',
        headers: { 'Content-Type': 'application/json', 'x-csrf-token': getCsrfToken() },
        body: JSON.stringify({ pct }),
      });
      if (!res.ok) throw new Error(await res.text());
      return res.json();
    },
    onSuccess: () => {
      setCommissionMsg(t('commission_success'));
      setCommissionDraft(undefined);
      void qc.invalidateQueries({ queryKey: ['admin-affiliate', enrollmentId] });
    },
    onError: () => setCommissionMsg(t('commission_error')),
  });

  // ─── Adjust balance ───────────────────────────────────────────────────────
  const [adjustAmount, setAdjustAmount] = useState<number>(0);
  const [adjustMemo, setAdjustMemo] = useState('');
  const [adjustMsg, setAdjustMsg] = useState<string | null>(null);
  const adjustMutation = useMutation({
    mutationFn: async ({ amountAgorot, memo }: { amountAgorot: number; memo: string }) => {
      if (!data?.user_id) throw new Error('no user_id');
      const res = await fetch('/api/admin/referrals/adjust', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json', 'x-csrf-token': getCsrfToken() },
        body: JSON.stringify({
          userId: data.user_id,
          amountAgorot,
          memo,
          idempotencyKey: crypto.randomUUID(),
        }),
      });
      if (!res.ok) throw new Error(await res.text());
      return res.json();
    },
    onSuccess: () => {
      setAdjustMsg(t('adjust_success'));
      setAdjustAmount(0);
      setAdjustMemo('');
      void qc.invalidateQueries({ queryKey: ['admin-affiliate', enrollmentId] });
    },
    onError: () => setAdjustMsg(t('adjust_error')),
  });

  // ─── Commission history query ─────────────────────────────────────────────
  const { data: commissionHistory, isLoading: commissionHistoryLoading } = useQuery<
    CommissionRow[]
  >({
    queryKey: ['admin-affiliate-commission-history', enrollmentId],
    queryFn: async () => {
      const res = await fetch(`/api/admin/affiliates/${enrollmentId}/commission-history`);
      if (!res.ok) return [];
      const json = (await res.json()) as { data: CommissionRow[] };
      return json.data ?? [];
    },
  });

  // ─── Create/Update affiliate link ─────────────────────────────────────────
  const [linkPct, setLinkPct] = useState<number | ''>('');
  const [linkWindow, setLinkWindow] = useState<number | ''>('');
  const [linkMsg, setLinkMsg] = useState<string | null>(null);
  const linkMutation = useMutation({
    mutationFn: async () => {
      const res = await fetch('/api/admin/referrals/affiliate', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json', 'x-csrf-token': getCsrfToken() },
        body: JSON.stringify({
          userId: data?.user_id,
          ...(linkPct !== '' ? { pct: linkPct } : {}),
          ...(linkWindow !== '' ? { windowDays: linkWindow } : {}),
        }),
      });
      if (!res.ok) throw new Error(await res.text());
      return res.json();
    },
    onSuccess: () => setLinkMsg(t('affiliate_link_success')),
    onError: () => setLinkMsg(t('affiliate_link_error')),
  });

  if (isLoading) {
    return (
      <p role="status" className="p-4 text-(--color-text-muted)">
        {t('detail_loading')}
      </p>
    );
  }

  if (!data) {
    return <EmptyState title={t('detail_not_found')} />;
  }

  return (
    <TooltipProvider>
      <div className="space-y-8">
        {/* Detail summary */}
        <dl className="grid grid-cols-2 gap-4 sm:grid-cols-3">
          <div>
            <DetailLabel tooltip={t('detail_ltv_margin_tooltip')}>
              {t('detail_ltv_margin')}
            </DetailLabel>
            <dd className="mt-0.5 font-semibold">
              <AffiliateLtvMarginValue ltv={data.ltv} t={t} />
            </dd>
          </div>
          <div>
            <dt className="text-xs text-(--color-text-muted)">{t('detail_total_payouts')}</dt>
            <dd className="mt-0.5 font-semibold">
              <AffiliateTotalPayoutsValue ltv={data.ltv} />
            </dd>
          </div>
          <div>
            <dt className="text-xs text-(--color-text-muted)">{t('detail_email')}</dt>
            <dd className="mt-0.5 font-medium">{data.email ?? '—'}</dd>
          </div>
          <div>
            <dt className="text-xs text-(--color-text-muted)">{t('detail_enrolled')}</dt>
            <dd className="mt-0.5 font-medium">{formatDate(data.enrolled_at, locale)}</dd>
          </div>
          <div>
            <dt className="text-xs text-(--color-text-muted)">{t('detail_status')}</dt>
            <dd className="mt-0.5">
              <StatusBadge
                state={data.status}
                map={AFFILIATE_STATUS_MAP}
                ns="admin_affiliates"
                size="sm"
              />
            </dd>
          </div>
          <div>
            <dt className="text-xs text-(--color-text-muted)">{t('detail_pct')}</dt>
            <dd className="mt-0.5 font-medium tabular-nums">
              {data.pct !== null ? `${data.pct}%` : '—'}
            </dd>
          </div>
          <div>
            <DetailLabel tooltip={t('detail_pending_tooltip')}>{t('detail_pending')}</DetailLabel>
            <dd className="mt-0.5 font-semibold tabular-nums">
              {formatAgorotShekels(data.pending_agorot ?? 0)}
            </dd>
          </div>
          <div>
            <DetailLabel tooltip={t('detail_matured_tooltip')}>{t('detail_matured')}</DetailLabel>
            <dd className="mt-0.5 font-semibold tabular-nums">
              {formatAgorotSigned(data.matured_agorot ?? 0)}
            </dd>
          </div>
          <div>
            <DetailLabel tooltip={t('detail_carried_debt_tooltip')}>
              {t('detail_carried_debt')}
            </DetailLabel>
            <dd className="mt-0.5 font-semibold tabular-nums">
              {formatAgorotShekels(data.carried_debt_agorot ?? 0)}
            </dd>
          </div>
          <div>
            <DetailLabel tooltip={t('detail_stripe_tooltip')}>{t('detail_stripe')}</DetailLabel>
            <dd className="mt-0.5 font-medium">
              <span>{stripeStatusLabel(data.stripe_status, t)}</span>
              {data.stripe_account_id ? (
                <span className="ms-2 text-xs text-(--color-text-muted)">
                  {data.stripe_payouts_enabled ? t('stripe_payouts_on') : t('stripe_payouts_off')}
                </span>
              ) : null}
            </dd>
          </div>
        </dl>

        {action.isError && (
          <p role="alert" className="text-sm text-(--color-error)">
            {String(action.error)}
          </p>
        )}

        <div className="flex flex-wrap gap-2">
          {data.status === 'active' && (
            <Button
              variant="secondary"
              size="sm"
              onClick={() => action.mutate({ action: 'suspend', reason: 'admin' })}
              loading={action.isPending}
            >
              {t('action_suspend')}
            </Button>
          )}
          {data.status === 'suspended' && (
            <Button
              variant="secondary"
              size="sm"
              onClick={() => action.mutate({ action: 'reinstate' })}
              loading={action.isPending}
            >
              {t('action_reinstate')}
            </Button>
          )}
          {['active', 'suspended'].includes(data.status) && (
            <Button
              variant="danger"
              size="sm"
              onClick={() => setRevokeConfirmOpen(true)}
              loading={action.isPending}
            >
              {t('action_revoke')}
            </Button>
          )}
        </div>

        <AlertDialog open={revokeConfirmOpen} onOpenChange={setRevokeConfirmOpen}>
          <AlertDialogContent>
            <AlertDialogHeader>
              <AlertDialogTitle>{t('action_revoke')}</AlertDialogTitle>
              <AlertDialogDescription>{t('action_revoke_confirm')}</AlertDialogDescription>
            </AlertDialogHeader>
            <AlertDialogFooter>
              <AlertDialogCancel>{tCommon('cancel')}</AlertDialogCancel>
              <AlertDialogAction
                onClick={() => {
                  action.mutate({ action: 'revoke' });
                  setRevokeConfirmOpen(false);
                }}
              >
                {t('action_revoke')}
              </AlertDialogAction>
            </AlertDialogFooter>
          </AlertDialogContent>
        </AlertDialog>

        {/* Commission edit */}
        <section aria-labelledby="commission-heading" className="space-y-3 rounded-lg border p-4">
          <h2 id="commission-heading" className="font-semibold">
            {t('commission_section_title')}
          </h2>
          <div className="flex items-end gap-3">
            <div className="flex flex-col gap-1">
              <Tooltip>
                <TooltipTrigger asChild>
                  <Label htmlFor="commission-pct" className="w-fit cursor-help">
                    {t('commission_pct_label')}
                  </Label>
                </TooltipTrigger>
                <TooltipContent>{t('commission_pct_tooltip')}</TooltipContent>
              </Tooltip>
              <NumberInput
                id="commission-pct"
                min={0}
                max={100}
                value={commissionPct}
                onChange={(n) => setCommissionDraft(n)}
                aria-label={t('commission_pct_label')}
              />
            </div>
            <Button
              size="sm"
              onClick={() => commissionMutation.mutate(commissionPct)}
              loading={commissionMutation.isPending}
              disabled={data.pct == null ? commissionDraft == null : commissionPct === data.pct}
            >
              {t('commission_save')}
            </Button>
          </div>
          {commissionMsg && (
            <p role="status" className="text-sm">
              {commissionMsg}
            </p>
          )}
        </section>

        {/* Adjust balance */}
        <section aria-labelledby="adjust-heading" className="space-y-3 rounded-lg border p-4">
          <Tooltip>
            <TooltipTrigger asChild>
              <h2 id="adjust-heading" className="w-fit cursor-help font-semibold">
                {t('adjust_section_title')}
              </h2>
            </TooltipTrigger>
            <TooltipContent>{t('adjust_section_tooltip')}</TooltipContent>
          </Tooltip>
          <div className="flex flex-col gap-3">
            <AdminMoneyInput
              name="adjust-amount"
              label={t('adjust_amount_label')}
              valueAgorot={adjustAmount || undefined}
              onChange={(agorot) => setAdjustAmount(agorot)}
            />
            <p className="text-text-muted text-xs">{t('adjust_amount_hint')}</p>
            <div className="flex flex-col gap-1">
              <Label htmlFor="adjust-memo">{t('adjust_memo_label')}</Label>
              <Textarea
                id="adjust-memo"
                value={adjustMemo}
                onChange={(e) => setAdjustMemo(e.target.value)}
                placeholder={t('adjust_memo_placeholder')}
                rows={2}
              />
            </div>
            <Button
              size="sm"
              onClick={() =>
                adjustMutation.mutate({ amountAgorot: adjustAmount, memo: adjustMemo })
              }
              loading={adjustMutation.isPending}
              disabled={!adjustMemo.trim()}
            >
              {t('adjust_submit')}
            </Button>
          </div>
          {adjustMsg && (
            <p role="status" className="text-sm">
              {adjustMsg}
            </p>
          )}
        </section>

        {/* Withdrawal requests */}
        <section aria-labelledby="payouts-heading" className="space-y-3 rounded-lg border p-4">
          <h2 id="payouts-heading" className="font-semibold">
            {t('payouts_section_title')}
          </h2>
          {payoutsLoading ? (
            <p className="text-text-muted text-sm">{t('payouts_loading')}</p>
          ) : !payouts?.length ? (
            <p className="text-text-muted text-sm">{t('payouts_empty')}</p>
          ) : (
            <ul className="flex flex-col gap-2">
              {payouts.map((p) => (
                <li key={p.id} className="flex items-center justify-between gap-3 border-b pb-2">
                  <div className="flex flex-col gap-0.5">
                    <span className="text-text-muted font-mono text-xs">{p.id.slice(0, 8)}</span>
                    <span className="font-semibold">{formatAgorotShekels(p.amountAgorot)}</span>
                    <span className="text-xs">{payoutStatusLabel(p.status, t)}</span>
                  </div>
                  <div className="flex gap-2">
                    {p.status === 'requested' && (
                      <Button
                        size="sm"
                        variant="secondary"
                        onClick={() => payoutAction.mutate({ payoutId: p.id, action: 'approve' })}
                        loading={payoutAction.isPending}
                      >
                        {t('payouts_approve')}
                      </Button>
                    )}
                    {p.status === 'approved' && (
                      <Button
                        size="sm"
                        variant="primary"
                        onClick={() => payoutAction.mutate({ payoutId: p.id, action: 'mark-paid' })}
                        loading={payoutAction.isPending}
                      >
                        {t('payouts_mark_paid')}
                      </Button>
                    )}
                  </div>
                </li>
              ))}
            </ul>
          )}
          {payoutActionError && (
            <p role="alert" className="text-sm text-(--color-error)">
              {payoutActionError}
            </p>
          )}
        </section>

        {/* Create/Update affiliate link */}
        <section
          aria-labelledby="affiliate-link-heading"
          className="space-y-3 rounded-lg border p-4"
        >
          <h2 id="affiliate-link-heading" className="font-semibold">
            {t('affiliate_link_section_title')}
          </h2>
          <div className="flex flex-col gap-3">
            <div className="flex flex-col gap-1">
              <Label htmlFor="link-user-id">{t('affiliate_link_user_id_label')}</Label>
              <Input id="link-user-id" value={data.user_id} readOnly aria-readonly="true" />
            </div>
            <div className="flex gap-3">
              <div className="flex flex-col gap-1">
                <Label htmlFor="link-pct">{t('affiliate_link_pct_label')}</Label>
                <NumberInput
                  id="link-pct"
                  min={0}
                  max={100}
                  value={linkPct === '' ? 0 : linkPct}
                  onChange={(n) => setLinkPct(n)}
                  aria-label={t('affiliate_link_pct_label')}
                />
              </div>
              <div className="flex flex-col gap-1">
                <Tooltip>
                  <TooltipTrigger asChild>
                    <Label htmlFor="link-window" className="w-fit cursor-help">
                      {t('affiliate_link_window_label')}
                    </Label>
                  </TooltipTrigger>
                  <TooltipContent>{t('affiliate_link_window_tooltip')}</TooltipContent>
                </Tooltip>
                <NumberInput
                  id="link-window"
                  min={1}
                  value={linkWindow === '' ? 0 : linkWindow}
                  onChange={(n) => setLinkWindow(n)}
                  aria-label={t('affiliate_link_window_label')}
                />
              </div>
            </div>
            <Button
              size="sm"
              onClick={() => linkMutation.mutate()}
              loading={linkMutation.isPending}
            >
              {t('affiliate_link_submit')}
            </Button>
          </div>
          {linkMsg && (
            <p role="status" className="text-sm">
              {linkMsg}
            </p>
          )}
        </section>

        {/* Commission history */}
        <section
          aria-labelledby="commission-history-heading"
          className="space-y-3 rounded-lg border p-4"
        >
          <h2 id="commission-history-heading" className="font-semibold">
            {t('commission_history_section_title')}
          </h2>
          {commissionHistoryLoading ? (
            <p className="text-text-muted text-sm">{t('commission_history_loading')}</p>
          ) : !commissionHistory?.length ? (
            <p className="text-text-muted text-sm">{t('commission_history_empty')}</p>
          ) : (
            <table className="w-full text-sm">
              <thead>
                <tr className="text-text-muted border-b text-start">
                  <th className="pb-2 text-start font-medium">
                    {t('commission_history_col_date')}
                  </th>
                  <th className="pb-2 text-end font-medium">
                    {t('commission_history_col_amount')}
                  </th>
                  <th className="ps-4 pb-2 text-start font-medium">
                    {t('commission_history_col_deal')}
                  </th>
                </tr>
              </thead>
              <tbody>
                {commissionHistory.map((c) => (
                  <tr key={c.id} className="border-b last:border-0">
                    <td className="text-text-muted py-1.5 tabular-nums">
                      {formatDate(c.createdAt, locale)}
                    </td>
                    <td className="py-1.5 text-end font-semibold tabular-nums">
                      {formatAgorotShekels(c.amountAgorot)}
                    </td>
                    <td className="max-w-xs truncate py-1.5 ps-4">{c.dealTitle}</td>
                  </tr>
                ))}
              </tbody>
            </table>
          )}
        </section>
      </div>
    </TooltipProvider>
  );
}

export function AffiliateDetail({ enrollmentId }: Props) {
  return (
    <HydratedIsland>
      <AffiliateDetailInner enrollmentId={enrollmentId} />
    </HydratedIsland>
  );
}
