/**
 * Billing Admin Page
 * 
 * Admin-Seite für Billing-Verwaltung (SysAdmin only).
 * - Settings verwalten
 * - Guthaben aufladen
 * - Konten übersicht
 */

import React, { useState, useEffect, useCallback, useMemo } from 'react';
import { Link, useSearchParams } from 'react-router-dom';
import { useBillingAdmin, type BillingSettings, type AccountSummary, type MandateUserSummary } from '../../hooks/useBilling';
import type { CheckoutCreateRequest } from '../../api/billingApi';
import { useUserMandates, type Mandate as UserMandateRow } from '../../hooks/useUserMandates';
import { useCurrentUser } from '../../hooks/useUsers';
import api from '../../api';
import { getUserDataCache } from '../../utils/userCache';
import styles from './Billing.module.css';

const _formatCurrency = (amount: number) => {
  return new Intl.NumberFormat('de-CH', {
    style: 'currency',
    currency: 'CHF'
  }).format(amount);
};

const _mandateDisplayLabel = (m: UserMandateRow): string => {
  if (m.label) return m.label;
  if (typeof m.name === 'object' && m.name) {
    const n = m.name as Record<string, string>;
    return n.de || n.en || Object.values(n)[0] || m.id;
  }
  return (m.name as string) || m.id;
};

// ============================================================================
// MANDATE SELECTOR
// ============================================================================

interface MandateSelectorProps {
  mandates: UserMandateRow[];
  loading: boolean;
  selectedMandateId: string | null;
  onSelect: (mandateId: string) => void;
}

const MandateSelector: React.FC<MandateSelectorProps> = ({
  mandates,
  loading,
  selectedMandateId,
  onSelect,
}) => (
  <div className={styles.formGroup}>
    <label>Mandant auswählen</label>
    <select
      className={styles.select}
      value={selectedMandateId || ''}
      onChange={e => onSelect(e.target.value)}
      disabled={loading}
    >
      <option value="">-- Mandant wählen --</option>
      {mandates.map(mandate => (
        <option key={mandate.id} value={mandate.id}>
          {_mandateDisplayLabel(mandate)}
        </option>
      ))}
    </select>
  </div>
);

// ============================================================================
// SETTINGS EDITOR
// ============================================================================

interface SettingsEditorProps {
  settings: BillingSettings | null;
  onSave: (settings: Partial<BillingSettings>) => Promise<void>;
  loading: boolean;
}

