import { useEffect, useMemo, useState } from 'react';
import { Helmet } from 'react-helmet';
import { Plus, Euro, FileText, TrendingDown, AlertCircle, Users, Eye, Edit, X } from 'lucide-react';
import KPIBar, { PeriodType } from '@/components/KPIBar';
import PrimaryButton_v2 from '@/components/PrimaryButton_v2';
import { useNavigate } from 'react-router-dom';
import { useAppDispatch, useAppSelector } from '@/store/hooks';
import { avoirStatus, getAllavoir } from '@/store/features/avoir/selectors';
import { Avoir } from '@/types/avoirType';
import { getAvoirs, selectAvoirAsync } from '@/store/features/avoir/thunk';
import { filterItemByPeriod, getPreviousPeriodItems } from '@/components/filter/ItemsFilter';
import { cn, formatDateFRCourt } from '@/lib/utils';
import DataTable from '@/components/ui/DataTable';
import { ModalAvoir } from '@/components/modal/ModalAvoir';
import { clientStatus, getAllClients } from '@/store/features/client/selectors';
import { articleStatus } from '@/store/features/article/selectors';
import { getArticles } from '@/store/features/article/thunk';
import { getClients } from '@/store/features/client/thunk';
import { Client } from '@/types/clientType';
import StatusBadge, { STATUS_LABELS } from '@/components/ui/StatusBadge';
import { SageDocumentType } from '@/types/sageTypes';
import ColumnSelector, { ColumnConfig } from '@/components/common/ColumnSelector';
import PeriodSelector from '@/components/common/PeriodSelector';
import ExportDropdown from '@/components/common/ExportDropdown';
import { useDashboardData } from '@/store/hooks/useAppData';
import AdvancedFilters from '@/components/common/AdvancedFilters';
import { Commercial } from '@/types/commercialType';
import { commercialsStatus, getAllcommercials } from '@/store/features/commercial/selectors';
import { getCommercials } from '@/store/features/commercial/thunk';

// ============================================
// CONSTANTES
// ============================================

const COLORS = {
  gray: 'bg-gray-400',
  yellow: 'bg-yellow-400',
  blue: 'bg-blue-400',
  green: 'bg-green-400',
};

// Labels de statut pour les avoirs
const AVOIR_STATUS_LABELS = {
  0: { label: 'Saisi', color: COLORS.gray },
  1: { label: 'Confirmé', color: COLORS.yellow },
  2: { label: 'A Facturer', color: COLORS.blue },
  3: { label: 'Facturé', color: COLORS.green },
} as const;

export type StatusCode = keyof typeof AVOIR_STATUS_LABELS;
type FilterType = 'all' | 'validated' | 'pending' | 'accounted';

interface KPIConfig {
  id: FilterType;
  title: string;
  icon: React.ElementType;
  color: string;
  getValue: (avoirs: Avoir[]) => number | string;
  getSubtitle: (avoirs: Avoir[], value: number | string) => string;
  getChange: (avoirs: Avoir[], value: number | string, period: PeriodType, allAvoirs: Avoir[]) => string;
  getTrend: (avoirs: Avoir[], value: number | string, period: PeriodType, allAvoirs: Avoir[]) => 'up' | 'down' | 'neutral';
  filter: (avoirs: Avoir[]) => Avoir[];
}

// ============================================
// CONFIGURATION DES COLONNES
// ============================================

const DEFAULT_COLUMNS: ColumnConfig[] = [
  { key: 'numero', label: 'N° Pièce', visible: true, locked: true },
  { key: 'client_code', label: 'Client', visible: true },
  { key: 'date', label: 'Date', visible: true },
  { key: 'total_ht_calcule', label: 'Montant HT', visible: true },
  { key: 'total_taxes_calcule', label: 'Montant TVA', visible: true },
  { key: 'total_ttc_calcule', label: 'Montant TTC', visible: true },
  { key: 'statut', label: 'Statut', visible: true },
];

// ============================================
// CONFIGURATION DES KPIs
// ============================================

