import { useState } from 'react';
import { ExternalLink } from 'lucide-react';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import { Label } from '@/components/ui/label';
import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group';
import { Separator } from '@/components/ui/separator';
import { Muted } from '@/components/ui/typography';
import { CopyableEmail } from '@/components/copyable-email';
import { cn } from '@/lib/utils';
import { toUserMessage } from '@/lib/errors';
import { SUPPORT_EMAIL } from '@/lib/constants';
import {
  useCreateCheckoutSession,
  useCreatePortalSession,
  useNetworkBilling,
} from '@/hooks/use-billing';
import { useNetworkUsage } from '@/hooks/use-network-usage';
import { useIsNetworkAdmin } from '@/hooks/use-networks';
import type { BillingCadence, BillingStatus } from '@/api/types';
import { platform } from '@/lib/platform';

function formatCents(cents: number): string {
  if (cents % 100 === 0) return `$${cents / 100}`;
  return `$${(cents / 100).toFixed(2)}`;
}

function formatDate(date: Date): string {
  return date.toLocaleDateString(undefined, {
    month: 'long',
    day: 'numeric',
    year: 'numeric',
  });
}

function PlanStatusBadge({ status }: { status: BillingStatus['plan_status'] }) {
  if (status === 'past_due')
    return <Badge variant="destructive">Past due</Badge>;
  if (status === 'canceled') return <Badge variant="secondary">Canceled</Badge>;
  if (status === 'trialing') return <Badge variant="secondary">Trialing</Badge>;
  return null;
}

function InfoRow({
  label,
  value,
}: {
  label: React.ReactNode;
  value: React.ReactNode;
}) {
  return (
    <div className="flex w-full items-center gap-3 px-4 py-3">
      <Muted className="text-sm">{label}</Muted>
      <div className="flex-1" />
      <div className="text-sm">{value}</div>
    </div>
  );
}

function CadenceOption({
  value,
  label,
  perSeatCents,
  billedNote,
  saveBadge,
  selected,
}: {
  value: BillingCadence;
  label: string;
  perSeatCents: number;
  billedNote: string;
  saveBadge?: string;
  selected: boolean;
}) {
  return (
    <Label
      htmlFor={`cadence-${value}`}
      className={cn(
        'hover:bg-accent flex w-full cursor-pointer items-center gap-3 px-4 py-3 font-normal transition-colors',
        selected && 'bg-accent/50',
      )}
    >
      <RadioGroupItem id={`cadence-${value}`} value={value} />
      <div className="min-w-0 flex-1">
        <div className="flex items-center gap-2">
          <p className="text-sm font-medium">{label}</p>
          {saveBadge && <Badge>{saveBadge}</Badge>}
        </div>
        <Muted className="text-xs">{billedNote}</Muted>
      </div>
      <div className="shrink-0 text-right">
        <p className="text-sm font-medium">{formatCents(perSeatCents)}</p>
        <Muted className="text-xs">per seat / mo</Muted>
      </div>
    </Label>
  );
}

function formatResetLocal(resetAt: Date): string {
  const time = resetAt.toLocaleTimeString(undefined, {
    hour: 'numeric',
    minute: '2-digit',
  });
  const now = new Date();
  const isSameDay =
    resetAt.getFullYear() === now.getFullYear() &&
    resetAt.getMonth() === now.getMonth() &&
    resetAt.getDate() === now.getDate();
  return `${isSameDay ? 'today' : 'tomorrow'} at ${time}`;
}

/**
 * Read-only plan + quota summary, sourced from `/usage` (member-accessible).
 * The `/billing` endpoint is admin-gated, so we can't use it for the
 * everyone-visible summary.
 */
function PlanSummary({ networkId }: { networkId: string }) {
  const { data: usage } = useNetworkUsage(networkId);

  if (!usage) return null;

  const isPro = usage.plan === 'pro';

  return (
    <>
      <InfoRow
        label="Plan"
        value={
          <div className="flex items-center gap-2">
            <span>{isPro ? 'Llink Pro' : 'Llink Free'}</span>
            <Badge variant={isPro ? 'default' : 'secondary'}>
              {isPro ? 'Pro' : 'Free'}
            </Badge>
          </div>
        }
      />
      {!isPro && (
        <>
          <Separator className="mx-4" />
          <InfoRow
            label="Today's messages"
            value={
              usage && usage.limit != null ? (
                <div className="flex flex-col items-end">
                  <span className="tabular-nums">
                    {usage.used} / {usage.limit}
                  </span>
                  <Muted className="text-xs">
                    Resets {formatResetLocal(usage.reset_at)}
                  </Muted>
                </div>
              ) : (
                <Muted className="text-sm">—</Muted>
              )
            }
          />
        </>
      )}
    </>
  );
}

