// SPDX-License-Identifier: GPL-3.0-or-later

import { useState, useEffect } from 'react';
import { CreditCard, HardDrive, Copy, CheckCircle, Database, RefreshCw, Key, Loader2, AlertCircle } from 'lucide-react';
import { useBackend } from '../contexts/BackendContext';
import Card from '../components/Card';
import Alert from '../components/Alert';
import Modal from '../components/Modal';
import CardOnramp from '../components/CardOnramp';
import { formatBytes, formatCredits, formatDateTime } from '../lib/utils';
import type { CredentialsResponse, PaymentIntentResponse, LTCPaymentIntentResponse, LTCPaymentStatus } from '../lib/api';
import * as api from '../lib/api';

export default function Account() {
  const { account } = useBackend();
  const [credentials, setCredentials] = useState<CredentialsResponse | null>(null);
  const [showRotateModal, setShowRotateModal] = useState(false);
  const [isRotating, setIsRotating] = useState(false);
  const [rotateSuccess, setRotateSuccess] = useState<string | null>(null);
  const [rotateError, setRotateError] = useState<string | null>(null);

  // Payment intent state
  const [paymentMethod, setPaymentMethod] = useState<'xmr' | 'ltc' | 'card'>('xmr');
  const [creditsAmount, setCreditsAmount] = useState(1);
  const [paymentIntent, setPaymentIntent] = useState<PaymentIntentResponse | null>(null);
  const [ltcIntent, setLtcIntent] = useState<LTCPaymentIntentResponse | null>(null);
  const [ltcStatus, setLtcStatus] = useState<LTCPaymentStatus | null>(null);
  const [isCreatingIntent, setIsCreatingIntent] = useState(false);
  const [intentError, setIntentError] = useState<string | null>(null);
  const [copied, setCopied] = useState(false);

  useEffect(() => {
    const fetchCredentials = async () => {
      try {
        const creds = await api.getCredentials();
        setCredentials(creds);
      } catch (err) {
        console.error('Failed to fetch credentials:', err);
      }
    };
    fetchCredentials();
  }, []);

  // While an LTC intent is active, poll how much has been received so we can show
  // an underpayment shortfall ("send $Z more"). Cleared when the intent changes.
  useEffect(() => {
    if (!ltcIntent) {
      setLtcStatus(null);
      return;
    }
    let cancelled = false;
    const poll = async () => {
      try {
        const s = await api.getLTCPaymentStatus();
        if (!cancelled) setLtcStatus(s);
      } catch {
        /* transient; keep the last-known status */
      }
    };
    poll();
    const id = setInterval(poll, 15000);
    return () => {
      cancelled = true;
      clearInterval(id);
    };
  }, [ltcIntent]);

  const resetIntents = () => {
    setPaymentIntent(null);
    setLtcIntent(null);
    setLtcStatus(null);
    setIntentError(null);
  };

  const handleGetXMRAddress = async () => {
    if (creditsAmount < 1) return;
    setIsCreatingIntent(true);
    resetIntents();
    try {
      const intent = await api.createPaymentIntent(creditsAmount);
      setPaymentIntent(intent);
    } catch (err) {
      setIntentError(err instanceof Error ? err.message : 'Failed to create payment intent');
    } finally {
      setIsCreatingIntent(false);
    }
  };

  const handleGetLTCIntent = async () => {
    if (creditsAmount < 1) return;
    setIsCreatingIntent(true);
    resetIntents();
    try {
      const intent = await api.createLTCPaymentIntent(creditsAmount);
      setLtcIntent(intent);
    } catch (err) {
      setIntentError(err instanceof Error ? err.message : 'Failed to create LTC payment intent');
    } finally {
      setIsCreatingIntent(false);
    }
  };

  const handleCopy = async (text: string) => {
    if (!text) return;
    try {
      await navigator.clipboard.writeText(text);
      setCopied(true);
      setTimeout(() => setCopied(false), 2000);
    } catch (err) {
      console.error('Failed to copy:', err);
    }
  };

  const handleRotateCredentials = async () => {
    setIsRotating(true);
    setRotateError(null);
    try {
      const result = await api.rotateCredentials();
      setRotateSuccess(`Credentials rotated successfully. New access key: ${result.access_key_id}`);
      setShowRotateModal(false);
      const creds = await api.getCredentials();
      setCredentials(creds);
    } catch (err) {
      setRotateError(err instanceof Error ? err.message : 'Failed to rotate credentials');
    } finally {
      setIsRotating(false);
    }
  };

  // LTC needed for N credits = N * credit_price_zar / ltc_zar_rate_locked (display only;
  // the server credits the exact LTC actually received at the locked rate).
  const ltcRate = ltcIntent ? parseFloat(ltcIntent.ltc_zar_rate_locked) : 0;
  const ltcAmount =
    ltcIntent && ltcRate > 0
      ? (creditsAmount * parseFloat(ltcIntent.credit_price_zar)) / ltcRate
      : 0;
  // Prefer the server's authoritative expected amount (exact-amount model); fall
  // back to the local computation for display before the intent is created.
  const ltcAmountStr = ltcIntent?.expected_amount_ltc ?? (ltcAmount > 0 ? ltcAmount.toFixed(8) : '0');

  return (
    <div className="space-y-6">
      {/* Header */}
      <div>
        <h1 className="text-2xl font-bold text-slate-900 dark:text-white">Account</h1>
        <p className="text-slate-600 dark:text-slate-400 mt-1">
          Manage your account and add credits
        </p>
      </div>

      {rotateSuccess && (
        <Alert type="success" onClose={() => setRotateSuccess(null)}>
          {rotateSuccess}
        </Alert>
      )}
      {rotateError && (
        <Alert type="error" onClose={() => setRotateError(null)}>
          {rotateError}
        </Alert>
      )}

      {/* Account Overview */}
      <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
        {/* Credits */}
        <Card>
          <div className="flex items-center space-x-4">
            <div className="p-4 rounded-xl bg-accent-100 dark:bg-accent-900/30">
              <CreditCard className="w-8 h-8 text-accent-600" />
            </div>
            <div>
              <p className="text-sm text-slate-500 dark:text-slate-400">Available Credits</p>
              <p className="text-3xl font-bold text-slate-900 dark:text-white">
                {formatCredits(account?.credits_remaining)}
              </p>
              <p className="text-sm text-slate-500 dark:text-slate-400 mt-1">
                ≈ ${((account?.credits_remaining || 0) * 9.99).toFixed(2)} value
              </p>
            </div>
          </div>
        </Card>

        {/* Storage */}
        <Card>
          <div className="flex items-center space-x-4">
            <div className="p-4 rounded-xl bg-primary-100 dark:bg-primary-900/30">
              <HardDrive className="w-8 h-8 text-primary-600" />
            </div>
            <div>
              <p className="text-sm text-slate-500 dark:text-slate-400">Storage Used</p>
              <p className="text-3xl font-bold text-slate-900 dark:text-white">
                {account?.storage_used_bytes ? formatBytes(account.storage_used_bytes) : '—'}
              </p>
              <p className="text-sm text-slate-500 dark:text-slate-400 mt-1">
                {account?.storage_used_bytes ? 'across all snapshots' : 'No backups yet'}
              </p>
            </div>
          </div>
        </Card>
      </div>

      {/* Account Details */}
      <Card title="Account Details">
        <div className="space-y-4">
          <div className="flex items-center justify-between py-2 border-b border-slate-200 dark:border-slate-700">
            <span className="text-sm text-slate-500 dark:text-slate-400">Status</span>
            <span className="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-400 capitalize">
              {account?.status || 'unknown'}
            </span>
          </div>
          <div className="flex items-center justify-between py-2 border-b border-slate-200 dark:border-slate-700">
            <span className="text-sm text-slate-500 dark:text-slate-400">Certificate Hash</span>
            <span className="font-mono text-sm text-slate-900 dark:text-white">
              {account?.cert_hash ? `${account.cert_hash.substring(0, 16)}...` : '-'}
            </span>
          </div>
          <div className="flex items-center justify-between py-2">
            <span className="text-sm text-slate-500 dark:text-slate-400">Registered</span>
            <span className="text-sm text-slate-900 dark:text-white">
              {account?.registered_at ? formatDateTime(account.registered_at) : '-'}
            </span>
          </div>
        </div>
      </Card>

      {/* Data Backend Info */}
      <Card
        title="Data Backend"
        subtitle="Connection details for your backup storage"
        action={
          credentials?.has_credentials ? (
            <button onClick={() => setShowRotateModal(true)} className="btn-secondary text-sm">
              <RefreshCw className="w-4 h-4 mr-2" />
              Rotate Credentials
            </button>
          ) : undefined
        }
      >
        <div className="space-y-4">
          <div className="flex items-center justify-between py-2 border-b border-slate-200 dark:border-slate-700">
            <span className="text-sm text-slate-500 dark:text-slate-400">Backend Type</span>
            <span className="inline-flex items-center space-x-2">
              <Database className="w-4 h-4 text-indigo-600" />
              <span className="text-sm font-medium text-slate-900 dark:text-white">
                {credentials?.data_backend === 's3' ? 'S3 (AWS Sig V4) via Tor' : 'REST via Tor'}
              </span>
            </span>
          </div>
          {credentials?.has_credentials && (
            <>
              <div className="flex items-center justify-between py-2 border-b border-slate-200 dark:border-slate-700">
                <span className="text-sm text-slate-500 dark:text-slate-400">Access Key ID</span>
                <span className="font-mono text-sm text-slate-900 dark:text-white">
                  {credentials.access_key_id}
                </span>
              </div>
              <div className="flex items-center justify-between py-2">
                <span className="text-sm text-slate-500 dark:text-slate-400">Bucket Name</span>
                <span className="font-mono text-sm text-slate-900 dark:text-white">
                  {credentials.bucket_name}
                </span>
              </div>
            </>
          )}
          <Alert type="info">
            <p className="text-sm">
              Data operations are encrypted end-to-end and routed through Tor.
              {credentials?.has_credentials
                ? ' Credential rotation is available via the CLI in advanced mode.'
                : ' Your account uses legacy REST authentication.'}
            </p>
          </Alert>
        </div>
      </Card>

      {/* Add Credits */}
      <Card title="Add Credits" subtitle="Buy credits with Monero, Litecoin, or a card">
        <div className="space-y-4">
          {/* Payment method */}
          <div>
            <label className="label">Payment method</label>
            <div className="grid grid-cols-3 gap-2">
              {([
                { id: 'xmr', label: 'Monero (XMR)', hint: 'Most private' },
                { id: 'ltc', label: 'Litecoin (LTC)', hint: 'Private' },
                { id: 'card', label: 'Card → LTC', hint: 'Convenient' },
              ] as const).map((m) => (
                <button
                  key={m.id}
                  type="button"
                  onClick={() => {
                    setPaymentMethod(m.id);
                    if (m.id === 'card') setCreditsAmount((c) => Math.max(2, c));
                    resetIntents();
                  }}
                  className={`px-3 py-2 rounded-lg border text-sm text-left ${
                    paymentMethod === m.id
                      ? 'border-accent-500 bg-accent-50 dark:bg-accent-900/20'
                      : 'border-slate-200 dark:border-slate-700 hover:border-slate-300'
                  }`}
                >
                  <span className="block font-medium text-slate-900 dark:text-white">{m.label}</span>
                  <span className="block text-xs text-slate-500 dark:text-slate-400">{m.hint}</span>
                </button>
              ))}
            </div>
          </div>

          {paymentMethod === 'card' && (
            <Alert type="info">
              <p className="text-sm">
                Card purchases have a <strong>minimum of 2 credits (~$20)</strong>. Card on-ramps
                enforce a ~$17 floor — the card processor's minimum plus the Litecoin exchange's
                per-swap minimum — so a single credit can't be bought by card. For 1 credit or any
                smaller amount, pay with <strong>Monero or Litecoin directly</strong>: no minimum,
                and more private.
              </p>
            </Alert>
          )}

          {/* Amount selector */}
          <div>
            <label className="label">Credits to purchase</label>
            <div className="flex items-center space-x-3">
              <input
                type="number"
                min={paymentMethod === 'card' ? 2 : 1}
                max={100}
                step={1}
                value={creditsAmount}
                onChange={(e) => {
                  setCreditsAmount(
                    Math.max(paymentMethod === 'card' ? 2 : 1, Math.floor(Number(e.target.value))),
                  );
                  resetIntents();
                }}
                className="input w-32"
              />
              <span className="text-sm text-slate-500 dark:text-slate-400">
                = {creditsAmount} TB/month · ${(creditsAmount * 9.99).toFixed(2)}
              </span>
            </div>
          </div>

          <button
            onClick={paymentMethod === 'xmr' ? handleGetXMRAddress : handleGetLTCIntent}
            disabled={isCreatingIntent || creditsAmount < (paymentMethod === 'card' ? 2 : 1)}
            className="btn-primary"
          >
            {isCreatingIntent ? (
              <>
                <Loader2 className="w-4 h-4 mr-2 animate-spin" />
                Getting address...
              </>
            ) : paymentMethod === 'xmr' ? (
              'Get XMR Payment Address'
            ) : paymentMethod === 'ltc' ? (
              'Get LTC Payment Address'
            ) : (
              'Continue to card payment'
            )}
          </button>

          {intentError && (
            <Alert type="error">
              <div className="flex items-start space-x-2">
                <AlertCircle className="w-4 h-4 mt-0.5 flex-shrink-0" />
                <p className="text-sm">{intentError}</p>
              </div>
            </Alert>
          )}

          {/* XMR intent result */}
          {paymentMethod === 'xmr' && paymentIntent && (
            <div className="space-y-3 p-4 bg-slate-50 dark:bg-slate-700/50 rounded-lg">
              <div className="flex items-center justify-between">
                <span className="text-sm text-slate-500 dark:text-slate-400">Amount (XMR)</span>
                <span className="font-mono font-semibold text-slate-900 dark:text-white">
                  {paymentIntent.amount_xmr} XMR
                </span>
              </div>
              <div className="flex items-center justify-between">
                <span className="text-sm text-slate-500 dark:text-slate-400">Credits</span>
                <span className="text-sm text-slate-900 dark:text-white">
                  {paymentIntent.credits_requested}
                </span>
              </div>
              <div className="flex items-center justify-between">
                <span className="text-sm text-slate-500 dark:text-slate-400">Rate locked until</span>
                <span className="text-sm text-slate-900 dark:text-white">
                  {formatDateTime(paymentIntent.expires_at)}
                </span>
              </div>
              <div>
                <label className="label">Payment Address (Monero XMR)</label>
                <div className="flex items-center space-x-2">
                  <input
                    type="text"
                    value={paymentIntent.payment_address}
                    readOnly
                    className="input font-mono text-xs"
                  />
                  <button
                    onClick={() => handleCopy(paymentIntent.payment_address)}
                    className="btn-secondary flex-shrink-0"
                    title="Copy address"
                  >
                    {copied ? (
                      <CheckCircle className="w-4 h-4 text-green-600" />
                    ) : (
                      <Copy className="w-4 h-4" />
                    )}
                  </button>
                </div>
              </div>
            </div>
          )}

          {/* LTC intent result (Litecoin or Card) */}
          {paymentMethod !== 'xmr' && ltcIntent && (
            <div className="space-y-3 p-4 bg-slate-50 dark:bg-slate-700/50 rounded-lg">
              <div className="flex items-center justify-between">
                <span className="text-sm text-slate-500 dark:text-slate-400">Amount (LTC)</span>
                <span className="font-mono font-semibold text-slate-900 dark:text-white">
                  ~{ltcAmountStr} LTC
                </span>
              </div>
              <div className="flex items-center justify-between">
                <span className="text-sm text-slate-500 dark:text-slate-400">Credits</span>
                <span className="text-sm text-slate-900 dark:text-white">{creditsAmount}</span>
              </div>
              <div className="flex items-center justify-between">
                <span className="text-sm text-slate-500 dark:text-slate-400">Rate locked until</span>
                <span className="text-sm text-slate-900 dark:text-white">
                  {formatDateTime(ltcIntent.expires_at)}
                </span>
              </div>
              <div>
                <label className="label">Payment Address (Litecoin LTC)</label>
                <div className="flex items-center space-x-2">
                  <input
                    type="text"
                    value={ltcIntent.payment_address}
                    readOnly
                    className="input font-mono text-xs"
                  />
                  <button
                    onClick={() => handleCopy(ltcIntent.payment_address)}
                    className="btn-secondary flex-shrink-0"
                    title="Copy address"
                  >
                    {copied ? (
                      <CheckCircle className="w-4 h-4 text-green-600" />
                    ) : (
                      <Copy className="w-4 h-4" />
                    )}
                  </button>
                </div>
              </div>

              {ltcStatus?.status === 'underpaid' && (
                <Alert type="warning">
                  <p className="text-sm">
                    <strong>Underpaid so far.</strong> We've received {ltcStatus.received_amount_ltc} of{' '}
                    {ltcStatus.expected_amount_ltc} LTC. Send about{' '}
                    <strong>${ltcStatus.remaining_amount_usd} more</strong> (≈ {ltcStatus.remaining_amount_ltc} LTC) to
                    the same address above to complete your {ltcStatus.credits_requested}-credit purchase.
                  </p>
                </Alert>
              )}
              {ltcStatus?.status === 'sufficient' && (
                <Alert type="success">
                  <p className="text-sm">
                    Payment received — your credits are added once it confirms (≈6 confirmations).
                  </p>
                </Alert>
              )}

              {paymentMethod === 'card' && (
                <CardOnramp
                  ltcAddress={ltcIntent.payment_address}
                  ltcAmount={ltcAmountStr}
                  usdAmount={(creditsAmount * 9.99).toFixed(2)}
                />
              )}
            </div>
          )}

          <Alert type="info">
            <p className="text-sm">
              {paymentMethod === 'xmr'
                ? 'Send the exact XMR amount to the address. Credits are added automatically after 10 confirmations (~20 minutes); the rate is locked for 30 minutes.'
                : paymentMethod === 'ltc'
                ? 'Send LTC to the address. Any amount is credited at the locked rate while in-window; the remainder carries forward. Credits are added after 6 confirmations.'
                : 'Continue to Guardarian above to pay by card; the Litecoin is sent to your payment address and credited after 6 confirmations. Card payments reduce your anonymity (see the notice above).'}
            </p>
          </Alert>
        </div>
      </Card>

      {/* Pricing Info */}
      <Card title="Pricing">
        <div className="overflow-x-auto">
          <table className="w-full">
            <thead>
              <tr className="border-b border-slate-200 dark:border-slate-700">
                <th className="text-left py-2 text-sm font-medium text-slate-500 dark:text-slate-400">Item</th>
                <th className="text-right py-2 text-sm font-medium text-slate-500 dark:text-slate-400">Rate</th>
              </tr>
            </thead>
            <tbody className="divide-y divide-slate-200 dark:divide-slate-700">
              <tr>
                <td className="py-3">
                  <p className="font-medium text-slate-900 dark:text-white">Storage</p>
                  <p className="text-sm text-slate-500 dark:text-slate-400">All snapshots, instant access</p>
                </td>
                <td className="py-3 text-right">
                  <p className="font-medium text-slate-900 dark:text-white">1 credit / TB / month</p>
                  <p className="text-sm text-slate-500 dark:text-slate-400">$9.99 per credit</p>
                </td>
              </tr>
              <tr>
                <td className="py-3">
                  <p className="font-medium text-slate-900 dark:text-white">Retrieval</p>
                  <p className="text-sm text-slate-500 dark:text-slate-400">Restore from any snapshot</p>
                </td>
                <td className="py-3 text-right">
                  <p className="font-medium text-slate-900 dark:text-white">Free</p>
                  <p className="text-sm text-slate-500 dark:text-slate-400">Up to 2× storage/month</p>
                </td>
              </tr>
            </tbody>
          </table>
        </div>
      </Card>

      {/* Credential Rotation Confirmation Modal */}
      <Modal
        isOpen={showRotateModal}
        onClose={() => setShowRotateModal(false)}
        title="Rotate S3 Credentials"
      >
        <div className="space-y-4">
          <Alert type="warning">
            <div className="flex items-start">
              <Key className="w-4 h-4 mr-2 mt-0.5 flex-shrink-0" />
              <div>
                <p className="font-medium">This will invalidate your current credentials</p>
                <p className="text-sm mt-1">
                  Your old secret access key will stop working immediately. The new key will be
                  saved to your backup key file automatically.
                </p>
              </div>
            </div>
          </Alert>
          <div className="flex justify-end space-x-3">
            <button onClick={() => setShowRotateModal(false)} className="btn-secondary">
              Cancel
            </button>
            <button
              onClick={handleRotateCredentials}
              disabled={isRotating}
              className="btn-primary"
            >
              {isRotating ? (
                <>
                  <div className="animate-spin rounded-full h-4 w-4 border-2 border-white border-t-transparent mr-2"></div>
                  Rotating...
                </>
              ) : (
                'Rotate Credentials'
              )}
            </button>
          </div>
        </div>
      </Modal>
    </div>
  );
}
