'use client';

import { useEffect, useRef, useState, useTransition } from 'react';
import QRCode from 'qrcode';
import { Check, Copy, Download, LoaderCircle, Share2 } from 'lucide-react';
import { startCheckout } from '@/app/actions/affiliate';
import { Button } from '@/components/ui/Button';
import { useMessages } from '@/i18n/client';
import type { AuraZoneReading } from '@/lib/aura/auraField';

/** Starts Midtrans checkout and sends the buyer to the payment page. */
export function BuyPremiumButton({ label, className }: { label?: string; className?: string }) {
  const t = useMessages().affiliate.checkout;
  const [pending, start] = useTransition();
  const [error, setError] = useState<string | null>(null);
  return (
    <div className={className}>
      <Button
        disabled={pending}
        onClick={() =>
          start(async () => {
            setError(null);
            const res = await startCheckout();
            if (res.ok) window.location.assign(res.redirectUrl);
            else setError(res.error);
          })
        }
      >
        {pending && <LoaderCircle className="size-4 animate-spin" aria-hidden />}
        {pending ? t.redirecting : (label ?? t.buy)}
      </Button>
      {error && (
        <p role="alert" className="mt-2 text-[13px] text-fire">
          {error}
        </p>
      )}
    </div>
  );
}

export function CopyField({ label, value }: { label: string; value: string }) {
  const t = useMessages().affiliate.dashboard;
  const [copied, setCopied] = useState(false);
  return (
    <div>
      <p className="text-xs font-medium text-subtle">{label}</p>
      <div className="mt-1.5 flex items-center gap-2 rounded-2xl bg-canvas p-1.5 pl-4 ring-1 ring-line">
        <span className="min-w-0 flex-1 truncate font-mono text-sm text-ink">{value}</span>
        <button
          type="button"
          onClick={async () => {
            await navigator.clipboard.writeText(value);
            setCopied(true);
            setTimeout(() => setCopied(false), 2000);
          }}
          className="inline-flex h-9 items-center gap-1.5 rounded-xl bg-surface px-3 text-[13px] font-medium text-ink ring-1 ring-line hover:bg-canvas"
        >
          {copied ? <Check className="size-4 text-wood" /> : <Copy className="size-4" />}
          {copied ? t.copied : t.copy}
        </button>
      </div>
    </div>
  );
}

const W = 1080;
const H = 1350;

function loadImage(src: string) {
  return new Promise<HTMLImageElement>((resolve, reject) => {
    const img = new Image();
    img.onload = () => resolve(img);
    img.onerror = reject;
    img.src = src;
  });
}