function FreeBilling({
  networkId,
  billing,
}: {
  networkId: string;
  billing: BillingStatus;
}) {
  const createCheckout = useCreateCheckoutSession(networkId);
  const [cadence, setCadence] = useState<BillingCadence>('annual');

  const handleUpgrade = () => {
    createCheckout.mutate(cadence, {
      onSuccess: ({ url }) => platform.link.openExternal(url),
    });
  };

  const annualPerSeatMonthlyCents = Math.round(billing.price_annual_cents / 12);
  const savingsPct = Math.round(
    (1 - annualPerSeatMonthlyCents / billing.price_monthly_cents) * 100,
  );

  return (
    <>
      <RadioGroup
        value={cadence}
        onValueChange={(v) => setCadence(v as BillingCadence)}
        className="gap-0"
      >
        <CadenceOption
          value="annual"
          label="Annual"
          perSeatCents={annualPerSeatMonthlyCents}
          billedNote="Billed annually"
          saveBadge={savingsPct > 0 ? `Save ${savingsPct}%` : undefined}
          selected={cadence === 'annual'}
        />
        <Separator className="mx-4" />
        <CadenceOption
          value="monthly"
          label="Monthly"
          perSeatCents={billing.price_monthly_cents}
          billedNote="Billed monthly · cancel anytime"
          selected={cadence === 'monthly'}
        />
      </RadioGroup>
      <div className="px-4 py-3">
        <Button
          className="w-full"
          onClick={handleUpgrade}
          disabled={createCheckout.isPending}
        >
          {createCheckout.isPending ? 'Opening Stripe...' : 'Upgrade to Pro'}
        </Button>
      </div>
    </>
  );
}

function ProBilling({
  networkId,
  billing,
}: {
  networkId: string;
  billing: BillingStatus;
}) {
  const createPortal = useCreatePortalSession(networkId);

  const handleManage = () => {
    createPortal.mutate(undefined, {
      onSuccess: ({ url }) => platform.link.openExternal(url),
    });
  };

  const cadenceLabel = billing.cadence === 'annual' ? 'Annual' : 'Monthly';
  const perSeatCents =
    billing.cadence === 'annual'
      ? Math.round(billing.price_annual_cents / 12)
      : billing.price_monthly_cents;
  const renewal = billing.current_period_end
    ? formatDate(billing.current_period_end)
    : null;

  return (
    <>
      {billing.cancel_at_period_end && renewal && (
        <div className="border-destructive/30 bg-destructive/10 text-destructive mx-4 my-2 rounded-md border px-3 py-2 text-sm">
          Your subscription is set to downgrade to Free on {renewal}.
        </div>
      )}
      {billing.plan_status === 'past_due' && (
        <div className="border-destructive/30 bg-destructive/10 text-destructive mx-4 my-2 rounded-md border px-3 py-2 text-sm">
          Your last payment failed. Update your payment method to keep Pro
          active.
        </div>
      )}

      <InfoRow
        label="Billing"
        value={
          <div className="flex items-center gap-2">
            <span>{`${cadenceLabel} · ${formatCents(perSeatCents)} / seat / mo`}</span>
            <PlanStatusBadge status={billing.plan_status} />
          </div>
        }
      />
      <Separator className="mx-4" />
      <InfoRow label="Seats" value={billing.seats} />
      {renewal && (
        <>
          <Separator className="mx-4" />
          <InfoRow
            label={billing.cancel_at_period_end ? 'Ends' : 'Renews'}
            value={renewal}
          />
        </>
      )}
      <div className="px-4 py-3">
        <Button
          variant="outline"
          className="w-full"
          onClick={handleManage}
          disabled={createPortal.isPending}
        >
          <ExternalLink className="mr-2 size-3.5" />
          {createPortal.isPending ? 'Opening Stripe...' : 'Manage subscription'}
        </Button>
      </div>
    </>
  );
}

/**
 * Unified billing section. Shows the plan + usage summary to every member,
 * and the admin-only management controls (upgrade / portal) below.
 *
 * `/billing` is admin-gated, so the management controls are the only part
 * that depends on it — members rely on `/usage` for the summary.
 */
export function BillingSection({ networkId }: { networkId: string }) {
  const isAdmin = useIsNetworkAdmin(networkId);
  return (
    <>
      <PlanSummary networkId={networkId} />
      {isAdmin && (
        <>
          <Separator className="mx-4" />
          <AdminBillingControls networkId={networkId} />
          <Separator className="mx-4" />
          <InfoRow
            label={
              <span className="flex flex-col">
                <span>Billing support</span>
                <span className="text-muted-foreground text-xs">
                  Invoices, receipts, or plan changes
                </span>
              </span>
            }
            value={<CopyableEmail email={SUPPORT_EMAIL} />}
          />
        </>
      )}
    </>
  );
}

function AdminBillingControls({ networkId }: { networkId: string }) {
  const { data: billing, isLoading, error } = useNetworkBilling(networkId);

  if (isLoading || !billing) {
    return (
      <div className="px-4 py-3">
        <Muted className="text-sm">Loading billing...</Muted>
      </div>
    );
  }
  if (error) {
    return (
      <div className="px-4 py-3">
        <Muted className="text-sm">
          Couldn't load billing: {toUserMessage(error)}
        </Muted>
      </div>
    );
  }
  if (billing.plan === 'pro') {
    return <ProBilling networkId={networkId} billing={billing} />;
  }
  return <FreeBilling networkId={networkId} billing={billing} />;
}