const KPI_CONFIG: KPIConfig[] = [
  {
    id: 'all',
    title: 'Total Avoirs HT',
    icon: Euro,
    color: 'blue',
    getValue: (avoirs) => avoirs.reduce((sum, item) => sum + item.total_ht, 0),
    getSubtitle: (avoirs) => {
      const totalTTC = avoirs.reduce((sum, item) => sum + item.total_ttc, 0);
      return `${totalTTC.toLocaleString('fr-FR', { minimumFractionDigits: 2 })}€ TTC`;
    },
    getChange: (avoirs, value, period, allAvoirs) => {
      const previousPeriodAvoirs = getPreviousPeriodItems(allAvoirs, period);
      const previousTotalHT = previousPeriodAvoirs.reduce((sum, item) => sum + item.total_ht, 0);
      return previousTotalHT > 0
        ? Math.abs(((Number(value) - previousTotalHT) / previousTotalHT) * 100).toFixed(1)
        : '0';
    },
    getTrend: (avoirs, value, period, allAvoirs) => {
      const previousPeriodAvoirs = getPreviousPeriodItems(allAvoirs, period);
      const previousTotalHT = previousPeriodAvoirs.reduce((sum, item) => sum + item.total_ht, 0);
      return Number(value) <= previousTotalHT ? 'up' : 'down';
    },
    filter: (avoirs) => avoirs,
  },
  {
    id: 'pending',
    title: "Nombre d'Avoirs",
    icon: FileText,
    color: 'orange',
    getValue: (avoirs) => avoirs.length,
    getSubtitle: (avoirs) => {
      const avgAvoir = avoirs.length > 0 ? avoirs.reduce((sum, item) => sum + item.total_ht, 0) / avoirs.length : 0;
      return `${avgAvoir.toLocaleString('fr-FR', { maximumFractionDigits: 0 })}€ moyen`;
    },
    getChange: (avoirs, value, period, allAvoirs) => {
      const previousPeriodAvoirs = getPreviousPeriodItems(allAvoirs, period);
      const countChange = Number(value) - previousPeriodAvoirs.length;
      return countChange !== 0 ? `${countChange > 0 ? '+' : ''}${countChange}` : '0';
    },
    getTrend: (avoirs, value, period, allAvoirs) => {
      const previousPeriodAvoirs = getPreviousPeriodItems(allAvoirs, period);
      return Number(value) <= previousPeriodAvoirs.length ? 'up' : 'down';
    },
    filter: (avoirs) => avoirs
  },
  {
    id: 'validated',
    title: 'Avoirs à Facturer',
    icon: TrendingDown,
    color: 'green',
    getValue: (avoirs) => avoirs.filter(a => a.statut === 2).length,
    getSubtitle: (avoirs) => {
      const validated = avoirs.filter(a => a.statut === 2);
      const validatedAmount = validated.reduce((sum, item) => sum + item.total_ht, 0);
      return `${validatedAmount.toLocaleString('fr-FR', { maximumFractionDigits: 0 })}€`;
    },
    getChange: (avoirs, value, period, allAvoirs) => {
      const previousPeriodAvoirs = getPreviousPeriodItems(allAvoirs, period);
      const previousValidated = previousPeriodAvoirs.filter(a => a.statut === 2);
      const validatedCountChange = Number(value) - previousValidated.length;
      return validatedCountChange !== 0 ? `${validatedCountChange > 0 ? '+' : ''}${validatedCountChange}` : '';
    },
    getTrend: (avoirs, value, period, allAvoirs) => {
      const previousPeriodAvoirs = getPreviousPeriodItems(allAvoirs, period);
      const previousValidated = previousPeriodAvoirs.filter(a => a.statut === 2);
      return Number(value) <= previousValidated.length ? 'up' : 'down';
    },
    filter: (avoirs) => avoirs.filter(a => a.statut === 2),
  },
  {
    id: 'accounted',
    title: 'Avoirs Facturés',
    icon: AlertCircle,
    color: 'purple',
    getValue: (avoirs) => avoirs.filter(a => a.statut === 3).length,
    getSubtitle: (avoirs) => {
      const accounted = avoirs.filter(a => a.statut === 3);
      const accountedAmount = accounted.reduce((sum, item) => sum + item.total_ht, 0);
      return `${accountedAmount.toLocaleString('fr-FR', { maximumFractionDigits: 0 })}€`;
    },
    getChange: (avoirs) => {
      const validationRate =
        avoirs.length > 0 ? ((avoirs.filter(a => a.statut === 2).length / avoirs.length) * 100).toFixed(1) : '0';
      return `${validationRate}% validés`;
    },
    getTrend: (avoirs) => {
      const pending = avoirs.filter(a => a.statut === 1);
      return pending.length > 0 ? 'neutral' : 'up';
    },
    filter: (avoirs) => avoirs.filter(a => a.statut === 3),
  },
];

