import React, { useState, useCallback } from 'react';
import {
  Box, Typography, Paper, CircularProgress, Button,
  Alert
} from '@mui/material';
import { DataGrid, type GridColDef, GridFooterContainer, GridFooter } from '@mui/x-data-grid';
import { esES } from '@mui/x-data-grid/locales';
import reportesService from '../../services/Reportes/reportesService';
import type { ReporteCuentasDistribuidorResponseDto } from '../../models/dtos/Reportes/ReporteCuentasDistribuidorResponseDto';
import type { BalanceCuentaDistDto } from '../../models/dtos/Reportes/BalanceCuentaDistDto';
import type { BalanceCuentaDebCredDto } from '../../models/dtos/Reportes/BalanceCuentaDebCredDto';
import type { BalanceCuentaPagosDto } from '../../models/dtos/Reportes/BalanceCuentaPagosDto';
import { usePermissions } from '../../hooks/usePermissions';
import SeleccionaReporteCuentasDistribuidores from './SeleccionaReporteCuentasDistribuidores';
import * as XLSX from 'xlsx';
import axios from 'axios';

type MovimientoConSaldo = BalanceCuentaDistDto & { id: string; saldoAcumulado: number };
type NotaConSaldo = BalanceCuentaDebCredDto & { id: string; saldoAcumulado: number };
type PagoConSaldo = BalanceCuentaPagosDto & { id: string; saldoAcumulado: number };