const SettingsEditor: React.FC<SettingsEditorProps> = ({ settings, onSave, loading }) => {
  const [formData, setFormData] = useState({
    billingModel: (settings?.billingModel === 'PREPAY_USER' ? 'PREPAY_USER' : 'PREPAY_MANDATE') as BillingSettings['billingModel'],
    defaultUserCredit: Number(settings?.defaultUserCredit ?? 0),
    warningThresholdPercent: Number(settings?.warningThresholdPercent ?? 10),
    notifyOnWarning: settings?.notifyOnWarning ?? true,
  });
  const [saving, setSaving] = useState(false);
  const [message, setMessage] = useState<{ type: 'success' | 'error'; text: string } | null>(null);
  
  useEffect(() => {
    if (settings) {
      setFormData({
        billingModel: settings.billingModel === 'PREPAY_USER' ? 'PREPAY_USER' : 'PREPAY_MANDATE',
        defaultUserCredit: Number(settings.defaultUserCredit ?? 0),
        warningThresholdPercent: Number(settings.warningThresholdPercent ?? 10),
        notifyOnWarning: settings.notifyOnWarning ?? true,
      });
    }
  }, [settings]);
  
  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    setSaving(true);
    setMessage(null);
    
    try {
      await onSave(formData);
      setMessage({ type: 'success', text: 'Einstellungen gespeichert!' });
    } catch (err: any) {
      setMessage({ type: 'error', text: err.message || 'Fehler beim Speichern' });
    } finally {
      setSaving(false);
    }
  };
  
  return (
    <div className={styles.adminSection}>
      <h3>Billing-Einstellungen</h3>
      
      {message && (
        <div className={message.type === 'success' ? styles.successMessage : styles.errorMessage}>
          {message.text}
        </div>
      )}
      
      <form onSubmit={handleSubmit}>
        <div className={styles.formRow}>
          <div className={styles.formGroup}>
            <label>Abrechnungsmodell</label>
            <select 
              className={styles.select}
              value={formData.billingModel}
              onChange={(e) => setFormData(prev => ({ ...prev, billingModel: e.target.value as BillingSettings['billingModel'] }))}
            >
              <option value="PREPAY_MANDATE">Prepaid (Mandant)</option>
              <option value="PREPAY_USER">Prepaid (Benutzer)</option>
            </select>
          </div>
          
          <div className={styles.formGroup}>
            <label>Standard-Guthaben (CHF)</label>
            <input 
              type="number"
              className={styles.input}
              value={formData.defaultUserCredit}
              onChange={(e) => setFormData(prev => ({ ...prev, defaultUserCredit: Number(e.target.value) }))}
              min="0"
              step="0.01"
            />
          </div>
        </div>
        
        <div className={styles.formRow}>
          <div className={styles.formGroup}>
            <label>Warnschwelle (%)</label>
            <input 
              type="number"
              className={styles.input}
              value={formData.warningThresholdPercent}
              onChange={(e) => setFormData(prev => ({ ...prev, warningThresholdPercent: Number(e.target.value) }))}
              min="0"
              max="100"
              step="1"
            />
          </div>
        </div>
        
        <div className={styles.formRow}>
          <div className={styles.formGroup}>
            <label>&nbsp;</label>
            <label style={{ display: 'flex', alignItems: 'center', gap: '8px', cursor: 'pointer' }}>
              <input 
                type="checkbox"
                checked={formData.notifyOnWarning}
                onChange={(e) => setFormData(prev => ({ ...prev, notifyOnWarning: e.target.checked }))}
              />
              Bei Warnung benachrichtigen
            </label>
          </div>
        </div>
        
        <button 
          type="submit" 
          className={`${styles.button} ${styles.buttonPrimary}`}
          disabled={saving || loading}
        >
          {saving ? 'Speichern...' : 'Einstellungen speichern'}
        </button>
      </form>
    </div>
  );
};

// ============================================================================
// CREDIT ADDER
// ============================================================================

interface CreditAdderProps {
  settings: BillingSettings | null;
  accounts: AccountSummary[];
  users: MandateUserSummary[];
  onAddCredit: (userId: string | undefined, amount: number, description: string) => Promise<any>;
}

const CreditAdder: React.FC<CreditAdderProps> = ({ settings, accounts, users, onAddCredit }) => {
  const [selectedUserId, setSelectedUserId] = useState<string>('');
  const [amount, setAmount] = useState<string>('');
  const [description, setDescription] = useState<string>('Manuelles Aufladen durch Admin');
  const [saving, setSaving] = useState(false);
  const [message, setMessage] = useState<{ type: 'success' | 'error'; text: string } | null>(null);
  
  const isPrepayUser = settings?.billingModel === 'PREPAY_USER';
  
  const accountsByUserId = accounts
    .filter(acc => acc.accountType === 'USER')
    .reduce((map, acc) => {
      if (acc.userId) map[acc.userId] = acc;
      return map;
    }, {} as Record<string, AccountSummary>);
  
  const _handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    const numAmount = parseFloat(amount);
    if (!numAmount || numAmount <= 0) {
      setMessage({ type: 'error', text: 'Betrag muss positiv sein' });
      return;
    }
    
    setSaving(true);
    setMessage(null);
    
    try {
      await onAddCredit(isPrepayUser ? selectedUserId : undefined, numAmount, description);
      setMessage({ type: 'success', text: `${_formatCurrency(numAmount)} erfolgreich gutgeschrieben.` });
      setAmount('');
    } catch (err: any) {
      setMessage({ type: 'error', text: err.message || 'Fehler beim Aufladen' });
    } finally {
      setSaving(false);
    }
  };
  
  return (
    <div className={styles.adminSection}>
      <h3>Guthaben manuell aufladen</h3>
      
      {message && (
        <div className={message.type === 'success' ? styles.successMessage : styles.errorMessage}>
          {message.text}
        </div>
      )}
      
      <form onSubmit={_handleSubmit}>
        {isPrepayUser && (
          <div className={styles.formRow}>
            <div className={styles.formGroup}>
              <label>Benutzer</label>
              <select 
                className={styles.select}
                value={selectedUserId}
                onChange={(e) => setSelectedUserId(e.target.value)}
                required
              >
                <option value="">-- Benutzer wählen --</option>
                {users.map((user) => {
                  const account = accountsByUserId[user.id];
                  const balanceInfo = account ? ` (${_formatCurrency(account.balance)})` : ' (kein Konto)';
                  return (
                    <option key={user.id} value={user.id}>
                      {user.displayName || user.username || user.id}{balanceInfo}
                    </option>
                  );
                })}
              </select>
            </div>
          </div>
        )}
        
        <div className={styles.formRow}>
          <div className={styles.formGroup}>
            <label>Betrag (CHF)</label>
            <input
              type="number"
              className={styles.input}
              value={amount}
              onChange={(e) => setAmount(e.target.value)}
              placeholder="z.B. 50"
              min="0.01"
              step="0.01"
              required
            />
          </div>
          <div className={styles.formGroup}>
            <label>Beschreibung</label>
            <input
              type="text"
              className={styles.input}
              value={description}
              onChange={(e) => setDescription(e.target.value)}
              placeholder="Beschreibung der Gutschrift"
            />
          </div>
        </div>
        
        <button 
          type="submit" 
          className={`${styles.button} ${styles.buttonPrimary}`}
          disabled={saving || (isPrepayUser && !selectedUserId) || !amount}
        >
          {saving ? 'Wird gutgeschrieben...' : 'Manuell aufladen'}
        </button>
      </form>
    </div>
  );
};