// ============================================
// COMPOSANT PRINCIPAL
// ============================================

const CreditNotesPage = () => {
  const navigate = useNavigate();
  const dispatch = useAppDispatch();
  const [period, setPeriod] = useState<PeriodType>('all');
  const [activeFilter, setActiveFilter] = useState<FilterType>('all');
  const [activeFilters, setActiveFilters] = useState<Record<string, string[] | undefined>>({});
  const [isCreateModalOpen, setIsCreateModalOpen] = useState(false);

  // État des colonnes visibles
  const [columnConfig, setColumnConfig] = useState<ColumnConfig[]>(DEFAULT_COLUMNS);

  const clients = useAppSelector(getAllClients) as Client[];
  const commercials = useAppSelector(getAllcommercials) as Commercial[];
  const avoirs = useAppSelector(getAllavoir) as Avoir[];
  const statusAvoir = useAppSelector(avoirStatus);

  const [editing, setEditing] = useState<Avoir | null>(null);
  const isLoading = statusAvoir === 'loading' && avoirs.length === 0;

  const statusClient = useAppSelector(clientStatus);
  const statusArticle = useAppSelector(articleStatus);
  const statusCommercial = useAppSelector(commercialsStatus);

  useEffect(() => {
    const load = async () => {
      try {
        if (statusArticle === 'idle') await dispatch(getArticles()).unwrap();
        if (statusClient === 'idle' || statusClient === 'failed') await dispatch(getClients()).unwrap();
        if (statusCommercial === 'idle') await dispatch(getCommercials()).unwrap();
      } catch (error) {
        console.error(error);
      }
    };
    load();
  }, [statusArticle, statusClient, statusCommercial, dispatch]);

  const { refresh } = useDashboardData();

  useEffect(() => {
    const load = async () => {
      if (statusAvoir === 'idle' || statusAvoir === 'failed') await dispatch(getAvoirs()).unwrap();
    };
    load();
  }, [statusAvoir, dispatch]);

  // ============================================
  // OPTIONS POUR LES FILTRES
  // ============================================

  const commercialOptions = useMemo(() => {
    return commercials.map(c => ({
      value: c.numero.toString(),
      label: `${c.prenom || ''} ${c.nom || ''}`.trim() || `Commercial ${c.numero}`,
    }));
  }, [commercials]);

  // Map pour retrouver le commercial d'un client rapidement
  const clientCommercialMap = useMemo(() => {
    const map = new Map<string, string>();
    clients.forEach(client => {
      if (client.commercial?.numero) {
        map.set(client.numero, client.commercial.numero.toString());
      }
    });
    return map;
  }, [clients]);

  const filterDefinitions = [
    {
      key: 'status',
      label: 'Statut',
      options: (Object.entries(AVOIR_STATUS_LABELS) as [string, typeof AVOIR_STATUS_LABELS[StatusCode]][]).map(
        ([value, { label, color }]) => ({
          value: value.toString(),
          label,
          color,
        })
      ),
    },
    {
      key: 'rep',
      label: 'Commercial',
      options: commercialOptions,
    },
  ];

  // ============================================
  // KPIs avec onClick
  // ============================================

  const kpis = useMemo(() => {
    const periodFilteredAvoirs = filterItemByPeriod(avoirs, period, 'date');

    return KPI_CONFIG.map(config => {
      const value = config.getValue(periodFilteredAvoirs);
      return {
        id: config.id,
        title: config.title,
        value: config.id === 'all' ? `${Number(value).toLocaleString('fr-FR', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}€` : value,
        change: config.getChange(periodFilteredAvoirs, value, period, avoirs),
        trend: config.getTrend(periodFilteredAvoirs, value, period, avoirs),
        icon: config.icon,
        subtitle: config.getSubtitle(periodFilteredAvoirs, value),
        color: config.color,
        isActive: activeFilter === config.id,
        onClick: () => setActiveFilter(prev => (prev === config.id ? 'all' : config.id)),
      };
    });
  }, [avoirs, period, activeFilter]);

  // ============================================
  // Filtrage combiné : Période + KPI + Filtres avancés
  // ============================================

  const filteredAvoirs = useMemo(() => {
    // 1. Filtrer par période
    let result = filterItemByPeriod(avoirs, period, 'date');

    // 2. Filtrer par KPI actif
    const kpiConfig = KPI_CONFIG.find(k => k.id === activeFilter);
    if (kpiConfig && activeFilter !== 'all') {
      result = kpiConfig.filter(result);
    }

    // 3. Filtres avancés (statut)
    if (activeFilters.status && activeFilters.status.length > 0) {
      result = result.filter(item => activeFilters.status!.includes(item.statut.toString()));
    }

    // 4. Filtre par commercial
    if (activeFilters.rep && activeFilters.rep.length > 0) {
      result = result.filter(item => {
        const commercialCode = clientCommercialMap.get(item.client_code);
        return commercialCode && activeFilters.rep!.includes(commercialCode);
      });
    }

    // 5. Tri par date décroissante
    return [...result].sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime());
  }, [avoirs, period, activeFilter, activeFilters, clientCommercialMap]);

  // ============================================
  // Label du filtre actif
  // ============================================

  const activeFilterLabel = useMemo(() => {
    const config = KPI_CONFIG.find(k => k.id === activeFilter);
    return config?.title || 'Tous';
  }, [activeFilter]);

  // ============================================
  // COLONNES DYNAMIQUES
  // ============================================

  const allColumnsDefinition = useMemo(() => {
    const clientsMap = new Map(clients.map(c => [c.numero, c]));

    return {
      numero: {
        key: 'numero',
        label: 'N° Pièce',
        sortable: true,
        render: (value: string) => <span className="font-bold">{value}</span>,
      },
      client_code: {
        key: 'client_code',
        label: 'Client',
        sortable: true,
        render: (clientCode: string) => {
          const client = clientsMap.get(clientCode);
          if (!client) return <span className="text-gray-400">{clientCode}</span>;
          const avatar = client.intitule?.charAt(0).toUpperCase() || '?';
          return (
            <div className="flex items-center gap-3">
              <div className="w-9 h-9 rounded-full bg-gray-100 dark:bg-gray-800 flex items-center justify-center text-xs font-bold text-gray-600 dark:text-gray-300">
                {avatar}
              </div>
              <div>
                <p className="text-sm font-medium text-gray-900 dark:text-white">{client.intitule}</p>
                <p className="text-xs text-gray-500">{client.email || client.telephone || clientCode}</p>
              </div>
            </div>
          );
        },
      },
      date: {
        key: 'date',
        label: 'Date',
        sortable: true,
        render: (date: string) => <span>{formatDateFRCourt(date)}</span>,
      },
      total_ht_calcule: {
        key: 'total_ht_calcule',
        label: 'Montant HT',
        sortable: true,
        render: (v: number) => `${v.toLocaleString()}€`,
      },
      total_taxes_calcule: {
        key: 'total_taxes_calcule',
        label: 'Montant TVA',
        sortable: true,
        render: (value: number) => `${value.toLocaleString()}€`,
      },
      total_ttc_calcule: {
        key: 'total_ttc_calcule',
        label: 'Montant TTC',
        sortable: true,
        render: (v: number) => <span className="font-bold">{v.toLocaleString()}€</span>,
      },
      statut: {
        key: 'statut',
        label: 'Statut',
        sortable: true,
        render: (v: number) => <StatusBadge status={v} type_doc={SageDocumentType.BON_AVOIR} />,
      },
    };
  }, [clients]);

  const visibleColumns = useMemo(() => {
    return columnConfig
      .filter(col => col.visible)
      .map(col => allColumnsDefinition[col.key as keyof typeof allColumnsDefinition])
      .filter(Boolean);
  }, [columnConfig, allColumnsDefinition]);

  // Formateurs personnalisés pour transformer les valeurs à l'export
  const columnFormatters: Record<string, (value: any, row: any) => string> = {
    date: value => {
      if (!value) return '';
      return formatDateFRCourt(value);
    },
    total_ht_calcule: value => {
      if (value === null || value === undefined) return '0 €';
      return `${value.toLocaleString('fr-FR', { minimumFractionDigits: 2 })} €`;
    },
    total_taxes_calcule: value => {
      if (value === null || value === undefined) return '0 €';
      return `${value.toLocaleString('fr-FR', { minimumFractionDigits: 2 })} €`;
    },
    total_ttc_calcule: value => {
      if (value === null || value === undefined) return '0 €';
      return `${value.toLocaleString('fr-FR', { minimumFractionDigits: 2 })} €`;
    },
    statut: value => {
      return AVOIR_STATUS_LABELS[value as StatusCode]?.label || 'Inconnu';
    },
    client_intitule: (value, row) => {
      return value || row.client_code || '';
    },
  };

  const actions = (row: Avoir) => (
    <>
      <button
        onClick={async () => {
          await dispatch(selectAvoirAsync(row)).unwrap();
          navigate(`/home/avoirs/${row.numero}`);
        }}
        className="p-2 hover:bg-gray-100 dark:hover:bg-gray-800 rounded-lg transition-colors"
        title="Voir détails"
      >
        <Eye className="w-4 h-4" />
      </button>
      <button
        onClick={async () => {
          const rep = (await dispatch(selectAvoirAsync(row)).unwrap()) as Avoir;
          handleEdit(rep);
        }}
        className="p-2 hover:bg-gray-100 dark:hover:bg-gray-800 rounded-lg transition-colors"
        title="Modifier"
      >
        <Edit className="w-4 h-4" />
      </button>
    </>
  );

  const handleCreate = () => {
    setEditing(null);
    setIsCreateModalOpen(true);
  };

  const handleEdit = (row: Avoir) => {
    setEditing(row);
    setIsCreateModalOpen(true);
  };

  return (
    <>
      <Helmet>
        <title>Avoirs - Dataven</title>
        <meta name="description" content="Gestion des avoirs" />
      </Helmet>
      <div className="space-y-6">
        <KPIBar kpis={kpis} period={period} loading={statusAvoir} onRefresh={refresh} />

        <div className="flex flex-col sm:flex-row sm:items-center justify-between gap-4">
          <div className="flex items-center gap-4">
            <div>
              <div className="flex items-center gap-3">
                <h1 className="text-2xl font-bold text-gray-900 dark:text-white">Avoirs</h1>
                {activeFilter !== 'all' && (
                  <button
                    onClick={() => setActiveFilter('all')}
                    className={cn(
                      'inline-flex items-center gap-1.5 px-3 py-1 rounded-full text-xs font-medium transition-colors',
                      'bg-[#007E45]/10 text-[#007E45] hover:bg-[#007E45]/20'
                    )}
                  >
                    {activeFilterLabel}
                    <X className="w-3 h-3" />
                  </button>
                )}
              </div>
              <p className="text-sm text-gray-600 dark:text-gray-400 mt-1">
                {filteredAvoirs.length} avoir{filteredAvoirs.length > 1 ? 's' : ''}
                {activeFilter !== 'all' && ` (${activeFilterLabel.toLowerCase()})`}
              </p>
            </div>
            <PeriodSelector value={period} onChange={setPeriod} />
          </div>
          <div className="flex gap-3 flex-wrap items-center">
            <ColumnSelector columns={columnConfig} onChange={setColumnConfig} />
            <ExportDropdown
              data={filteredAvoirs}
              columns={columnConfig}
              columnFormatters={columnFormatters}
              filename="Avoir"
            />
            <AdvancedFilters
              filters={filterDefinitions}
              activeFilters={activeFilters}
              onFilterChange={(key, values) => {
                setActiveFilters(prev => ({
                  ...prev,
                  [key]: values,
                }));
              }}
              onReset={() => setActiveFilters({})}
            />
            <PrimaryButton_v2 icon={Plus} onClick={handleCreate}>
              Nouvel avoir
            </PrimaryButton_v2>
          </div>
        </div>

        <DataTable
          columns={visibleColumns}
          data={filteredAvoirs}
          actions={actions}
          status={isLoading}
          onRowClick={async (row: Avoir) => {
            await dispatch(selectAvoirAsync(row)).unwrap();
            navigate(`/home/avoirs/${row.numero}`);
          }}
        />
      </div>

      <ModalAvoir
        open={isCreateModalOpen}
        onClose={() => setIsCreateModalOpen(false)}
        title={editing ? `Mettre à jour l'avoir ${editing.numero}` : 'Créer un avoir'}
        editing={editing}
      />
    </>
  );
};

export default CreditNotesPage;