const ReporteCuentasDistribuidoresPage: React.FC = () => {
  const [originalReportData, setOriginalReportData] = useState<ReporteCuentasDistribuidorResponseDto | null>(null);
  const [movimientosConSaldo, setMovimientosConSaldo] = useState<MovimientoConSaldo[]>([]);
  const [error, setError] = useState<string | null>(null);
  const [notasConSaldo, setNotasConSaldo] = useState<NotaConSaldo[]>([]);
  const [pagosConSaldo, setPagosConSaldo] = useState<PagoConSaldo[]>([]);
  const [loading, setLoading] = useState<boolean>(false);
  const [loadingPdf, setLoadingPdf] = useState<boolean>(false);
  const [apiErrorParams, setApiErrorParams] = useState<string | null>(null);
  const [showParamSelector, setShowParamSelector] = useState<boolean>(true);
  const [currentParams, setCurrentParams] = useState<{
    idDistribuidor: number;
    idEmpresa: number;
    fechaDesde: string;
    fechaHasta: string;
    nombreDistribuidor?: string;
    nombreEmpresa?: string;
  } | null>(null);
  const { tienePermiso, isSuperAdmin } = usePermissions();
  const puedeVerReporte = isSuperAdmin || tienePermiso("RR001");

  // Calcula saldos acumulados seccion por seccion
  const calcularSaldosPorSeccion = (data: ReporteCuentasDistribuidorResponseDto) => {
    const procesarLista = <T extends { fecha: string | Date; debe?: number; haber?: number; id?: number | string }>(
      lista: T[],
      idPrefix: string,
      saldoInicial: number
    ): Array<T & { id: string; saldoAcumulado: number }> => {
      let acumulado = saldoInicial;
      return lista
        .slice()
        .sort((a, b) => new Date(a.fecha).getTime() - new Date(b.fecha).getTime())
        .map((item, idx) => {
          const debe = Number(item.debe) || 0;
          const haber = Number(item.haber) || 0;
          acumulado += debe - haber;
          return {
            ...item,
            id: item.id?.toString() || `${idPrefix}-${idx}`,
            saldoAcumulado: acumulado
          };
        });
    };

    const baseInicial = data.saldoInicial ?? 0;
    const movs = procesarLista(data.entradasSalidas, 'mov', baseInicial);
    const ultimoMov = movs.length ? movs[movs.length - 1].saldoAcumulado : baseInicial;
    const notas = procesarLista(data.debitosCreditos, 'nota', ultimoMov);
    const ultimoNota = notas.length ? notas[notas.length - 1].saldoAcumulado : ultimoMov;
    const pagos = procesarLista(data.pagos, 'pago', ultimoNota);

    return { movs, notas, pagos };
  };

  // Genera columnas con formateo
  const generarColumns = (): { mov: GridColDef[]; notas: GridColDef[]; pagos: GridColDef[] } => ({
    mov: [
      { field: 'fecha', headerName: 'Fecha', width: 100 },
      { field: 'publicacion', headerName: 'Publicación', flex: 1 },
      { field: 'remito', headerName: 'Remito', width: 100 },
      {
        field: 'debe',
        headerName: 'Debe',
        type: 'number',
        width: 130,
        align: 'right',
        headerAlign: 'right',
        valueFormatter: (value: number | null | undefined) =>
          value != null ? value.toLocaleString('es-AR', { style: 'currency', currency: 'ARS' }) : ''
      },
      //{ field: 'debe', headerName: 'Debe', type: 'number', width: 130, align: 'right', headerAlign: 'right' },
      {
        field: 'haber',
        headerName: 'Haber',
        type: 'number',
        width: 130,
        align: 'right',
        headerAlign: 'right',
        valueFormatter: (value: number | null | undefined) =>
          value != null ? value.toLocaleString('es-AR', { style: 'currency', currency: 'ARS' }) : ''
      },
      //{ field: 'haber', headerName: 'Haber', type: 'number', width: 130, align: 'right', headerAlign: 'right' },
      {
        field: 'saldoAcumulado',
        headerName: 'Saldo',
        type: 'number',
        width: 130,
        align: 'right',
        headerAlign: 'right',
        valueFormatter: (value: number | null | undefined) =>
          value != null ? value.toLocaleString('es-AR', { style: 'currency', currency: 'ARS' }) : ''
      },
      //{ field: 'saldoAcumulado', headerName: 'Saldo', type: 'number', width: 150, align: 'right', headerAlign: 'right' }
    ],
    notas: [
      { field: 'fecha', headerName: 'Fecha', width: 100 },
      { field: 'referencia', headerName: 'Referencia', flex: 1 },
      {
        field: 'debe',
        headerName: 'Debe',
        type: 'number',
        width: 130,
        align: 'right',
        headerAlign: 'right',
        valueFormatter: (value: number | null | undefined) =>
          value != null ? value.toLocaleString('es-AR', { style: 'currency', currency: 'ARS' }) : ''
      },
      //{ field: 'debe', headerName: 'Debe', type: 'number', width: 130, align: 'right', headerAlign: 'right' },
      {
        field: 'haber',
        headerName: 'Haber',
        type: 'number',
        width: 130,
        align: 'right',
        headerAlign: 'right',
        valueFormatter: (value: number | null | undefined) =>
          value != null ? value.toLocaleString('es-AR', { style: 'currency', currency: 'ARS' }) : ''
      },
      //{ field: 'haber', headerName: 'Haber', type: 'number', width: 130, align: 'right', headerAlign: 'right' },
      {
        field: 'saldoAcumulado',
        headerName: 'Saldo',
        type: 'number',
        width: 130,
        align: 'right',
        headerAlign: 'right',
        valueFormatter: (value: number | null | undefined) =>
          value != null ? value.toLocaleString('es-AR', { style: 'currency', currency: 'ARS' }) : ''
      },
      //{ field: 'saldoAcumulado', headerName: 'Saldo', type: 'number', width: 150, align: 'right', headerAlign: 'right' }
    ],
    pagos: [
      { field: 'fecha', headerName: 'Fecha', width: 100 },
      { field: 'recibo', headerName: 'Recibo', width: 100 },
      { field: 'tipo', headerName: 'Tipo', width: 150 },
      { field: 'detalle', headerName: 'Detalle', flex: 1 },
      {
        field: 'debe',
        headerName: 'Debe',
        type: 'number',
        width: 130,
        align: 'right',
        headerAlign: 'right',
        valueFormatter: (value: number | null | undefined) =>
          value != null ? value.toLocaleString('es-AR', { style: 'currency', currency: 'ARS' }) : ''
      },
      //{ field: 'debe', headerName: 'Debe', type: 'number', width: 130, align: 'right', headerAlign: 'right' },
      {
        field: 'haber',
        headerName: 'Haber',
        type: 'number',
        width: 130,
        align: 'right',
        headerAlign: 'right',
        valueFormatter: (value: number | null | undefined) =>
          value != null ? value.toLocaleString('es-AR', { style: 'currency', currency: 'ARS' }) : ''
      },
      //{ field: 'haber', headerName: 'Haber', type: 'number', width: 130, align: 'right', headerAlign: 'right' },
      {
        field: 'saldoAcumulado',
        headerName: 'Saldo',
        type: 'number',
        width: 130,
        align: 'right',
        headerAlign: 'right',
        valueFormatter: (value: number | null | undefined) =>
          value != null ? value.toLocaleString('es-AR', { style: 'currency', currency: 'ARS' }) : ''
      },
      //{ field: 'saldoAcumulado', headerName: 'Saldo', type: 'number', width: 150, align: 'right', headerAlign: 'right' }
    ]
  });

  // Renderiza DataGrid con footer de totales
  const renderDataGrid = (
    rows: Array<{ debe?: number; haber?: number }>,
    columns: GridColDef[]
  ) => {
    const totalDebe = rows.reduce((sum, r) => sum + (r.debe || 0), 0);
    const totalHaber = rows.reduce((sum, r) => sum + (r.haber || 0), 0);
    return rows.length ? (
      <Paper sx={{ height: 350, width: '100%', mb: 2 }}>
        <DataGrid
          rows={rows}
          columns={columns}
          localeText={esES.components.MuiDataGrid.defaultProps.localeText}
          density="compact"
          slots={{
            footer: () => (
              <GridFooterContainer>
                <GridFooter sx={{ borderTop: 'none' }} />
                <Box sx={{ p: 1, fontWeight: 'bold' }}>
                  <Typography variant="subtitle2" component="span" sx={{ mr: 2 }}>
                    TOTAL DEBE: <strong>{totalDebe.toLocaleString('es-AR', { style: 'currency', currency: 'ARS' })}</strong>
                  </Typography>
                  <Typography variant="subtitle2" component="span">
                    TOTAL HABER: <strong>{totalHaber.toLocaleString('es-AR', { style: 'currency', currency: 'ARS' })}</strong>
                  </Typography>
                </Box>
              </GridFooterContainer>
            )
          }}
        />
      </Paper>
    ) : (
      <Typography sx={{ fontStyle: 'italic', mb: 2 }}>No hay registros</Typography>
    );
  };

  const handleGenerarReporte = useCallback(async (params: {
    idDistribuidor: number;
    idEmpresa: number;
    fechaDesde: string;
    fechaHasta: string;
  }) => {
    if (!puedeVerReporte) {
      setError("No tiene permiso para generar este reporte.");
      setLoading(false);
      return;
    }
    setError(null);
    setLoading(true);
    setApiErrorParams(null);
    setOriginalReportData(null);
    setMovimientosConSaldo([]);
    setNotasConSaldo([]);
    setPagosConSaldo([]);

    const distSvc = (await import('../../services/Distribucion/distribuidorService')).default;
    const empSvc = (await import('../../services/Distribucion/empresaService')).default;
    const [distData, empData] = await Promise.all([
      distSvc.getDistribuidorLookupById(params.idDistribuidor),
      empSvc.getEmpresaLookupById(params.idEmpresa)
    ]);
    setCurrentParams({
      ...params,
      nombreDistribuidor: distData?.nombre,
      nombreEmpresa: empData?.nombre
    });

    try {
      const data = await reportesService.getReporteCuentasDistribuidor(params);
      setOriginalReportData(data);
      const { movs, notas, pagos } = calcularSaldosPorSeccion(data);
      setMovimientosConSaldo(movs);
      setNotasConSaldo(notas);
      setPagosConSaldo(pagos);
      setShowParamSelector(false);
    } catch (error: any) {
      const msg = axios.isAxiosError(error) && error.response?.data?.message
        ? error.response.data.message
        : 'Error al generar el reporte';
      setApiErrorParams(msg);
    } finally {
      setLoading(false);
    }
  }, []);

  const handleVolverAParametros = useCallback(() => {
    setShowParamSelector(true);
    setOriginalReportData(null);
    setMovimientosConSaldo([]);
    setNotasConSaldo([]);
    setPagosConSaldo([]);
  }, []);

  const handleExportToExcel = useCallback(() => {
    if (!originalReportData) {
      alert('No hay datos para exportar.');
      return;
    }

    const sumDebe = (rows: Array<{ debe?: number }>) => rows.reduce((s, r) => s + (r.debe || 0), 0);
    const sumHaber = (rows: Array<{ haber?: number }>) => rows.reduce((s, r) => s + (r.haber || 0), 0);

    const totalDebeAll = sumDebe(movimientosConSaldo) + sumDebe(notasConSaldo) + sumDebe(pagosConSaldo);
    const totalHaberAll = sumHaber(movimientosConSaldo) + sumHaber(notasConSaldo) + sumHaber(pagosConSaldo);
    const saldoInicialExp = originalReportData.saldoInicial ?? 0;
    const saldoFinalExp = saldoInicialExp + totalDebeAll - totalHaberAll;

    const wb = XLSX.utils.book_new();

    // Hoja Resumen — siempre presente, con saldo inicial y final aunque no haya movimientos
    const resumenRows = [
      { Concepto: 'Saldo Inicial', Monto: saldoInicialExp },
      { Concepto: 'Total Debe',    Monto: totalDebeAll },
      { Concepto: 'Total Haber',   Monto: totalHaberAll },
      { Concepto: 'Saldo Final',   Monto: saldoFinalExp },
    ];
    const wsResumen = XLSX.utils.json_to_sheet(resumenRows);
    XLSX.utils.book_append_sheet(wb, wsResumen, 'Resumen');

    if (movimientosConSaldo.length) {
      const ws = XLSX.utils.json_to_sheet(movimientosConSaldo.map(({ id, ...rest }) => rest));
      XLSX.utils.book_append_sheet(wb, ws, 'Movimientos');
    }
    if (notasConSaldo.length) {
      const ws = XLSX.utils.json_to_sheet(notasConSaldo.map(({ id, ...rest }) => rest));
      XLSX.utils.book_append_sheet(wb, ws, 'Notas');
    }
    if (pagosConSaldo.length) {
      const ws = XLSX.utils.json_to_sheet(pagosConSaldo.map(({ id, ...rest }) => rest));
      XLSX.utils.book_append_sheet(wb, ws, 'Pagos');
    }

    XLSX.writeFile(wb, `Reporte_${Date.now()}.xlsx`);
  }, [originalReportData, movimientosConSaldo, notasConSaldo, pagosConSaldo]);

  const handleGenerarYAbrirPdf = useCallback(async () => {
    if (!currentParams) return;
    setLoadingPdf(true);
    try {
      const blob = await reportesService.getReporteCuentasDistribuidorPdf(currentParams);
      window.open(URL.createObjectURL(blob), '_blank');
    } catch {
      setError('Ocurrió un error al generar el PDF.');
    } finally {
      setLoadingPdf(false);
    }
  }, [currentParams]);

  if (showParamSelector) {
    if (!loading && !puedeVerReporte) {
      return <Alert severity="error" sx={{ m: 2 }}>No tiene permiso para acceder a este reporte.</Alert>;
    }
    return (
      <Box sx={{ p: 2, display: 'flex', justifyContent: 'center' }}>
        <Paper sx={{ width: '100%', maxWidth: 600 }} elevation={3}>
          <SeleccionaReporteCuentasDistribuidores
            onGenerarReporte={handleGenerarReporte}
            onCancel={handleVolverAParametros}
            isLoading={loading}
            apiErrorMessage={apiErrorParams}
          />
        </Paper>
      </Box>
    );
  }

  // Totales de cada sección para resumen final
  const totalMov = movimientosConSaldo.reduce((sum, r) => sum + ((r.debe || 0) - (r.haber || 0)), 0);
  const totalNot = notasConSaldo.reduce((sum, r) => sum + ((r.debe || 0) - (r.haber || 0)), 0);
  const totalPag = pagosConSaldo.reduce((sum, r) => sum + ((r.debe || 0) - (r.haber || 0)), 0);
  const saldoInicial = originalReportData?.saldoInicial ?? 0;
  const saldoFinal = saldoInicial + totalMov + totalNot + totalPag;

  const cols = generarColumns();

  return (
    <Box sx={{ p: 2 }}>
      {error && (
        <Paper sx={{ mb: 2, p: 2, backgroundColor: '#ffeaea' }}>
          <Typography color="error">{error}</Typography>
        </Paper>
      )}
      <Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 2 }}>
        <Typography variant="h5">Cuenta Corriente Distribuidor</Typography>
        <Box sx={{ display: 'flex', gap: 1 }}>
          <Button onClick={handleGenerarYAbrirPdf} variant="contained" disabled={!originalReportData} size="small">
            {loadingPdf ? <CircularProgress size={20} /> : 'Abrir PDF'}
          </Button>
          <Button onClick={handleExportToExcel} variant="outlined" disabled={!originalReportData} size="small">
            Exportar a Excel
          </Button>
          <Button onClick={handleVolverAParametros} variant="outlined" color="secondary" size="small">
            Nuevos Parámetros
          </Button>
        </Box>
      </Box>

      <Paper sx={{ p: 2, mb: 2 }}>
        <Typography>Distribuidor: <strong>{currentParams?.nombreDistribuidor}</strong></Typography>
        <Typography>Empresa: <strong>{currentParams?.nombreEmpresa}</strong></Typography>
        <Typography>Período: <strong>{currentParams?.fechaDesde}</strong> al <strong>{currentParams?.fechaHasta}</strong></Typography>
        <Typography>Saldo Inicial del Período: <strong>{saldoInicial.toLocaleString('es-AR', { style: 'currency', currency: 'ARS' })}</strong></Typography>
      </Paper>

      <Typography variant="h6" sx={{ mt: 2 }}>Movimientos de Entrada / Salida</Typography>
      {renderDataGrid(movimientosConSaldo, cols.mov)}

      <Typography variant="h6" sx={{ mt: 2 }}>Notas de Crédito / Débito</Typography>
      {renderDataGrid(notasConSaldo, cols.notas)}

      <Typography variant="h6" sx={{ mt: 2 }}>Pagos Recibidos / Realizados</Typography>
      {renderDataGrid(pagosConSaldo, cols.pagos)}

      <Paper sx={{ p: 2, mt: 3 }}>
        <Typography variant="h6">Resumen Final</Typography>
        <Typography>Saldo Inicial: <strong>{saldoInicial.toLocaleString('es-AR', { style: 'currency', currency: 'ARS' })}</strong></Typography>
        <Typography>Movimientos (Debe - Haber): {totalMov.toLocaleString('es-AR', { style: 'currency', currency: 'ARS' })}</Typography>
        <Typography>Notas C/D (Debe - Haber): {totalNot.toLocaleString('es-AR', { style: 'currency', currency: 'ARS' })}</Typography>
        <Typography>Pagos (Debe - Haber): {totalPag.toLocaleString('es-AR', { style: 'currency', currency: 'ARS' })}</Typography>
        <Typography variant="subtitle1" sx={{ fontWeight: 'bold', mt: 1 }}>
          Saldo Final: {saldoFinal.toLocaleString('es-AR', { style: 'currency', currency: 'ARS' })}
        </Typography>
      </Paper>
    </Box>
  );
};

export default ReporteCuentasDistribuidoresPage;