/**
 * BillingDataView (Statistiken)
 * 
 * Unified statistics page with internal tabs:
 * - Tab "Übersicht": KPI grid with cost, balance, storage metrics
 * - Tab "Diagramme": Charts with pie/bar toggle, cost trends
 * - Tab "Transaktionen": Transaction table with scope filter
 */

import React, { useState, useEffect, useMemo, useCallback } from 'react';
import { useSearchParams } from 'react-router-dom';
import { FormGeneratorTable, ColumnConfig } from '../../components/FormGenerator/FormGeneratorTable';
import { FormGeneratorReport } from '../../components/FormGenerator/FormGeneratorReport';
import type { ReportSection, ReportFilterState, ReportChartDataPoint } from '../../components/FormGenerator/FormGeneratorReport';
import api from '../../api';
import { useBilling } from '../../hooks/useBilling';
import { UserTransaction } from '../../api/billingApi';
import { formatBinaryDataSizeFromMebibytes } from '../../utils/formatDataSize';
import { useLanguage } from '../../providers/language/LanguageContext';
import styles from './Billing.module.css';

type TranslateFn = (key: string, params?: Record<string, string | number>) => string;

// ============================================================================
// HELPER: Currency formatter
// ============================================================================

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

// ============================================================================
// TYPES
// ============================================================================

interface ViewStatistics {
  totalCost: number;
  transactionCount: number;
  costByProvider: Record<string, number>;
  costByModel: Record<string, number>;
  costByFeature: Record<string, number>;
  costByMandate: Record<string, number>;
  timeSeries: Array<{ date: string; cost: number; count: number }>;
}

interface DataVolumeInfo {
  mandateId: string;
  mandateName: string;
  usedMB: number;
  filesMB: number;
  ragIndexMB: number;
  maxDataVolumeMB: number | null;
  percentUsed: number | null;
  warning: boolean;
}

// ============================================================================
// TAB NAVIGATION COMPONENT
// ============================================================================

type TabType = 'overview' | 'diagrams' | 'transactions';

interface TabNavProps {
  activeTab: TabType;
  onTabChange: (tab: TabType) => void;
}

const TabNav: React.FC<TabNavProps> = ({ activeTab, onTabChange }) => {
  const { t } = useLanguage();
  const _navLinkStyle = (isActive: boolean) => ({
    padding: '8px 16px',
    textDecoration: 'none',
    borderRadius: '4px',
    backgroundColor: isActive ? 'var(--primary-color, #F25843)' : 'transparent',
    color: isActive ? 'white' : 'var(--color-text, #e0e0e0)',
    fontWeight: isActive ? 600 : 400,
    cursor: 'pointer',
    border: 'none',
    fontSize: '14px',
  });

  return (
    <nav style={{
      display: 'flex',
      gap: '8px',
      marginBottom: '24px',
      borderBottom: '1px solid var(--color-border, #333)',
      paddingBottom: '8px'
    }}>
      <button onClick={() => onTabChange('overview')} style={_navLinkStyle(activeTab === 'overview')}>
        {t('Übersicht')}
      </button>
      <button onClick={() => onTabChange('diagrams')} style={_navLinkStyle(activeTab === 'diagrams')}>
        {t('Diagramme')}
      </button>
      <button onClick={() => onTabChange('transactions')} style={_navLinkStyle(activeTab === 'transactions')}>
        {t('Transaktionen')}
      </button>
    </nav>
  );
};

// ============================================================================
// HELPERS: Convert viewStats to ReportSection arrays
// ============================================================================

function _recordToChartData(record: Record<string, number>, t: TranslateFn): ReportChartDataPoint[] {
  return Object.entries(record)
    .sort((a, b) => b[1] - a[1])
    .map(([key, value]) => ({ key: key || t('—'), value }));
}