/** Draws the shareable card: instant-film aura photo, aura type and colours, QR and affiliate code. */
async function drawCard(
  canvas: HTMLCanvasElement,
  opts: { photo: string; zones: AuraZoneReading[]; typeName: string; typeColor: string; code: string; link: string; tagline: string; codeLabel: string; scan: string },
) {
  const ctx = canvas.getContext('2d')!;
  canvas.width = W;
  canvas.height = H;
  ctx.fillStyle = '#FBFAF7';
  ctx.fillRect(0, 0, W, H);

  // Photo, cropped to cover the frame.
  const fx = 60, fy = 60, fw = W - 120, fh = 960;
  const img = await loadImage(opts.photo);
  const scale = Math.max(fw / img.width, fh / img.height);
  const sw = fw / scale, sh = fh / scale;
  ctx.save();
  ctx.beginPath();
  ctx.rect(fx, fy, fw, fh);
  ctx.clip();
  ctx.drawImage(img, (img.width - sw) / 2, (img.height - sh) / 2, sw, sh, fx, fy, fw, fh);

  // Soft aura clouds from each zone, with the face kept clear.
  const zone = Object.fromEntries(opts.zones.map((z) => [z.zone, z.color])) as Record<string, string>;
  const clouds: [number, number, number, string][] = [
    [fx + fw * 0.5, fy, fw * 0.75, zone.top],
    [fx, fy + fh * 0.42, fw * 0.6, zone.left],
    [fx + fw, fy + fh * 0.48, fw * 0.6, zone.right],
    [fx + fw * 0.5, fy + fh, fw * 0.8, zone.bottom],
  ];
  ctx.filter = 'blur(40px)';
  for (const op of ['source-over', 'screen'] as const) {
    ctx.globalCompositeOperation = op;
    ctx.globalAlpha = op === 'screen' ? 0.7 : 0.55;
    for (const [x, y, r, color] of clouds) {
      const g = ctx.createRadialGradient(x, y, 0, x, y, r);
      g.addColorStop(0, color);
      g.addColorStop(0.35, color);
      g.addColorStop(1, 'rgba(0,0,0,0)');
      ctx.fillStyle = g;
      ctx.fillRect(fx - 100, fy - 100, fw + 200, fh + 200);
    }
  }
  // Halo around the head in the core colour.
  ctx.globalCompositeOperation = 'screen';
  ctx.globalAlpha = 0.85;
  const cx = fx + fw / 2, cy = fy + fh * 0.4;
  const halo = ctx.createRadialGradient(cx, cy, fw * 0.17, cx, cy, fw * 0.36);
  halo.addColorStop(0, 'rgba(0,0,0,0)');
  halo.addColorStop(0.55, zone.center);
  halo.addColorStop(1, 'rgba(0,0,0,0)');
  ctx.fillStyle = halo;
  ctx.fillRect(fx, fy, fw, fh);
  ctx.restore();
  ctx.filter = 'none';
  ctx.globalAlpha = 1;
  ctx.globalCompositeOperation = 'source-over';

  // Caption area.
  const font = '"Plus Jakarta Sans", "PingFang SC", "Microsoft YaHei", system-ui, sans-serif';
  ctx.fillStyle = '#0B1222';
  ctx.font = `600 30px ${font}`;
  ctx.fillText('Aura+', 60, 1085);
  ctx.fillStyle = '#6B7285';
  ctx.font = `400 24px ${font}`;
  ctx.fillText(opts.tagline, 60, 1120);

  ctx.fillStyle = opts.typeColor;
  ctx.beginPath();
  ctx.arc(80, 1182, 18, 0, Math.PI * 2);
  ctx.fill();
  ctx.fillStyle = '#0B1222';
  ctx.font = `700 46px ${font}`;
  ctx.fillText(opts.typeName, 112, 1198);

  // Zone colour dots.
  opts.zones.forEach((z, i) => {
    ctx.fillStyle = z.color;
    ctx.beginPath();
    ctx.arc(80 + i * 34, 1245, 11, 0, Math.PI * 2);
    ctx.fill();
  });

  ctx.fillStyle = '#3A4255';
  ctx.font = `600 28px ${font}`;
  ctx.fillText(opts.codeLabel, 60, 1300);

  // QR to the referral link.
  const qr = await loadImage(await QRCode.toDataURL(opts.link, { margin: 1, width: 200, color: { dark: '#0B1222', light: '#FBFAF7' } }));
  ctx.drawImage(qr, W - 60 - 200, 1080, 200, 200);
  ctx.fillStyle = '#6B7285';
  ctx.font = `400 20px ${font}`;
  ctx.textAlign = 'center';
  ctx.fillText(opts.scan, W - 160, 1310);
  ctx.textAlign = 'left';
}

export function ShareCard({
  photo,
  zones,
  typeName,
  typeColor,
  code,
  link,
}: {
  photo: string;
  zones: AuraZoneReading[];
  typeName: string;
  typeColor: string;
  code: string;
  link: string;
}) {
  const t = useMessages().affiliate.dashboard;
  const canvasRef = useRef<HTMLCanvasElement>(null);
  const [ready, setReady] = useState(false);

  useEffect(() => {
    if (!canvasRef.current) return;
    drawCard(canvasRef.current, {
      photo,
      zones,
      typeName,
      typeColor,
      code,
      link,
      tagline: t.cardTagline,
      codeLabel: t.cardCode(code),
      scan: t.cardScan,
    }).then(() => setReady(true));
  }, [photo, zones, typeName, typeColor, code, link, t]);

  const toBlob = () =>
    new Promise<Blob | null>((resolve) => canvasRef.current?.toBlob((b) => resolve(b), 'image/png'));

  const download = async () => {
    const blob = await toBlob();
    if (!blob) return;
    const a = document.createElement('a');
    a.href = URL.createObjectURL(blob);
    a.download = `aura-${code}.png`;
    a.click();
    URL.revokeObjectURL(a.href);
  };

  const share = async () => {
    const blob = await toBlob();
    if (!blob) return;
    const file = new File([blob], `aura-${code}.png`, { type: 'image/png' });
    const text = t.shareMessage(link);
    if (navigator.canShare?.({ files: [file] })) {
      await navigator.share({ files: [file], text }).catch(() => {});
    } else {
      // Desktop browsers without file sharing: hand off to WhatsApp with the link, and save the image.
      await download();
      window.open(`https://wa.me/?text=${encodeURIComponent(text)}`, '_blank', 'noopener');
    }
  };

  return (
    <div className="grid items-start gap-6 md:grid-cols-[minmax(0,320px)_minmax(0,1fr)]">
      <canvas
        ref={canvasRef}
        className="w-full rounded-[8px] shadow-float ring-1 ring-black/5"
        style={{ aspectRatio: `${W} / ${H}` }}
      />
      <div className="flex flex-wrap gap-3">
        <Button onClick={share} disabled={!ready}>
          <Share2 className="size-4" aria-hidden />
          {t.share}
        </Button>
        <Button variant="outline" onClick={download} disabled={!ready}>
          <Download className="size-4" aria-hidden />
          {t.download}
        </Button>
      </div>
    </div>
  );
}