// ============================================================================
// ACCOUNTS OVERVIEW
// ============================================================================

interface AccountsOverviewProps {
  accounts: AccountSummary[];
  users: MandateUserSummary[];
  loading: boolean;
}

const AccountsOverview: React.FC<AccountsOverviewProps> = ({ accounts, users, loading }) => {
  const formatCurrency = (amount: number) => {
    return new Intl.NumberFormat('de-CH', {
      style: 'currency',
      currency: 'CHF'
    }).format(amount);
  };

  // Build a lookup map: userId -> display name
  const _userNameMap = useMemo(() => {
    const map = new Map<string, string>();
    for (const user of users) {
      const displayName = user.displayName
        || [user.firstName, user.lastName].filter(Boolean).join(' ')
        || user.username
        || user.id;
      map.set(user.id, displayName);
    }
    return map;
  }, [users]);
  
  if (loading) {
    return <div className={styles.loadingPlaceholder}>Lade Konten...</div>;
  }
  
  if (accounts.length === 0) {
    return <div className={styles.noData}>Keine Konten vorhanden</div>;
  }
  
  return (
    <div className={styles.adminSection}>
      <h3>Konten</h3>
      <div className={styles.accountsGrid}>
        {accounts.map((account) => (
          <div key={account.id} className={styles.accountCard}>
            <h4>{account.accountType === 'MANDATE' ? 'Mandanten-Konto' : 'Benutzer-Konto'}</h4>
            <div className={styles.accountInfo}>
              {account.userId && <span>User: {_userNameMap.get(account.userId) || account.userId}</span>}
              <span>Guthaben: <strong>{formatCurrency(account.balance)}</strong></span>
              <span>Status: {account.enabled ? 'Aktiv' : 'Deaktiviert'}</span>
            </div>
          </div>
        ))}
      </div>
    </div>
  );
};

// ============================================================================
// MANDATE ADMIN — STRIPE TOP-UP (same URL as SysAdmin billing admin)
// ============================================================================

interface MandateStripeTopUpProps {
  mandateId: string;
  createCheckout: (
    checkoutRequest: CheckoutCreateRequest,
    targetMandateId?: string
  ) => Promise<{ redirectUrl?: string } | null>;
}