function _buildOverviewSections(
  viewStats: ViewStatistics,
  totalBalance: number,
  totalStorageMB: number,
  t: TranslateFn,
): ReportSection[] {
  const topProvider = Object.entries(viewStats.costByProvider).sort((a, b) => b[1] - a[1])[0];
  const topModel = Object.entries(viewStats.costByModel || {}).sort((a, b) => b[1] - a[1])[0];
  const topFeature = Object.entries(viewStats.costByFeature).sort((a, b) => b[1] - a[1])[0];

  return [
    {
      type: 'kpiGrid',
      items: [
        {
          label: t('Gesamtkosten'),
          value: _formatCurrency(viewStats.totalCost),
          subtitle: t('{n} Transaktionen', { n: String(viewStats.transactionCount) }),
        },
        {
          label: t('Anbieter'),
          value: Object.keys(viewStats.costByProvider).length,
          subtitle: topProvider ? t('Top: {name}', { name: topProvider[0] }) : t('Keine Nutzung'),
        },
        {
          label: t('Modelle'),
          value: Object.keys(viewStats.costByModel || {}).length,
          subtitle: topModel ? t('Top: {name}', { name: topModel[0] }) : t('Keine Nutzung'),
        },
        {
          label: t('Features'),
          value: Object.keys(viewStats.costByFeature).length,
          subtitle: topFeature ? t('Top: {name}', { name: topFeature[0] }) : t('Keine Nutzung'),
        },
        {
          label: t('Guthaben'),
          value: _formatCurrency(totalBalance),
        },
        {
          label: t('Speicher'),
          value: formatBinaryDataSizeFromMebibytes(totalStorageMB),
        },
      ]
    },
  ];
}

function _buildDiagramSections(viewStats: ViewStatistics, chartMode: 'pie' | 'bar', t: TranslateFn): ReportSection[] {
  const timeSeriesData: ReportChartDataPoint[] = viewStats.timeSeries.map(ts => ({
    key: ts.date,
    value: ts.cost
  }));

  const avgCost = viewStats.transactionCount > 0
    ? viewStats.totalCost / viewStats.transactionCount
    : 0;

  const chartType = chartMode === 'pie' ? 'pieChart' : 'horizontalBar';

  return [
    {
      type: 'kpiGrid',
      items: [
        { label: t('Gesamtkosten'), value: _formatCurrency(viewStats.totalCost), subtitle: t('{n} Transaktionen', { n: String(viewStats.transactionCount) }) },
        { label: t('Durchschnitt'), value: _formatCurrency(avgCost), subtitle: t('pro Transaktion') },
        { label: t('Anbieter'), value: Object.keys(viewStats.costByProvider).length },
        { label: t('Modelle'), value: Object.keys(viewStats.costByModel || {}).length },
        { label: t('Features'), value: Object.keys(viewStats.costByFeature).length },
        { label: t('Mandanten'), value: Object.keys(viewStats.costByMandate).length },
      ]
    },
    {
      type: 'barChart',
      title: t('Kostenentwicklung'),
      data: timeSeriesData,
      formatValue: _formatCurrency,
      span: 'full' as const
    },
    {
      type: chartType,
      title: t('Kosten nach Anbieter'),
      data: _recordToChartData(viewStats.costByProvider, t),
      formatValue: _formatCurrency,
      donut: chartMode === 'pie',
      span: 'half' as const
    },
    {
      type: chartType,
      title: t('Kosten nach Modell'),
      data: _recordToChartData(viewStats.costByModel || {}, t),
      formatValue: _formatCurrency,
      donut: chartMode === 'pie',
      span: 'half' as const
    },
    {
      type: chartType,
      title: t('Kosten nach Feature'),
      data: _recordToChartData(viewStats.costByFeature, t),
      formatValue: _formatCurrency,
      donut: chartMode === 'pie',
      span: 'half' as const
    },
    {
      type: chartType,
      title: t('Kosten nach Mandant'),
      data: _recordToChartData(viewStats.costByMandate, t),
      formatValue: _formatCurrency,
      donut: chartMode === 'pie',
      span: 'half' as const
    },
  ];
}

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

