import React, { useState, useCallback } from 'react';
import {
  Box, Typography, Paper, CircularProgress, Alert, Button
} from '@mui/material';
import { DataGrid, type GridColDef, GridFooterContainer } from '@mui/x-data-grid';
import { esES } from '@mui/x-data-grid/locales';
import reportesService from '../../services/Reportes/reportesService';
import type { ListadoDistribucionGeneralResponseDto } from '../../models/dtos/Reportes/ListadoDistribucionGeneralResponseDto';
import type { ListadoDistribucionGeneralResumenDto } from '../../models/dtos/Reportes/ListadoDistribucionGeneralResumenDto';
import type { ListadoDistribucionGeneralPromedioDiaDto } from '../../models/dtos/Reportes/ListadoDistribucionGeneralPromedioDiaDto';
import SeleccionaReporteListadoDistribucionGeneral from './SeleccionaReporteListadoDistribucionGeneral';
import * as XLSX from 'xlsx';
import axios from 'axios';

interface ResumenDiarioExtendido extends ListadoDistribucionGeneralResumenDto {
  id: string;
}

interface PromediosPorDiaExtendido extends ListadoDistribucionGeneralPromedioDiaDto {
  id: string;
}

const ReporteListadoDistribucionGeneralPage: React.FC = () => {
  const [reportData, setReportData] = useState<ListadoDistribucionGeneralResponseDto | null>(null);
  const [resumenCalculado, setResumenCalculado] = useState<ResumenDiarioExtendido[]>([]);
  const [promediosCalculado, setPromediosCalculado] = useState<PromediosPorDiaExtendido[]>([]);

  const [loading, setLoading] = useState(false);
  const [loadingPdf, setLoadingPdf] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [apiErrorParams, setApiErrorParams] = useState<string | null>(null);
  const [showParamSelector, setShowParamSelector] = useState(true);
  const [currentParams, setCurrentParams] = useState<{
    idPublicacion: number;
    fechaDesde: string;
    fechaHasta: string;
    nombrePublicacion?: string;
    mesAnioParaNombreArchivo?: string;
  } | null>(null);

  const [totalesResumen, setTotalesResumen] = useState({
    cantidadTirada: 0,
    sinCargo: 0,
    perdidos: 0,
    llevados: 0,
    devueltos: 0,
    vendidos: 0,
  });

  const [totalesPromedios, setTotalesPromedios] = useState({
    cantidadDias: 0,
    promedioTirada: 0,
    promedioSinCargo: 0,
    promedioPerdidos: 0,
    promedioLlevados: 0,
    promedioDevueltos: 0,
    promedioVendidos: 0,
  });


  const handleGenerarReporte = useCallback(async (params: {
    idPublicacion: number;
    fechaDesde: string;
    fechaHasta: string;
  }) => {
    setLoading(true);
    setError(null);
    setApiErrorParams(null);
    setReportData(null);
    setResumenCalculado([]);
    setPromediosCalculado([]);
    setTotalesResumen({ cantidadTirada: 0, sinCargo: 0, perdidos: 0, llevados: 0, devueltos: 0, vendidos: 0 });
    setTotalesPromedios({ cantidadDias: 0, promedioTirada: 0, promedioSinCargo: 0, promedioPerdidos: 0, promedioLlevados: 0, promedioDevueltos: 0, promedioVendidos: 0 });

    const pubService = (await import('../../services/Distribucion/publicacionService')).default;
    const pubData = await pubService.getPublicacionById(params.idPublicacion);
    const mesAnioParts = params.fechaDesde.split('-');
    const mesAnioNombre = `${mesAnioParts[1]}/${mesAnioParts[0]}`;

    setCurrentParams({ ...params, nombrePublicacion: pubData?.nombre, mesAnioParaNombreArchivo: mesAnioNombre });

    try {
      const data = await reportesService.getListadoDistribucionGeneral(params);

      const resumenConId = data.resumen.map((item, index) => ({
        ...item,
        id: `resumen-${index}`
      }));
      setResumenCalculado(resumenConId);

      const totalesResumenCalculados = data.resumen.reduce((acc, item) => ({
        cantidadTirada: acc.cantidadTirada + item.cantidadTirada,
        sinCargo: acc.sinCargo + item.sinCargo,
        perdidos: acc.perdidos + item.perdidos,
        llevados: acc.llevados + item.llevados,
        devueltos: acc.devueltos + item.devueltos,
        vendidos: acc.vendidos + item.vendidos,
      }), { cantidadTirada: 0, sinCargo: 0, perdidos: 0, llevados: 0, devueltos: 0, vendidos: 0 });
      setTotalesResumen(totalesResumenCalculados);

      const promediosConId = data.promediosPorDia.map((item, index) => ({
        ...item,
        id: `promedio-${index}`
      }));
      setPromediosCalculado(promediosConId);

      const totalDias = data.promediosPorDia.reduce((sum, item) => sum + item.cantidadDias, 0);
      const promediosPonderados = data.promediosPorDia.reduce((acc, item) => ({
        tirada: acc.tirada + item.promedioTirada * item.cantidadDias,
        sinCargo: acc.sinCargo + item.promedioSinCargo * item.cantidadDias,
        perdidos: acc.perdidos + item.promedioPerdidos * item.cantidadDias,
        llevados: acc.llevados + item.promedioLlevados * item.cantidadDias,
        devueltos: acc.devueltos + item.promedioDevueltos * item.cantidadDias,
        vendidos: acc.vendidos + item.promedioVendidos * item.cantidadDias,
      }), { tirada: 0, sinCargo: 0, perdidos: 0, llevados: 0, devueltos: 0, vendidos: 0 });

      setTotalesPromedios({
        cantidadDias: totalDias,
        promedioTirada: totalDias > 0 ? promediosPonderados.tirada / totalDias : 0,
        promedioSinCargo: totalDias > 0 ? promediosPonderados.sinCargo / totalDias : 0,
        promedioPerdidos: totalDias > 0 ? promediosPonderados.perdidos / totalDias : 0,
        promedioLlevados: totalDias > 0 ? promediosPonderados.llevados / totalDias : 0,
        promedioDevueltos: totalDias > 0 ? promediosPonderados.devueltos / totalDias : 0,
        promedioVendidos: totalDias > 0 ? promediosPonderados.vendidos / totalDias : 0,
      });

      setReportData(data);

      if (resumenConId.length === 0 && promediosConId.length === 0) {
        setError("No se encontraron datos para los parámetros seleccionados.");
      }
      setShowParamSelector(false);
    } catch (err: any) {
      const message = axios.isAxiosError(err) && err.response?.data?.message
        ? err.response.data.message
        : 'Ocurrió un error al generar el reporte.';
      setApiErrorParams(message);
      setReportData(null);
    } finally {
      setLoading(false);
    }
  }, []);

  const handleVolverAParametros = useCallback(() => {
    setShowParamSelector(true);
    setReportData(null);
    setError(null);
    setApiErrorParams(null);
    setCurrentParams(null);
    setResumenCalculado([]);
    setPromediosCalculado([]);
  }, []);

  const handleExportToExcel = useCallback(() => {
    if (!resumenCalculado.length && !promediosCalculado.length) {
      alert("No hay datos para exportar.");
      return;
    }
    const wb = XLSX.utils.book_new();

    if (resumenCalculado.length) {
      const resumenToExport = resumenCalculado.map(item => ({
        "Fecha": item.fecha ? new Date(item.fecha).toLocaleDateString('es-AR', { timeZone: 'UTC' }) : '-',
        "Tirada": item.cantidadTirada,
        "Sin Cargo": item.sinCargo,
        "Perdidos": item.perdidos,
        "Llevados": item.llevados,
        "Devueltos": item.devueltos,
        "Vendidos": item.vendidos,
      }));
      resumenToExport.push({
        "Fecha": "TOTALES",
        "Tirada": totalesResumen.cantidadTirada,
        "Sin Cargo": totalesResumen.sinCargo,
        "Perdidos": totalesResumen.perdidos,
        "Llevados": totalesResumen.llevados,
        "Devueltos": totalesResumen.devueltos,
        "Vendidos": totalesResumen.vendidos,
      });
      const wsResumen = XLSX.utils.json_to_sheet(resumenToExport);
      XLSX.utils.book_append_sheet(wb, wsResumen, "ResumenDiario");
    }

    if (promediosCalculado.length) {
      const promediosToExport = promediosCalculado.map(item => ({
        "Día Semana": item.dia,
        "Cant. Días": item.cantidadDias,
        "Prom. Tirada": item.promedioTirada,
        "Prom. Sin Cargo": item.promedioSinCargo,
        "Prom. Perdidos": item.promedioPerdidos,
        "Prom. Llevados": item.promedioLlevados,
        "Prom. Devueltos": item.promedioDevueltos,
        "Prom. Vendidos": item.promedioVendidos,
      }));
      promediosToExport.push({
        "Día Semana": "GENERAL",
        "Cant. Días": totalesPromedios.cantidadDias,
        "Prom. Tirada": totalesPromedios.promedioTirada,
        "Prom. Sin Cargo": totalesPromedios.promedioSinCargo,
        "Prom. Perdidos": totalesPromedios.promedioPerdidos,
        "Prom. Llevados": totalesPromedios.promedioLlevados,
        "Prom. Devueltos": totalesPromedios.promedioDevueltos,
        "Prom. Vendidos": totalesPromedios.promedioVendidos,
      });
      const wsPromedios = XLSX.utils.json_to_sheet(promediosToExport);
      XLSX.utils.book_append_sheet(wb, wsPromedios, "PromediosPorDia");
    }

    let fileName = "ListadoDistribucionGeneral";
    if (currentParams) {
      fileName += `_${currentParams.nombrePublicacion?.replace(/\s+/g, '') ?? `Pub${currentParams.idPublicacion}`}`;
      fileName += `_${currentParams.mesAnioParaNombreArchivo?.replace('/', '-')}`;
    }
    fileName += ".xlsx";
    XLSX.writeFile(wb, fileName);
  }, [resumenCalculado, promediosCalculado, currentParams, totalesResumen, totalesPromedios]);

  const handleGenerarYAbrirPdf = useCallback(async () => {
    if (!currentParams) {
      setError("Primero debe generar el reporte en pantalla o seleccionar parámetros.");
      return;
    }
    setLoadingPdf(true);
    setError(null);
    try {
      const blob = await reportesService.getListadoDistribucionGeneralPdf({
        idPublicacion: currentParams.idPublicacion,
        fechaDesde: currentParams.fechaDesde,
        fechaHasta: currentParams.fechaHasta
      });
      if (blob.type === "application/json") {
        const text = await blob.text();
        const msg = JSON.parse(text).message ?? "Error inesperado al generar PDF.";
        setError(msg);
      } else {
        const url = URL.createObjectURL(blob);
        const w = window.open(url, '_blank');
        if (!w) alert("Permite popups para ver el PDF.");
      }
    } catch {
      setError('Ocurrió un error al generar el PDF.');
    } finally {
      setLoadingPdf(false);
    }
  }, [currentParams]);

  const columnsResumen: GridColDef[] = [
    { field: 'fecha', headerName: 'Fecha', flex: 0.8, minWidth: 100, valueFormatter: (value) => value ? new Date(value).toLocaleDateString('es-AR', { timeZone: 'UTC' }) : '-' },
    { field: 'cantidadTirada', headerName: 'Tirada', type: 'number', flex: 1, minWidth: 100, align: 'right', headerAlign: 'right', valueFormatter: (value) => Number(value).toLocaleString('es-AR') },
    { field: 'sinCargo', headerName: 'Sin Cargo', type: 'number', flex: 1, minWidth: 100, align: 'right', headerAlign: 'right', valueFormatter: (value) => Number(value).toLocaleString('es-AR') },
    { field: 'perdidos', headerName: 'Perdidos', type: 'number', flex: 1, minWidth: 100, align: 'right', headerAlign: 'right', valueFormatter: (value) => Number(value).toLocaleString('es-AR') },
    { field: 'llevados', headerName: 'Llevados', type: 'number', flex: 1, minWidth: 100, align: 'right', headerAlign: 'right', valueFormatter: (value) => Number(value).toLocaleString('es-AR') },
    { field: 'devueltos', headerName: 'Devueltos', type: 'number', flex: 1, minWidth: 100, align: 'right', headerAlign: 'right', valueFormatter: (value) => Number(value).toLocaleString('es-AR') },
    { field: 'vendidos', headerName: 'Vendidos', type: 'number', flex: 1, minWidth: 100, align: 'right', headerAlign: 'right', valueFormatter: (value) => Number(value).toLocaleString('es-AR') },
  ];

  const columnsPromedios: GridColDef[] = [
    { field: 'dia', headerName: 'Día Semana', flex: 1, minWidth: 130 },
    { field: 'cantidadDias', headerName: 'Cant. Días', type: 'number', flex: 0.8, minWidth: 100, align: 'right', headerAlign: 'right', valueFormatter: (value) => Number(value).toLocaleString('es-AR') },
    { field: 'promedioTirada', headerName: 'Prom. Tirada', type: 'number', flex: 1, minWidth: 120, align: 'right', headerAlign: 'right', valueFormatter: (value) => Number(value).toLocaleString('es-AR', { maximumFractionDigits: 0 }) },
    { field: 'promedioSinCargo', headerName: 'Prom. Sin Cargo', type: 'number', flex: 1, minWidth: 120, align: 'right', headerAlign: 'right', valueFormatter: (value) => Number(value).toLocaleString('es-AR', { maximumFractionDigits: 0 }) },
    { field: 'promedioPerdidos', headerName: 'Prom. Perdidos', type: 'number', flex: 1, minWidth: 120, align: 'right', headerAlign: 'right', valueFormatter: (value) => Number(value).toLocaleString('es-AR', { maximumFractionDigits: 0 }) },
    { field: 'promedioLlevados', headerName: 'Prom. Llevados', type: 'number', flex: 1, minWidth: 120, align: 'right', headerAlign: 'right', valueFormatter: (value) => Number(value).toLocaleString('es-AR', { maximumFractionDigits: 0 }) },
    { field: 'promedioDevueltos', headerName: 'Prom. Devueltos', type: 'number', flex: 1, minWidth: 120, align: 'right', headerAlign: 'right', valueFormatter: (value) => Number(value).toLocaleString('es-AR', { maximumFractionDigits: 0 }) },
    { field: 'promedioVendidos', headerName: 'Prom. Vendidos', type: 'number', flex: 1, minWidth: 120, align: 'right', headerAlign: 'right', valueFormatter: (value) => Number(value).toLocaleString('es-AR', { maximumFractionDigits: 0 }) },
  ];

  const CustomFooterResumen = () => (
    <GridFooterContainer>
      <Box sx={{ p: 1, display: 'flex', alignItems: 'center', fontWeight: 'bold', width: '100%' }}>
        <Typography variant="subtitle2" sx={{ minWidth: columnsResumen[0].minWidth, fontWeight: 'bold' }}>TOTALES:</Typography>
        <Typography variant="subtitle2" sx={{ flex: columnsResumen[1].flex, minWidth: columnsResumen[1].minWidth, textAlign: 'right', fontWeight: 'bold' }}>{totalesResumen.cantidadTirada.toLocaleString('es-AR')}</Typography>
        <Typography variant="subtitle2" sx={{ flex: columnsResumen[2].flex, minWidth: columnsResumen[2].minWidth, textAlign: 'right', fontWeight: 'bold' }}>{totalesResumen.sinCargo.toLocaleString('es-AR')}</Typography>
        <Typography variant="subtitle2" sx={{ flex: columnsResumen[3].flex, minWidth: columnsResumen[3].minWidth, textAlign: 'right', fontWeight: 'bold' }}>{totalesResumen.perdidos.toLocaleString('es-AR')}</Typography>
        <Typography variant="subtitle2" sx={{ flex: columnsResumen[4].flex, minWidth: columnsResumen[4].minWidth, textAlign: 'right', fontWeight: 'bold' }}>{totalesResumen.llevados.toLocaleString('es-AR')}</Typography>
        <Typography variant="subtitle2" sx={{ flex: columnsResumen[5].flex, minWidth: columnsResumen[5].minWidth, textAlign: 'right', fontWeight: 'bold' }}>{totalesResumen.devueltos.toLocaleString('es-AR')}</Typography>
        <Typography variant="subtitle2" sx={{ flex: columnsResumen[6].flex, minWidth: columnsResumen[6].minWidth, textAlign: 'right', fontWeight: 'bold' }}>{totalesResumen.vendidos.toLocaleString('es-AR')}</Typography>
      </Box>
    </GridFooterContainer>
  );

  const CustomFooterPromedios = () => (
    <GridFooterContainer>
      <Box sx={{ p: 1, display: 'flex', alignItems: 'center', fontWeight: 'bold', width: '100%' }}>
        <Typography variant="subtitle2" sx={{ flex: columnsPromedios[0].flex, minWidth: columnsPromedios[0].minWidth, fontWeight: 'bold' }}>GENERAL:</Typography>
        <Typography variant="subtitle2" sx={{ flex: columnsPromedios[1].flex, minWidth: columnsPromedios[1].minWidth, textAlign: 'right', fontWeight: 'bold' }}>{totalesPromedios.cantidadDias.toLocaleString('es-AR')}</Typography>
        <Typography variant="subtitle2" sx={{ flex: columnsPromedios[2].flex, minWidth: columnsPromedios[2].minWidth, textAlign: 'right', fontWeight: 'bold' }}>{totalesPromedios.promedioTirada.toLocaleString('es-AR', { maximumFractionDigits: 0 })}</Typography>
        <Typography variant="subtitle2" sx={{ flex: columnsPromedios[3].flex, minWidth: columnsPromedios[3].minWidth, textAlign: 'right', fontWeight: 'bold' }}>{totalesPromedios.promedioSinCargo.toLocaleString('es-AR', { maximumFractionDigits: 0 })}</Typography>
        <Typography variant="subtitle2" sx={{ flex: columnsPromedios[4].flex, minWidth: columnsPromedios[4].minWidth, textAlign: 'right', fontWeight: 'bold' }}>{totalesPromedios.promedioPerdidos.toLocaleString('es-AR', { maximumFractionDigits: 0 })}</Typography>
        <Typography variant="subtitle2" sx={{ flex: columnsPromedios[5].flex, minWidth: columnsPromedios[5].minWidth, textAlign: 'right', fontWeight: 'bold' }}>{totalesPromedios.promedioLlevados.toLocaleString('es-AR', { maximumFractionDigits: 0 })}</Typography>
        <Typography variant="subtitle2" sx={{ flex: columnsPromedios[6].flex, minWidth: columnsPromedios[6].minWidth, textAlign: 'right', fontWeight: 'bold' }}>{totalesPromedios.promedioDevueltos.toLocaleString('es-AR', { maximumFractionDigits: 0 })}</Typography>
        <Typography variant="subtitle2" sx={{ flex: columnsPromedios[7].flex, minWidth: columnsPromedios[7].minWidth, textAlign: 'right', fontWeight: 'bold' }}>{totalesPromedios.promedioVendidos.toLocaleString('es-AR', { maximumFractionDigits: 0 })}</Typography>
      </Box>
    </GridFooterContainer>
  );

  if (showParamSelector) {
    return (
      <Box sx={{ p: 2, display: 'flex', justifyContent: 'center', mt: 2 }}>
        <Paper sx={{ width: '100%', maxWidth: 600 }} elevation={3}>
          <SeleccionaReporteListadoDistribucionGeneral
            onGenerarReporte={handleGenerarReporte}
            onCancel={handleVolverAParametros}
            isLoading={loading}
            apiErrorMessage={apiErrorParams}
          />
        </Paper>
      </Box>
    );
  }

  return (
    <Box sx={{ p: 2 }}>
      <Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 2, flexWrap: 'wrap', gap: 1 }}>
        <Typography variant="h5">Reporte: Listado Distribución General</Typography>
        <Box sx={{ display: 'flex', gap: 1 }}>
          <Button onClick={handleGenerarYAbrirPdf} variant="contained" disabled={loadingPdf || !reportData || !!error} size="small">
            {loadingPdf ? <CircularProgress size={20} color="inherit" /> : "Abrir PDF"}
          </Button>
          <Button onClick={handleExportToExcel} variant="outlined" disabled={!reportData || !!error} size="small">
            Exportar a Excel
          </Button>
          <Button onClick={handleVolverAParametros} variant="outlined" color="secondary" size="small">
            Nuevos Parámetros
          </Button>
        </Box>
      </Box>

      {loading && <Box sx={{ textAlign: 'center' }}><CircularProgress /></Box>}
      {error && !loading && <Alert severity="error" sx={{ my: 2 }}>{error}</Alert>}

      {!loading && !error && reportData && (
        <>
          <Typography variant="h6" gutterBottom sx={{ mt: 2 }}>Resumen Diario</Typography>
          {resumenCalculado.length > 0 ? (
            <Paper sx={{ height: 450, width: '100%', mb: 3 }}>
              <DataGrid
                rows={resumenCalculado}
                columns={columnsResumen}
                localeText={esES.components.MuiDataGrid.defaultProps.localeText}
                density="compact"
                slots={{ footer: CustomFooterResumen }}
                hideFooterPagination
                hideFooterSelectedRowCount
              />
            </Paper>
          ) : (<Typography sx={{ fontStyle: 'italic' }}>No hay datos de resumen diario.</Typography>)}

          <Typography variant="h6" gutterBottom sx={{ mt: 2 }}>Promedios por Día de Semana</Typography>
          {promediosCalculado.length > 0 ? (
            <Paper sx={{ height: 400, width: '100%' }}>
              <DataGrid
                rows={promediosCalculado}
                columns={columnsPromedios}
                localeText={esES.components.MuiDataGrid.defaultProps.localeText}
                density="compact"
                slots={{ footer: CustomFooterPromedios }}
                hideFooterPagination
                hideFooterSelectedRowCount
              />
            </Paper>
          ) : (<Typography sx={{ fontStyle: 'italic' }}>No hay datos de promedios por día.</Typography>)}
        </>
      )}
    </Box>
  );
};

export default ReporteListadoDistribucionGeneralPage;