'use client';

import React, { useEffect, useRef, useState } from 'react';
import { X, Loader2, Pause, Download, ArrowRight } from 'lucide-react';
import { Button } from '@/components/ui/Button';

export type UpgradeReason = 'limit' | 'logo' | 'shapes';

export interface ActiveCodeSummary {
  id: string;
  title: string;
  scans30d: number;
}

interface UpgradeModalProps {
  open: boolean;
  reason: UpgradeReason;
  /** How many dynamic codes the user already has. Only used for reason="limit". */
  currentCount?: number;
  /** The plan limit that was hit. Only used for reason="limit". */
  limit?: number;
  /** Active dynamic codes, so the user can free a slot instead of paying. */
  activeCodes?: ActiveCodeSummary[];
  /** Called when the user pauses a code to free a slot. */
  onPauseCode?: (id: string) => Promise<void>;
  /** Called when the user chooses to download a static code instead. */
  onDownloadStatic?: () => void;
  onClose: () => void;
  /** Path Stripe returns to after checkout. Defaults to the current URL. */
  returnPath?: string;
}

function ordinal(n: number): string {
  const s = ['th', 'st', 'nd', 'rd'];
  const v = n % 100;
  return n + (s[(v - 20) % 10] || s[v] || s[0]);
}

/**
 * Copy notes, so nobody softens this back into a generic paywall:
 *
 * The headline names the thing the user just built, not the plan they lack.
 * They are buying a specific code that already exists, not an abstraction.
 *
 * The two secondary options are deliberate. "Pause a code" keeps them inside
 * the free plan, and "download as static" hands them a working result for
 * nothing. Both cost conversions. Both are what makes the closing line
 * believable instead of decorative - this product does not hold printed codes
 * hostage, and this is the one screen where that has to be demonstrated
 * rather than claimed.
 */
function getCopy(reason: UpgradeReason, currentCount?: number, limit?: number) {
  if (reason === 'logo') {
    return {
      headline: 'Your logo belongs inside this code.',
      body: 'A QR code with your mark in the middle gets scanned more often than an anonymous black square, because people can see who it belongs to before they trust it.',
      mechanism:
        'Pro puts your logo in the center of every code you make, at the error-correction level that keeps it scannable.',
      cta: 'Add my logo - €9 / month',
      reassurance: 'Your current codes keep working exactly as they are.',
    };
  }

  if (reason === 'shapes') {
    return {
      headline: 'This shape needs Pro.',
      body: 'Rounded modules, dots and flowing styles make a code look designed instead of generated. On a menu or a flyer, that is the difference between something people scan and something they ignore.',
      mechanism:
        'Pro unlocks four module shapes and your own eye styles. Colors stay free on every plan.',
      cta: 'Unlock shapes - €9 / month',
      reassurance: 'Your current codes keep working exactly as they are.',
    };
  }

  const next = (currentCount ?? 3) + 1;
  const cap = limit ?? 3;

  return {
    headline: `Your ${ordinal(next)} code is finished. It just needs a slot.`,
    body: `You are using all ${cap} dynamic codes on your plan. This one is built and waiting - you can keep it, or free a slot from the codes you already have.`,
    mechanism: 'Pro raises the ceiling to 50 dynamic codes and adds device and location data for every scan.',
    cta: 'Save this code with Pro - €9 / month',
    reassurance: `Your ${cap} active codes keep running, whichever way you decide.`,
  };
}