export const BillingDataView: React.FC = () => {
  const { t } = useLanguage();
  const [activeTab, setActiveTab] = useState<TabType>('overview');
  const [searchParams, setSearchParams] = useSearchParams();
  const [checkoutMessage, setCheckoutMessage] = useState<{ type: 'success' | 'error'; text: string } | null>(null);
  const [chartMode, setChartMode] = useState<'pie' | 'bar'>('pie');
  const [onlyMyData, setOnlyMyData] = useState(false);
  
  // Scope filter: 'personal' | 'all' | mandateId
  const [selectedScope, setSelectedScope] = useState<string>('personal');
  
  // Dashboard state (for Overview tab)
  const { 
    balances, 
    loading: dashboardLoading,
    refetch: refetchBalances,
  } = useBilling();

  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) {
          setCheckoutMessage({ type: 'error', text: t('Zahlung abgebrochen.') });
        }
        return;
      }

      if (!sessionIdParam) {
        if (!cancelled) {
          setCheckoutMessage({ type: 'success', text: t('Zahlung erfolgreich. Guthaben wird gutgeschrieben.') });
        }
        refetchBalances();
        return;
      }

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

    _confirmCheckoutIfNeeded();

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

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

  // Statistics state (shared by Overview and Statistics tabs)
  const [viewStats, setViewStats] = useState<ViewStatistics | null>(null);
  const [statsLoading, setStatsLoading] = useState(false);

  // Storage volume state (for Statistics tab)
  const [storageData, setStorageData] = useState<DataVolumeInfo[]>([]);
  const [, setStorageLoading] = useState(false);

  // Transactions state (for Transactions tab)
  const [transactions, setTransactions] = useState<UserTransaction[]>([]);
  const [transactionsLoading, setTransactionsLoading] = useState(false);
  const [transactionsError, setTransactionsError] = useState<string | null>(null);
  const [transactionsPagination, setTransactionsPagination] = useState<any>(null);

  // Unified scope params -- single source of truth for all tab API calls
  // "nur meine Daten" is an additional filter on top of the dropdown scope
  const _scopeParams = useMemo((): Record<string, string> => {
    const params: Record<string, string> = {};
    if (selectedScope === 'personal') {
      params.scope = 'personal';
    } else if (selectedScope === 'all') {
      params.scope = 'all';
    } else {
      params.scope = 'mandate';
      params.mandateId = selectedScope;
    }
    if (onlyMyData) {
      params.onlyMine = 'true';
    }
    return params;
  }, [selectedScope, onlyMyData]);

  // Load aggregated statistics from the view/statistics route
  const _loadViewStatistics = useCallback(async (period: string, year: number, month?: number) => {
    try {
      setStatsLoading(true);
      const params: Record<string, string | number> = { period, year, ..._scopeParams };
      if (period === 'day' && month) {
        params.month = month;
      }
      const response = await api.get('/api/billing/view/statistics', { params });
      setViewStats(response.data);
    } catch (err: any) {
      console.error('Failed to load statistics:', err);
      setViewStats(null);
    } finally {
      setStatsLoading(false);
    }
  }, [_scopeParams]);

  // Handle filter changes from FormGeneratorReport (user changes period/year/month)
  const _handleStatsFilterChange = useCallback((filterState: ReportFilterState) => {
    const period = filterState.period || 'month';
    const year = filterState.year || new Date().getFullYear();
    const month = filterState.month;
    _loadViewStatistics(period, year, month);
  }, [_loadViewStatistics]);

  // Load storage volume for all accessible mandates
  const _loadStorageData = useCallback(async () => {
    const mandateIds = new Set<string>();
    for (const b of balances) {
      if (selectedScope === 'personal' || selectedScope === 'all' || selectedScope === b.mandateId) {
        mandateIds.add(b.mandateId);
      }
    }
    if (mandateIds.size === 0) {
      setStorageData([]);
      return;
    }

    setStorageLoading(true);
    try {
      const mandateNameMap = new Map(balances.map(b => [b.mandateId, b.mandateName]));
      const results = await Promise.all(
        Array.from(mandateIds).map(async (mid) => {
          try {
            const params: Record<string, string> = {};
            if (onlyMyData) params.onlyMine = 'true';
            const resp = await api.get(`/api/subscription/data-volume/${mid}`, { params });
            return { ...resp.data, mandateName: mandateNameMap.get(mid) || mid.slice(0, 8) } as DataVolumeInfo;
          } catch {
            return null;
          }
        })
      );
      setStorageData(results.filter((r): r is DataVolumeInfo => r !== null));
    } catch {
      setStorageData([]);
    } finally {
      setStorageLoading(false);
    }
  }, [balances, selectedScope, onlyMyData]);

  // Initial data load
  useEffect(() => {
    if (activeTab === 'overview' || activeTab === 'diagrams') {
      _loadViewStatistics('month', new Date().getFullYear());
      _loadStorageData();
    }
  }, [activeTab, _loadViewStatistics, _loadStorageData]);

  // Load transactions with pagination support + scope filter
  const _loadTransactions = useCallback(async (paginationParams?: any) => {
    try {
      setTransactionsLoading(true);
      setTransactionsError(null);
      
      const params: Record<string, string> = { ..._scopeParams };
      if (paginationParams && typeof paginationParams === 'object' && 'page' in paginationParams) {
        const pObj: any = {};
        if (paginationParams.page !== undefined) pObj.page = paginationParams.page;
        if (paginationParams.pageSize !== undefined) pObj.pageSize = paginationParams.pageSize;
        if (paginationParams.sort) pObj.sort = paginationParams.sort;
        if (paginationParams.filters) pObj.filters = paginationParams.filters;
        if (paginationParams.search) pObj.search = paginationParams.search;
        if (Object.keys(pObj).length > 0) {
          params.pagination = JSON.stringify(pObj);
        }
      }
      
      const response = await api.get('/api/billing/view/users/transactions', { params });
      const data = response.data;
      
      if (data && typeof data === 'object' && 'items' in data) {
        setTransactions(Array.isArray(data.items) ? data.items : []);
        if (data.pagination) {
          setTransactionsPagination(data.pagination);
        }
      } else {
        setTransactions(Array.isArray(data) ? data : []);
      }
    } catch (err: any) {
      console.error('Failed to load transactions:', err);
      setTransactionsError(err.response?.data?.detail || err.message || t('Fehler beim Laden der Transaktionen'));
    } finally {
      setTransactionsLoading(false);
    }
  }, [_scopeParams, t]);

  const _fetchTransactionFilterValues = useCallback(async (
    columnKey: string,
    crossFilters?: Record<string, any>,
  ): Promise<string[]> => {
    const params: Record<string, string> = {
      column: columnKey,
      ..._scopeParams,
    };
    if (crossFilters && Object.keys(crossFilters).length > 0) {
      params.pagination = JSON.stringify({ filters: crossFilters });
    }
    const resp = await api.get('/api/billing/view/users/transactions', { params: { ...params, mode: 'filterValues' } });
    return Array.isArray(resp.data) ? resp.data : [];
  }, [_scopeParams]);

  const transactionsHookData = useMemo(() => ({
    refetch: _loadTransactions,
    pagination: transactionsPagination || undefined,
    fetchFilterValues: _fetchTransactionFilterValues,
  }), [_loadTransactions, transactionsPagination, _fetchTransactionFilterValues]);

  // Table column definitions
  const columns: ColumnConfig[] = useMemo(() => [
    { key: 'createdAt', label: t('Datum'), type: 'timestamp' as any, sortable: true, width: 160 },
    { key: 'mandateName', label: t('Mandant'), type: 'text' as any, sortable: true, filterable: true, searchable: true, width: 150 },
    { key: 'userName', label: t('Benutzer'), type: 'text' as any, sortable: true, filterable: true, searchable: true, width: 150 },
    { key: 'transactionType', label: t('Typ'), type: 'text' as any, sortable: true, filterable: true, width: 100 },
    { key: 'description', label: t('Beschreibung'), type: 'text' as any, searchable: true, width: 250 },
    { key: 'aicoreProvider', label: t('Anbieter'), type: 'text' as any, sortable: true, filterable: true, width: 120 },
    { key: 'aicoreModel', label: t('Modell'), type: 'text' as any, sortable: true, filterable: true, width: 150 },
    { key: 'featureCode', label: t('Feature'), type: 'text' as any, sortable: true, filterable: true, width: 120 },
    { key: 'amount', label: t('Betrag (CHF)'), type: 'number' as any, sortable: true, width: 120 },
  ], [t]);

  const totalBalance = useMemo(() => {
    const filtered = selectedScope === 'personal' || selectedScope === 'all'
      ? balances
      : balances.filter(b => b.mandateId === selectedScope);
    return filtered.reduce((sum, b) => sum + (b.balance || 0), 0);
  }, [balances, selectedScope]);

  const totalStorageMB = useMemo(() => {
    return storageData.reduce((sum, s) => sum + (s.usedMB || 0), 0);
  }, [storageData]);

  const overviewSections = useMemo<ReportSection[]>(() => {
    if (!viewStats) return [];
    return _buildOverviewSections(viewStats, totalBalance, totalStorageMB, t);
  }, [viewStats, totalBalance, totalStorageMB, t]);

  const diagramSections = useMemo<ReportSection[]>(() => {
    if (!viewStats) return [];
    return _buildDiagramSections(viewStats, chartMode, t);
  }, [viewStats, chartMode, t]);

  // Period selector config (shared between overview and statistics)
  const periodSelectorConfig = useMemo(() => ({
    periods: ['month' as const, 'day' as const],
    defaultPeriod: 'month' as const,
    showYear: true,
    showMonth: true,
    defaultYear: new Date().getFullYear(),
    defaultMonth: new Date().getMonth() + 1
  }), []);

  // Build scope options from balances (mandates the user has access to)
  const scopeOptions = useMemo(() => {
    const options: Array<{ value: string; label: string }> = [
      { value: 'personal', label: t('Meine Kosten') },
    ];
    // Add mandate options from balances
    const seen = new Set<string>();
    for (const b of balances) {
      if (!seen.has(b.mandateId)) {
        seen.add(b.mandateId);
        options.push({ value: b.mandateId, label: t('Mandant: {name}', { name: b.mandateName }) });
      }
    }
    options.push({ value: 'all', label: t('Alle (RBAC)') });
    return options;
  }, [balances, t]);

  return (
    <div className={styles.billingDashboard}>
      <header className={styles.pageHeader}>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
          <div>
            <h1>{t('Statistiken')}</h1>
            <p className={styles.subtitle}>{t('Nutzung, Diagramme und Transaktionen')}</p>
          </div>
          <div style={{ display: 'flex', alignItems: 'center', gap: '12px' }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
              <label style={{ fontSize: '13px', opacity: 0.7 }}>{t('Kontext:')}</label>
              <select
                className={styles.select || ''}
                value={selectedScope}
                onChange={(e) => setSelectedScope(e.target.value)}
              >
                {scopeOptions.map(opt => (
                  <option key={opt.value} value={opt.value}>{opt.label}</option>
                ))}
              </select>
            </div>
            <label style={{ display: 'flex', alignItems: 'center', gap: '6px', fontSize: '13px', cursor: 'pointer' }}>
              <input
                type="checkbox"
                checked={onlyMyData}
                onChange={(e) => setOnlyMyData(e.target.checked)}
                style={{ cursor: 'pointer' }}
              />
              {t('nur meine Daten')}
            </label>
          </div>
        </div>
      </header>

      <TabNav activeTab={activeTab} onTabChange={setActiveTab} />

      {checkoutMessage && (
        <div className={checkoutMessage.type === 'success' ? styles.successMessage : styles.errorMessage} style={{ marginBottom: '1rem' }}>
          {checkoutMessage.text}
          {(successParam || canceledParam) && (
            <button type="button" onClick={_clearStripeParams} style={{ marginLeft: '1rem', background: 'none', border: 'none', cursor: 'pointer', textDecoration: 'underline', color: 'inherit' }}>{t('Schließen')}</button>
          )}
        </div>
      )}

      {/* ================================================================ */}
      {/* Tab: Übersicht (KPI overview) */}
      {/* ================================================================ */}
      {activeTab === 'overview' && (
        <section className={styles.section}>
          <FormGeneratorReport
            loading={statsLoading || dashboardLoading}
            sections={overviewSections}
            noDataMessage={t('Keine Statistiken verfügbar')}
            currencyCode="CHF"
          />
        </section>
      )}

      {/* ================================================================ */}
      {/* Tab: Diagramme */}
      {/* ================================================================ */}
      {activeTab === 'diagrams' && (
        <section className={styles.section}>
          <div style={{ display: 'flex', justifyContent: 'flex-end', marginBottom: '12px' }}>
            <div style={{
              display: 'inline-flex',
              borderRadius: '6px',
              overflow: 'hidden',
              border: '1px solid var(--border-color, #333)',
            }}>
              <button
                onClick={() => setChartMode('pie')}
                style={{
                  padding: '6px 14px',
                  fontSize: '13px',
                  border: 'none',
                  cursor: 'pointer',
                  background: chartMode === 'pie' ? 'var(--primary-color, #F25843)' : 'var(--bg-secondary, #2a2a2a)',
                  color: chartMode === 'pie' ? '#fff' : 'var(--color-text, #e0e0e0)',
                  fontWeight: chartMode === 'pie' ? 600 : 400,
                }}
              >
                {t('Pie')}
              </button>
              <button
                onClick={() => setChartMode('bar')}
                style={{
                  padding: '6px 14px',
                  fontSize: '13px',
                  border: 'none',
                  cursor: 'pointer',
                  background: chartMode === 'bar' ? 'var(--primary-color, #F25843)' : 'var(--bg-secondary, #2a2a2a)',
                  color: chartMode === 'bar' ? '#fff' : 'var(--color-text, #e0e0e0)',
                  fontWeight: chartMode === 'bar' ? 600 : 400,
                }}
              >
                {t('Balken')}
              </button>
            </div>
          </div>
          <FormGeneratorReport
            periodSelector={periodSelectorConfig}
            onFilterChange={_handleStatsFilterChange}
            loading={statsLoading}
            sections={diagramSections}
            noDataMessage={t('Keine Statistiken verfügbar')}
            currencyCode="CHF"
          />
        </section>
      )}

      {/* ================================================================ */}
      {/* Tab: Transaktionen */}
      {/* ================================================================ */}
      {activeTab === 'transactions' && (
        <div style={{ display: 'flex', flexDirection: 'column', flex: 1, minHeight: '500px' }}>
          {transactionsError && (
            <div className={styles.errorMessage}>
              {transactionsError}
            </div>
          )}

          <FormGeneratorTable
            key={`txn-${_scopeParams.scope}-${_scopeParams.mandateId ?? ''}-${onlyMyData}`}
            data={transactions}
            columns={columns}
            apiEndpoint="/api/billing/view/users/transactions"
            loading={transactionsLoading}
            pagination={true}
            pageSize={25}
            searchable={true}
            filterable={true}
            sortable={true}
            selectable={false}
            emptyMessage={t('Keine Transaktionen vorhanden')}
            onRefresh={_loadTransactions}
            hookData={transactionsHookData}
          />
        </div>
      )}

    </div>
  );
};

export default BillingDataView;
