/**
 * TrusteePositionsView
 * 
 * Positions-Verwaltung für eine Trustee-Instanz.
 * Verwendet FormGeneratorTable für konsistentes UI.
 */

import React, { useState, useMemo, useEffect, useCallback } from 'react';
import { useTrusteePositions, useTrusteePositionOperations, TrusteePosition } from '../../../hooks/useTrustee';
import { useInstanceId } from '../../../hooks/useCurrentInstance';
import { useApiRequest } from '../../../hooks/useApi';
import { FormGeneratorTable, type ColumnConfig } from '../../../components/FormGenerator/FormGeneratorTable';
import { FormGeneratorForm } from '../../../components/FormGenerator/FormGeneratorForm';
import { FaSync, FaReceipt, FaDownload } from 'react-icons/fa';
import { useToast } from '../../../contexts/ToastContext';
import api from '../../../api';
import { fetchSyncStatus, syncPositionsToAccounting, type AccountingSyncStatus } from '../../../api/trusteeApi';
import { formatAmount, formatPercent } from '../../../utils/formatAmount';
import styles from '../../admin/Admin.module.css';

export const TrusteePositionsView: React.FC = () => {
  const instanceId = useInstanceId();
  const { request } = useApiRequest();
  const { showError, showSuccess } = useToast();
  const [downloadingDocIds, setDownloadingDocIds] = useState<Set<string>>(new Set());
  const [syncStatusItems, setSyncStatusItems] = useState<AccountingSyncStatus[]>([]);
  const [syncingPositionIds, setSyncingPositionIds] = useState<Set<string>>(new Set());

  // Entity hook
  const {
    items: positions,
    attributes,
    permissions,
    pagination,
    loading,
    error,
    refetch,
    fetchById,
    updateOptimistically,
    removeOptimistically,
  } = useTrusteePositions();

  // Operations hook
  const {
    handleDelete,
    handleCreate,
    handleUpdate,
    deletingItems,
  } = useTrusteePositionOperations();

  // Modal state
  const [editingPosition, setEditingPosition] = useState<TrusteePosition | null>(null);
  const [isCreateMode, setIsCreateMode] = useState(false);

  // Initial fetch
  useEffect(() => {
    if (instanceId) {
      refetch();
    }
  }, [instanceId]);

  // Load sync status for Sync-Status column
  useEffect(() => {
    if (!instanceId) return;
    let cancelled = false;
    fetchSyncStatus(request, instanceId)
      .then((data) => {
        if (!cancelled && data?.items) setSyncStatusItems(data.items);
      })
      .catch(() => {});
    return () => { cancelled = true; };
  }, [instanceId, request]);

  const _reloadSyncStatus = useCallback(() => {
    if (!instanceId) return;
    fetchSyncStatus(request, instanceId)
      .then((data) => data?.items && setSyncStatusItems(data.items))
      .catch(() => {});
  }, [instanceId, request]);

  const handleBatchSyncToAccounting = useCallback(
    async (rows: TrusteePosition[]) => {
      if (!instanceId || rows.length === 0) return;
      const ids = new Set(rows.map((r) => r.id));
      setSyncingPositionIds(ids);
      try {
        const res = await syncPositionsToAccounting(request, instanceId, rows.map((r) => r.id));
        if (res.errors === 0) {
          showSuccess('Sync', `${res.success} Position(en) erfolgreich synchronisiert.`);
        } else if (res.success > 0) {
          showError('Sync teilweise fehlgeschlagen', `${res.success} OK, ${res.errors} Fehler.`);
        } else {
          const firstError = res.results?.find((r: any) => !r.success);
          showError('Sync fehlgeschlagen', firstError?.errorMessage || `${res.errors} Fehler.`);
        }
        refetch();
        _reloadSyncStatus();
      } catch (err: any) {
        showError('Sync fehlgeschlagen', err.response?.data?.detail || err.message || 'Unbekannter Fehler.');
      } finally {
        setSyncingPositionIds((prev) => {
          const next = new Set(prev);
          ids.forEach((id) => next.delete(id));
          return next;
        });
      }
    },
    [instanceId, request, refetch, _reloadSyncStatus, showSuccess, showError]
  );

  const handleSingleSyncToAccounting = useCallback(
    async (row: TrusteePosition) => {
      await handleBatchSyncToAccounting([row]);
    },
    [handleBatchSyncToAccounting]
  );

  // Document download: same as TrusteeDocumentsView – first load document metadata, then /data blob with correct MIME type and filename
  const handleDownloadDocument = useCallback(
    async (documentId: string) => {
      if (!instanceId) return;
      setDownloadingDocIds(prev => new Set(prev).add(documentId));
      try {
        const docRes = await api.get(`/api/trustee/${instanceId}/documents/${documentId}`);
        const doc = docRes.data;
        if (!doc) {
          showError('Fehler', 'Dokument nicht gefunden.');
          return;
        }
        const response = await api.get(
          `/api/trustee/${instanceId}/documents/${documentId}/data`,
          { responseType: 'blob' }
        );
        const blob = new Blob([response.data], { type: doc.documentMimeType });
        const url = window.URL.createObjectURL(blob);
        const link = document.createElement('a');
        link.href = url;
        link.download = doc.documentName || 'document';
        document.body.appendChild(link);
        link.click();
        document.body.removeChild(link);
        window.URL.revokeObjectURL(url);
      } catch (err) {
        console.error('Download error:', err);
        showError('Fehler', 'Fehler beim Herunterladen des Dokuments.');
      } finally {
        setDownloadingDocIds(prev => {
          const next = new Set(prev);
          next.delete(documentId);
          return next;
        });
      }
    },
    [instanceId, showError]
  );

  // Hidden columns (not shown in table view, but available in edit form). documentId hidden – use Belege column instead.
  const hiddenColumns = ['desc', 'documentId', 'featureInstanceId', 'mandateId', 'taxCode', 'costCenter'];

  // Belege column: icon-only download (Beleg, optional later: Bank-Referenz). Max 0, 1 or 2 docs per position.
  const belegeColumn: ColumnConfig = useMemo(() => ({
    key: '_documentRefs',
    label: 'Belege',
    sortable: false,
    filterable: false,
    searchable: false,
    width: 56,
    minWidth: 48,
    maxWidth: 80,
    formatter: (_value: unknown, row: TrusteePosition) => {
      const docIds: string[] = [row.documentId, row.bankDocumentId].filter(Boolean) as string[];
      if (docIds.length === 0) return <span style={{ color: 'var(--text-secondary)' }}>—</span>;
      const labels = ['Beleg', 'Bank-Referenz'];
      return (
        <span style={{ display: 'inline-flex', gap: '4px', alignItems: 'center' }}>
          {docIds.map((id, i) => (
            <button
              key={id}
              type="button"
              onClick={(e) => {
                e.stopPropagation();
                handleDownloadDocument(id);
              }}
              disabled={downloadingDocIds.has(id)}
              title={labels[i] ?? `Dokument ${i + 1}`}
              style={{
                padding: '4px',
                minWidth: 28,
                height: 28,
                border: '1px solid var(--border-color, #e5e7eb)',
                borderRadius: 4,
                background: 'var(--bg-secondary, #f9fafb)',
                cursor: downloadingDocIds.has(id) ? 'wait' : 'pointer',
                display: 'inline-flex',
                alignItems: 'center',
                justifyContent: 'center',
              }}
            >
              {downloadingDocIds.has(id) ? (
                <span style={{ fontSize: 12 }}>…</span>
              ) : (
                <FaDownload size={14} />
              )}
            </button>
          ))}
        </span>
      );
    },
  }), [handleDownloadDocument, downloadingDocIds]);

  // Map positionId -> display sync status: prefer synced over error (successful retry hides old error)
  const syncByPosition = useMemo(() => {
    const m = new Map<string, { syncStatus: string; errorMessage?: string }>();
    for (const s of syncStatusItems) {
      const cur = m.get(s.positionId);
      const prefer =
        !cur ||
        s.syncStatus === 'synced' ||
        (cur.syncStatus !== 'synced' && s.syncStatus === 'error');
      if (prefer) m.set(s.positionId, { syncStatus: s.syncStatus, errorMessage: s.errorMessage });
    }
    return m;
  }, [syncStatusItems]);

  const syncStatusColumn: ColumnConfig = useMemo(
    () => ({
      key: '_syncStatus',
      label: 'Sync-Status',
      sortable: false,
      filterable: false,
      searchable: false,
      width: 160,
      minWidth: 100,
      maxWidth: 280,
      formatter: (_value: unknown, row: TrusteePosition) => {
        const info = syncByPosition.get(row.id);
        if (!info)
          return <span style={{ color: 'var(--text-secondary)' }}>—</span>;
        if (info.syncStatus === 'error')
          return (
            <span
              title={info.errorMessage || ''}
              style={{ color: 'var(--error-color, #dc2626)' }}
            >
              Fehler{info.errorMessage ? ': ' + (info.errorMessage.length > 40 ? info.errorMessage.slice(0, 37) + '…' : info.errorMessage) : ''}
            </span>
          );
        if (info.syncStatus === 'synced')
          return <span style={{ color: 'var(--success-color, #16a34a)' }}>Synchronisiert</span>;
        return <span>{info.syncStatus}</span>;
      },
    }),
    [syncByPosition]
  );

  // Desired column order: Belege (icons), Sync-Status, Erstellt am, Valuta, Tags, Company, then the rest
  const positionColumnOrder = [
    '_documentRefs',   // Belege (download icons)
    '_syncStatus',     // Sync-Status
    '_createdAt',      // Erstellt am
    'valuta',          // Valuta date
    'tags',
    'company',
  ];

  const amountFields = new Set(['bookingAmount', 'originalAmount']);
  const vatAmountFields = new Set(['vatAmount']);
  const percentFields = new Set(['vatPercentage']);

  // Generate columns from attributes + synthetic columns, then reorder
  const columns = useMemo(() => {
    const attrColumns = (attributes || [])
      .filter(attr => !hiddenColumns.includes(attr.name))
      .map(attr => {
        const col: ColumnConfig = {
          key: attr.name,
          label: attr.label || attr.name,
          type: attr.type as any,
          sortable: attr.sortable !== false,
          filterable: attr.filterable !== false,
          searchable: attr.searchable !== false,
          width: attr.width || 150,
          minWidth: attr.minWidth || 100,
          maxWidth: attr.maxWidth || 400,
        };
        if (amountFields.has(attr.name)) {
          col.formatter = (v: unknown) => formatAmount(v);
        } else if (vatAmountFields.has(attr.name)) {
          col.formatter = (v: unknown) => formatAmount(v, true);
        } else if (percentFields.has(attr.name)) {
          col.formatter = (v: unknown) => formatPercent(v);
        }
        return col;
      });

    const createdAtCol = {
      key: '_createdAt',
      label: 'Erstellt am',
      type: 'timestamp' as any,
      sortable: true,
      filterable: false,
      searchable: false,
      width: 150,
      minWidth: 120,
      maxWidth: 200,
    };

    const allColumns = [...attrColumns, belegeColumn, syncStatusColumn, createdAtCol];
    const byKey = new Map(allColumns.map(c => [c.key, c]));

    const ordered: typeof allColumns = [];
    for (const key of positionColumnOrder) {
      const col = byKey.get(key);
      if (col) {
        ordered.push(col);
        byKey.delete(key);
      }
    }
    const restKeys = allColumns.map(c => c.key).filter(k => byKey.has(k));
    for (const key of restKeys) {
      const col = byKey.get(key);
      if (col) ordered.push(col);
    }
    return ordered;
  }, [attributes, belegeColumn, syncStatusColumn]);

  // Check permissions
  const canCreate = permissions?.create !== 'n';
  const canUpdate = permissions?.update !== 'n';
  const canDelete = permissions?.delete !== 'n';

  // Handle edit click
  const handleEditClick = async (pos: TrusteePosition) => {
    const fullPos = await fetchById(pos.id);
    if (fullPos) {
      setEditingPosition(fullPos);
      setIsCreateMode(false);
    }
  };

  // Handle create click
  const handleCreateClick = () => {
    setEditingPosition(null);
    setIsCreateMode(true);
  };

  // Handle form submit
  const handleFormSubmit = async (data: Partial<TrusteePosition>) => {
    // Auto-calculate VAT if provided
    const processedData = { ...data };
    if (processedData.bookingAmount && processedData.vatPercentage && !processedData.vatAmount) {
      processedData.vatAmount = processedData.bookingAmount * (processedData.vatPercentage / 100);
    }
    
    if (isCreateMode) {
      const result = await handleCreate(processedData);
      if (result.success) {
        setIsCreateMode(false);
        refetch();
      }
    } else if (editingPosition) {
      const result = await handleUpdate(editingPosition.id, processedData);
      if (result.success) {
        setEditingPosition(null);
        refetch();
      }
    }
  };

  // Handle delete (confirmation handled by DeleteActionButton)
  const handleDeletePos = async (pos: TrusteePosition) => {
    removeOptimistically(pos.id);
    const success = await handleDelete(pos.id);
    if (!success) {
      refetch(); // Revert on error
    }
  };

  // Close modal
  const handleCloseModal = () => {
    setEditingPosition(null);
    setIsCreateMode(false);
  };

  // Form attributes (exclude system fields)
  const formAttributes = useMemo(() => {
    const excludedFields = ['id', 'mandateId', 'instanceId', '_createdBy', '_createdAt', '_modifiedAt', '_modifiedBy'];
    return (attributes || []).filter(attr => !excludedFields.includes(attr.name));
  }, [attributes]);

  // Handle inline update
  const handleInlineUpdate = async (itemId: string, updateData: Partial<TrusteePosition>, row: TrusteePosition) => {
    updateOptimistically(itemId, updateData);
    const result = await handleUpdate(itemId, { ...row, ...updateData });
    if (!result.success) {
      refetch(); // Revert on error
    }
  };

  if (error) {
    return (
      <div className={styles.adminPage}>
        <div className={styles.errorContainer}>
          <span className={styles.errorIcon}>⚠️</span>
          <p className={styles.errorMessage}>Fehler beim Laden der Positionen: {error}</p>
          <button className={styles.secondaryButton} onClick={() => refetch()}>
            <FaSync /> Erneut versuchen
          </button>
        </div>
      </div>
    );
  }

  return (
    <div className={styles.adminPage}>
      <div className={styles.pageHeader}>
        <div>
          <p className={styles.pageSubtitle}>Buchungspositionen verwalten</p>
        </div>
        <div className={styles.headerActions}>
          <button 
            className={styles.secondaryButton} 
            onClick={() => refetch()}
            disabled={loading}
          >
            <FaSync className={loading ? 'spinning' : ''} /> Aktualisieren
          </button>
          {canCreate && (
            <button 
              className={styles.primaryButton}
              onClick={handleCreateClick}
            >
              + Neue Position
            </button>
          )}
        </div>
      </div>

      <div className={styles.tableContainer}>
        {loading && (!positions || positions.length === 0) ? (
          <div className={styles.loadingContainer}>
            <div className={styles.spinner} />
            <span>Lade Positionen...</span>
          </div>
        ) : !positions || positions.length === 0 ? (
          <div className={styles.emptyState}>
            <FaReceipt className={styles.emptyIcon} />
            <h3 className={styles.emptyTitle}>Keine Positionen vorhanden</h3>
            <p className={styles.emptyDescription}>
              Erstellen Sie eine neue Position, um zu beginnen.
            </p>
            {canCreate && (
              <button 
                className={styles.primaryButton}
                onClick={handleCreateClick}
              >
                + Neue Position
              </button>
            )}
          </div>
        ) : (
          <FormGeneratorTable
            data={positions}
            columns={columns}
            apiEndpoint={instanceId ? `/api/trustee/${instanceId}/positions` : undefined}
            loading={loading}
            pagination={true}
            pageSize={25}
            searchable={true}
            filterable={true}
            sortable={true}
            selectable={true}
            batchActions={[
              {
                label: 'Buchhaltung synchronisieren',
                icon: FaSync,
                loading: syncingPositionIds.size > 0,
                onClick: handleBatchSyncToAccounting,
              },
            ]}
            actionButtons={[
              ...(canUpdate ? [{
                type: 'edit' as const,
                onAction: handleEditClick,
                title: 'Bearbeiten',
              }] : []),
              ...(canDelete ? [{
                type: 'delete' as const,
                title: 'Löschen',
                loading: (row: TrusteePosition) => deletingItems.has(row.id),
              }] : []),
            ]}
            customActions={[
              {
                id: 'sync-accounting',
                icon: <FaSync />,
                title: 'In Buchhaltung synchronisieren',
                onClick: handleSingleSyncToAccounting,
                loading: (row: TrusteePosition) => syncingPositionIds.has(row.id),
              },
            ]}
            onDelete={handleDeletePos}
            hookData={{
              refetch,
              permissions,
              pagination,
              handleDelete,
              handleInlineUpdate,
              updateOptimistically,
            }}
            emptyMessage="Keine Positionen gefunden"
          />
        )}
      </div>

      {/* Create/Edit Modal */}
      {(editingPosition || isCreateMode) && (
        <div className={styles.modalOverlay} onClick={handleCloseModal}>
          <div className={styles.modal} onClick={e => e.stopPropagation()}>
            <div className={styles.modalHeader}>
              <h2 className={styles.modalTitle}>
                {isCreateMode ? 'Neue Position' : 'Position bearbeiten'}
              </h2>
              <button 
                className={styles.modalClose}
                onClick={handleCloseModal}
              >
                ✕
              </button>
            </div>
            <div className={styles.modalContent}>
              {formAttributes.length === 0 ? (
                <div className={styles.loadingContainer}>
                  <div className={styles.spinner} />
                  <span>Lade Formular...</span>
                </div>
              ) : (
                <FormGeneratorForm
                  attributes={formAttributes}
                  data={editingPosition || {
                    bookingCurrency: 'CHF',
                    originalCurrency: 'CHF',
                    bookingAmount: 0,
                    originalAmount: 0,
                    vatPercentage: 0,
                    vatAmount: 0,
                  }}
                  mode={isCreateMode ? 'create' : 'edit'}
                  onSubmit={handleFormSubmit}
                  onCancel={handleCloseModal}
                  submitButtonText={isCreateMode ? 'Erstellen' : 'Speichern'}
                  cancelButtonText="Abbrechen"
                  instanceId={instanceId}
                />
              )}
            </div>
          </div>
        </div>
      )}
    </div>
  );
};

export default TrusteePositionsView;