export default function UpgradeModal({
  open,
  reason,
  currentCount,
  limit,
  activeCodes = [],
  onPauseCode,
  onDownloadStatic,
  onClose,
  returnPath,
}: UpgradeModalProps) {
  const overlayRef = useRef<HTMLDivElement>(null);
  const [checkoutLoading, setCheckoutLoading] = useState(false);
  const [showCodeList, setShowCodeList] = useState(false);
  const [pausingId, setPausingId] = useState<string | null>(null);
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    if (!open) return;
    const onKey = (e: KeyboardEvent) => {
      if (e.key === 'Escape') onClose();
    };
    document.addEventListener('keydown', onKey);
    return () => document.removeEventListener('keydown', onKey);
  }, [open, onClose]);

  useEffect(() => {
    if (!open) {
      setShowCodeList(false);
      setError(null);
    }
  }, [open]);

  if (!open) return null;

  const copy = getCopy(reason, currentCount, limit);

  const handleCheckout = async () => {
    setCheckoutLoading(true);
    setError(null);
    try {
      const path =
        returnPath ??
        (typeof window !== 'undefined'
          ? window.location.pathname + window.location.search
          : '/create');

      const res = await fetch('/api/stripe/create-checkout-session', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          plan: 'PRO',
          billingInterval: 'month',
          returnPath: path,
        }),
      });

      if (!res.ok) {
        const data = await res.json().catch(() => null);
        throw new Error(data?.error || 'Could not start checkout.');
      }

      const { url } = await res.json();
      window.location.href = url;
    } catch (err: any) {
      setError(err?.message || 'Could not start checkout. Please try again.');
      setCheckoutLoading(false);
    }
  };

  const handlePause = async (id: string) => {
    if (!onPauseCode) return;
    setPausingId(id);
    setError(null);
    try {
      await onPauseCode(id);
    } catch (err: any) {
      setError(err?.message || 'Could not pause that code.');
      setPausingId(null);
    }
  };

  return (
    <div
      ref={overlayRef}
      className="fixed inset-0 z-50 flex items-center justify-center p-4 overflow-y-auto"
      style={{ backgroundColor: 'rgba(15, 23, 42, 0.6)', backdropFilter: 'blur(4px)' }}
      onClick={(e) => {
        if (e.target === overlayRef.current) onClose();
      }}
      role="dialog"
      aria-modal="true"
      aria-labelledby="upgrade-modal-title"
    >
      <div className="my-8 w-full max-w-lg overflow-hidden rounded-3xl bg-white shadow-2xl">
        <div className="relative border-b border-slate-100 p-6">
          <button
            onClick={onClose}
            className="absolute right-4 top-4 text-slate-400 transition-colors hover:text-slate-600"
            aria-label="Close"
          >
            <X className="h-5 w-5" />
          </button>

          <h2
            id="upgrade-modal-title"
            className="pr-8 text-2xl font-bold leading-snug text-slate-900"
          >
            {copy.headline}
          </h2>
          <p className="mt-3 text-base leading-relaxed text-slate-600">{copy.body}</p>
          <p className="mt-3 text-base leading-relaxed text-slate-600">{copy.mechanism}</p>
        </div>

        <div className="space-y-3 p-6">
          {error && (
            <div className="rounded-lg border border-red-200 bg-red-50 p-3 text-sm text-red-800">
              {error}
            </div>
          )}

          <Button
            onClick={handleCheckout}
            disabled={checkoutLoading}
            className="h-12 w-full bg-primary-600 text-base font-semibold text-white hover:bg-primary-700"
          >
            {checkoutLoading ? (
              <span className="flex items-center justify-center gap-2">
                <Loader2 className="h-4 w-4 animate-spin" /> Opening checkout...
              </span>
            ) : (
              <span className="flex items-center justify-center gap-2">
                {copy.cta} <ArrowRight className="h-4 w-4" />
              </span>
            )}
          </Button>

          {reason === 'limit' && onPauseCode && activeCodes.length > 0 && !showCodeList && (
            <button
              onClick={() => setShowCodeList(true)}
              className="flex w-full items-center justify-center gap-2 rounded-lg border border-slate-200 py-3 text-sm font-medium text-slate-700 transition-colors hover:bg-slate-50"
            >
              <Pause className="h-4 w-4" /> Pause one of my existing codes
            </button>
          )}

          {reason === 'limit' && showCodeList && (
            <div className="rounded-lg border border-slate-200">
              <p className="border-b border-slate-100 px-4 py-3 text-sm text-slate-600">
                Pausing keeps the code and its scan history. It stops resolving until you
                switch it back on.
              </p>
              <ul className="divide-y divide-slate-100">
                {activeCodes.map((code) => (
                  <li key={code.id} className="flex items-center justify-between gap-3 px-4 py-3">
                    <div className="min-w-0">
                      <p className="truncate text-sm font-medium text-slate-900">{code.title}</p>
                      <p className="text-xs text-slate-500">
                        {code.scans30d === 0
                          ? 'No scans in the last 30 days'
                          : `${code.scans30d} scan${code.scans30d === 1 ? '' : 's'} in the last 30 days`}
                      </p>
                    </div>
                    <Button
                      variant="secondary"
                      size="sm"
                      disabled={pausingId !== null}
                      onClick={() => handlePause(code.id)}
                    >
                      {pausingId === code.id ? (
                        <Loader2 className="h-4 w-4 animate-spin" />
                      ) : (
                        'Pause'
                      )}
                    </Button>
                  </li>
                ))}
              </ul>
            </div>
          )}

          {reason === 'limit' && onDownloadStatic && (
            <button
              onClick={onDownloadStatic}
              className="flex w-full items-center justify-center gap-2 rounded-lg border border-slate-200 py-3 text-sm font-medium text-slate-700 transition-colors hover:bg-slate-50"
            >
              <Download className="h-4 w-4" /> Download it as a static code instead
            </button>
          )}

          <p className="pt-1 text-center text-sm text-slate-500">{copy.reassurance}</p>

          <button
            onClick={onClose}
            className="w-full py-1 text-sm text-slate-400 transition-colors hover:text-slate-600"
          >
            Not now
          </button>
        </div>
      </div>
    </div>
  );
}