const MandateStripeTopUp: React.FC<MandateStripeTopUpProps> = ({ mandateId, createCheckout }) => {
  const [amount, setAmount] = useState('');
  const [busy, setBusy] = useState(false);
  const [localMsg, setLocalMsg] = useState<string | null>(null);

  const _handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    const n = parseFloat(amount);
    if (!n || n <= 0) {
      setLocalMsg('Betrag muss positiv sein');
      return;
    }
    setBusy(true);
    setLocalMsg(null);
    try {
      const currentUser = getUserDataCache();
      const currentUrl = new URL(window.location.href);
      currentUrl.searchParams.delete('success');
      currentUrl.searchParams.delete('canceled');
      currentUrl.searchParams.delete('session_id');
      currentUrl.hash = '';
      const returnUrl = `${currentUrl.origin}${currentUrl.pathname}${currentUrl.search}`;
      const result = await createCheckout(
        { userId: currentUser?.id, amount: n, returnUrl },
        mandateId
      );
      if (result?.redirectUrl) {
        window.location.href = result.redirectUrl;
      }
    } catch (err: unknown) {
      const msg = err instanceof Error ? err.message : 'Checkout fehlgeschlagen';
      setLocalMsg(msg);
      setBusy(false);
    }
  };

  return (
    <div className={styles.adminSection}>
      <h3>Guthaben via Stripe aufladen</h3>
      <p style={{ fontSize: '13px', color: 'var(--text-secondary, #64748b)', marginTop: 0 }}>
        Sie werden zu Stripe weitergeleitet. Nach erfolgreicher Zahlung kehren Sie hierher zurück.
      </p>
      {localMsg && <div className={styles.errorMessage}>{localMsg}</div>}
      <form onSubmit={_handleSubmit}>
        <div className={styles.formRow}>
          <div className={styles.formGroup}>
            <label>Betrag (CHF)</label>
            <input
              type="number"
              className={styles.input}
              value={amount}
              onChange={e => setAmount(e.target.value)}
              placeholder="z.B. 50"
              min="0.01"
              step="0.01"
              required
            />
          </div>
        </div>
        <button
          type="submit"
          className={`${styles.button} ${styles.buttonPrimary}`}
          disabled={busy || !amount}
        >
          {busy ? 'Weiterleitung...' : 'Mit Stripe bezahlen'}
        </button>
      </form>
    </div>
  );
};

// ============================================================================
// MAIN COMPONENT
// ============================================================================

export const BillingAdmin: React.FC = () => {
  const [searchParams, setSearchParams] = useSearchParams();
  const { user: currentUser } = useCurrentUser();
  const isSysAdmin = currentUser?.isSysAdmin === true;

  const [selectedMandateId, setSelectedMandateId] = useState<string | null>(null);
  const [mandateList, setMandateList] = useState<UserMandateRow[]>([]);
  const [mandatesLoading, setMandatesLoading] = useState(true);

  const { fetchMandates } = useUserMandates();
  const {
    settings,
    accounts,
    users,
    loading,
    saveSettings,
    addCredit,
    loadAccounts,
    createCheckout,
  } = useBillingAdmin(selectedMandateId || undefined);
  
  const handleMandateSelect = (mandateId: string) => {
    setSelectedMandateId(mandateId || null);
  };
  
  const handleSaveSettings = useCallback(async (settingsUpdate: Partial<BillingSettings>) => {
    if (!selectedMandateId) return;
    await saveSettings(settingsUpdate);
  }, [selectedMandateId, saveSettings]);
  
  const _handleAddCredit = useCallback(async (userId: string | undefined, amount: number, description: string) => {
    if (!selectedMandateId) throw new Error('Mandant nicht ausgewählt');
    const result = await addCredit({ userId, amount, description });
    if (!result) throw new Error('Gutschrift konnte nicht erstellt werden');
    await loadAccounts();
    return result;
  }, [selectedMandateId, addCredit, loadAccounts]);

  useEffect(() => {
    let cancelled = false;
    (async () => {
      setMandatesLoading(true);
      try {
        const data = await fetchMandates();
        if (!cancelled) {
          setMandateList(Array.isArray(data) ? data : []);
        }
      } finally {
        if (!cancelled) setMandatesLoading(false);
      }
    })();
    return () => {
      cancelled = true;
    };
  }, [fetchMandates]);

  useEffect(() => {
    if (!isSysAdmin && mandateList.length === 1 && selectedMandateId === null) {
      setSelectedMandateId(mandateList[0].id);
    }
  }, [isSysAdmin, mandateList, selectedMandateId]);

  const [stripeReturnMessage, setStripeReturnMessage] = useState<{
    type: 'success' | 'error';
    text: string;
  } | null>(null);
  const successParam = searchParams.get('success');
  const canceledParam = searchParams.get('canceled');
  const sessionIdParam = searchParams.get('session_id');

  useEffect(() => {
    let cancelled = false;

    const _confirmCheckoutIfNeeded = async () => {
      if (successParam !== 'true') {
        if (canceledParam === 'true' && !cancelled) {
          setStripeReturnMessage({ type: 'error', text: 'Zahlung abgebrochen.' });
        }
        return;
      }

      if (!sessionIdParam) {
        if (!cancelled) {
          setStripeReturnMessage({
            type: 'success',
            text: 'Zahlung erfolgreich. Guthaben wird gutgeschrieben.',
          });
        }
        if (selectedMandateId) await loadAccounts(selectedMandateId);
        return;
      }

      try {
        await api.post('/api/billing/checkout/confirm', { sessionId: sessionIdParam });
        if (!cancelled) {
          setStripeReturnMessage({
            type: 'success',
            text: 'Zahlung erfolgreich. Guthaben wurde verbucht.',
          });
        }
      } catch (err: unknown) {
        const detail = (err as { response?: { data?: { detail?: string } } })?.response?.data?.detail;
        if (!cancelled) {
          setStripeReturnMessage({
            type: 'error',
            text:
              detail ||
              'Zahlung erfolgreich, aber Verbuchung konnte nicht bestätigt werden.',
          });
        }
      } finally {
        if (selectedMandateId) await loadAccounts(selectedMandateId);
      }
    };

    _confirmCheckoutIfNeeded();

    return () => {
      cancelled = true;
    };
  }, [successParam, canceledParam, sessionIdParam, selectedMandateId, loadAccounts]);

  const _clearStripeParams = useCallback(() => {
    searchParams.delete('success');
    searchParams.delete('canceled');
    searchParams.delete('session_id');
    setSearchParams(searchParams, { replace: true });
    setStripeReturnMessage(null);
  }, [searchParams, setSearchParams]);

  const showStripeForMandateAdmin = !isSysAdmin && !!selectedMandateId && !!settings;

  return (
    <div className={styles.billingDashboard}>
      <header className={styles.pageHeader}>
        <h1>Billing Administration</h1>
        <p className={styles.subtitle}>
          {isSysAdmin
            ? 'Verwaltung von Abrechnungseinstellungen und Guthaben'
            : 'Guthaben und Konten für Ihre Mandanten'}
        </p>
        {isSysAdmin && (
          <p style={{ marginTop: '8px' }}>
            <Link to="/admin/billing/mandates" style={{ color: 'var(--color-primary)' }}>
              Mandanten-Übersicht (Balances &amp; Transaktionen)
            </Link>
          </p>
        )}
      </header>

      {stripeReturnMessage && (
        <div
          className={
            stripeReturnMessage.type === 'success' ? styles.successMessage : styles.errorMessage
          }
          style={{ marginBottom: '1rem' }}
        >
          <div style={{ display: 'flex', justifyContent: 'space-between', gap: '12px', alignItems: 'center' }}>
            <span>{stripeReturnMessage.text}</span>
            <button type="button" className={styles.button} onClick={_clearStripeParams}>
              OK
            </button>
          </div>
        </div>
      )}

      <section className={styles.section}>
        <MandateSelector
          mandates={mandateList}
          loading={mandatesLoading}
          selectedMandateId={selectedMandateId}
          onSelect={handleMandateSelect}
        />
      </section>

      {selectedMandateId && (
        <>
          {isSysAdmin && (
            <SettingsEditor
              settings={settings}
              onSave={handleSaveSettings}
              loading={loading}
            />
          )}

          {isSysAdmin && (
            <CreditAdder
              settings={settings}
              accounts={accounts}
              users={users}
              onAddCredit={_handleAddCredit}
            />
          )}

          {showStripeForMandateAdmin && (
            <MandateStripeTopUp mandateId={selectedMandateId} createCheckout={createCheckout} />
          )}

          <AccountsOverview accounts={accounts} users={users} loading={loading} />
        </>
      )}

      {!selectedMandateId && (
        <div className={styles.noData}>Bitte wählen Sie einen Mandanten aus.</div>
      )}
    </div>
  );
};

export default BillingAdmin;
