import React, { createContext, useCallback, useEffect, useState } from 'react';
import {
  Dialog,
  DialogBody,
  DialogContent,
  DialogDescription,
  DialogHeader,
  DialogTitle
} from '@/components/ui/dialog';
import { useCallApi } from '@/hooks';
import { apiConfig } from '@/config/api.config';
import { DataGridColumnHeader, DataGridProvider } from '@/components';
import { useManageStatementContext } from '../hooks/useManageWalletStatementContext';
import { toast, Toaster } from 'sonner';
import { format } from 'date-fns';
import FilterSection from './FilterSection';
import * as XLSX from 'xlsx';
import jsPDF from 'jspdf';
import autoTable from 'jspdf-autotable';
import ExcelJS from 'exceljs';
import { toAbsoluteUrl } from '@/utils';

interface ContextProps {
  doExportData: (sorting: any, filter: any) => Promise<any>;
  doExportExcel: () => Promise<void>;
  doExportPDF: () => Promise<void>;
}

const initialProps: ContextProps = {
  doExportData: async () => ({ data: [], totalCount: 0 }),
  doExportExcel: async () => {},
  doExportPDF: async () => {}
};

export const showDetailWalletContext = createContext<ContextProps>(initialProps);

const ShowDetailWalletDialog = () => {
  const { GetData, GetExportData } = useCallApi();
  const { showDetailDialog, setShowDetailDialog, selectedWallet } = useManageStatementContext();
  const [filters, setFilters] = useState<any>({});
  const [transaction, setTransaction] = useState<any[]>([]);

  const categoryMap: Record<string, string> = {
    T: 'TRANSFER',
    P: 'PURCHASE',
    W: 'WITHDRAW',
    U: 'TOP UP',
    R: 'RETURN',
    N: 'TOP UP PARTNER',
    E: 'REWARD',
    L: 'PURCHASE LOJA',
    B: 'TOP UP P24',
    A: 'TRANSFER AGENT',
    M: 'WITHDRAWAL AGENT',
    O: 'TOP UP AGENT',
    S: 'TRANSFER P24',
    I: 'WIJTDRAW MERCHANT',
    D: 'DONATION',
    F: 'FEE',
    V: 'REVERSAL',
    C: 'CASHBACK CASH',
    H: 'CASHBACK POINT'
  };

  const columns = [
    {
      accessorKey: 'transaction_code',
      header: ({ column }: any) => (
        <DataGridColumnHeader title="Transaction Code" column={column} />
      ),
      enableSorting: false,
      meta: { headerClassName: 'min-w-[120px]' }
    },
    {
      accessorKey: 'msisdn_reff',
      header: ({ column }: any) => <DataGridColumnHeader title="MSISDN Reffer" column={column} />,
      enableSorting: false,
      meta: { headerClassName: 'min-w-[120px]' }
    },
    {
      accessorKey: 'transaction_type.name',
      header: ({ column }: any) => (
        <DataGridColumnHeader title="Transaction Type" column={column} />
      ),
      enableSorting: false,
      meta: { headerClassName: 'min-w-[180px]' }
    },
    {
      accessorKey: 'type',
      header: ({ column }: any) => <DataGridColumnHeader title="Type" column={column} />,
      enableSorting: false,
      meta: { headerClassName: 'min-w-[80px]' }
    },
    {
      accessorKey: 'pre_amount',
      header: ({ column }: any) => <DataGridColumnHeader title="Pre Amount" column={column} />,
      enableSorting: false,
      cell: (info: any) => info.getValue()?.toFixed(2),
      meta: { headerClassName: 'min-w-[100px]' }
    },
    {
      accessorKey: 'amount',
      header: ({ column }: any) => <DataGridColumnHeader title="Amount" column={column} />,
      enableSorting: true,
      cell: (info: any) => info.getValue()?.toFixed(2),
      meta: { headerClassName: 'min-w-[100px]' }
    },
    {
      accessorKey: 'post_amount',
      header: ({ column }: any) => <DataGridColumnHeader title="Post Amount" column={column} />,
      enableSorting: false,
      cell: (info: any) => info.getValue()?.toFixed(2),
      meta: { headerClassName: 'min-w-[100px]' }
    },
    {
      accessorFn: (row: any) => categoryMap[row.category] || '_',
      accessorKey: 'category',
      header: ({ column }: any) => <DataGridColumnHeader title="Category" column={column} />,
      enableSorting: false,
      enableHiding: false,
      meta: { headerClassName: 'w-[250px]' }
    },
    {
      accessorKey: 'date',
      header: ({ column }: any) => <DataGridColumnHeader title="Date" column={column} />,
      enableSorting: false,
      cell: (info: any) => {
        const val = info.getValue();
        if (!val) return '-';
        return new Date(val).toLocaleString('id-ID', {
          day: '2-digit',
          month: 'short',
          year: 'numeric',
          hour: '2-digit',
          minute: '2-digit'
        });
      },
      meta: { headerClassName: 'min-w-[150px]' }
    },
    {
      accessorKey: 'purpose',
      header: ({ column }: any) => <DataGridColumnHeader title="Purpose" column={column} />,
      enableSorting: false,
      cell: (info: any) => info.getValue() || '-',
      meta: { headerClassName: 'min-w-[200px]' }
    },
    {
      accessorKey: 'notes',
      header: ({ column }: any) => <DataGridColumnHeader title="Notes" column={column} />,
      enableSorting: false,
      cell: (info: any) => info.getValue() || '-',
      meta: { headerClassName: 'min-w-[200px]' }
    }
  ];

  const getTransactionLists = useCallback(
    async (page: number, limit: number, sorting: any, _columnFilters: any) => {
      try {
        const response = await GetData(
          `${apiConfig.service_wallet}/dashboard/balance/list-balance-detail/${selectedWallet?.ID}`,
          {
            limit,
            page: page + 1,
            with_deleted: false,
            order_field: sorting?.[0]?.id ?? 'amount',
            order_direction: sorting?.[0]?.desc ? 'ASC' : 'DESC',
            filter: JSON.stringify(filters)
          }
        );

        if (!response || !response.data) {
          console.warn('No data received:', response);
          return { data: [], totalCount: 0 };
        }

        setTransaction(response.data.list);
        return { data: response.data.list, totalCount: response.data.total_count };
      } catch (error) {
        console.error('Error fetching transaction', error);
        return { data: [], totalCount: 0 };
      }
    },
    [GetData, filters, selectedWallet]
  );

  const getAllTransactionData = async () => {
    try {
      const response = await GetData(
        `${apiConfig.service_wallet}/dashboard/balance/list-balance-detail/${selectedWallet?.ID}`,
        {
          limit: 10000,
          page: 1,
          with_deleted: false,
          order_field: 'amount',
          order_direction: 'DESC',
          filter: JSON.stringify(filters)
        }
      );

      return response?.data?.list || [];
    } catch (error) {
      console.error('Error fetching all transaction data', error);
      return [];
    }
  };

  const formatTransactionData = (data: any[]) => {
    return data.map((item) => ({
      'Transaction Code': item.transaction_code || '-',
      'MSISDN Reffer': item.msisdn_reff || '-',
      'Transaction Type': item.transaction_type?.name || '-',
      Type: item.type || '-',
      'Pre Amount': item.pre_amount?.toFixed(2) || '0.00',
      Amount: item.amount?.toFixed(2) || '0.00',
      'Post Amount': item.post_amount?.toFixed(2) || '0.00',
      Category: categoryMap[item.category] || '-',
      Date: item.date
        ? new Date(item.date).toLocaleString('id-ID', {
            day: '2-digit',
            month: 'short',
            year: 'numeric',
            hour: '2-digit',
            minute: '2-digit'
          })
        : '-',
      Purpose: item.purpose || '-',
      Notes: item.notes || '-'
    }));
  };

  const doExportExcel = async () => {
    try {
      const allData = await getAllTransactionData();
      const formattedData = formatTransactionData(allData);

      const wb = XLSX.utils.book_new();
      const ws = XLSX.utils.json_to_sheet([]);

      // Membuat space untuk header image (sekitar 10 baris)
      const imageSpaceRows = 10;

      const companyHeader = [
        // Baris kosong untuk space gambar header
        ...Array(imageSpaceRows).fill(['']),
        [''],
        ['Wallet Statement Details'],
        [`Export Date: ${format(new Date(), 'dd MMM yyyy HH:mm:ss')}`],
        [`Wallet ID: ${selectedWallet?.ID || '-'}`],
        ['']
      ];

      const columnHeaders = [
        [
          'Transaction Code',
          'MSISDN Reffer',
          'Transaction Type',
          'Type',
          'Pre Amount',
          'Amount',
          'Post Amount',
          'Category',
          'Date',
          'Purpose',
          'Notes'
        ]
      ];

      const excelData = [
        ...companyHeader,
        ...columnHeaders,
        ...formattedData.map((item) => Object.values(item))
      ];

      XLSX.utils.sheet_add_aoa(ws, excelData);

      // Set column widths
      const colWidths = [
        { wch: 20 },
        { wch: 15 },
        { wch: 35 },
        { wch: 10 },
        { wch: 12 },
        { wch: 12 },
        { wch: 12 },
        { wch: 15 },
        { wch: 20 },
        { wch: 25 },
        { wch: 25 }
      ];
      ws['!cols'] = colWidths;

      // Style untuk title "Wallet Statement Details"
      const titleRowIndex = imageSpaceRows + 1;
      const titleCell = XLSX.utils.encode_cell({ r: titleRowIndex, c: 0 });
      if (ws[titleCell]) {
        ws[titleCell].s = {
          font: { bold: true, sz: 16 },
          alignment: { horizontal: 'center' }
        };
      }

      // Style untuk export date dan wallet ID
      for (let i = titleRowIndex + 1; i < titleRowIndex + 3; i++) {
        const cellRef = XLSX.utils.encode_cell({ r: i, c: 0 });
        if (ws[cellRef]) {
          ws[cellRef].s = {
            font: { sz: 11 },
            alignment: { horizontal: 'left' }
          };
        }
      }

      // Merge cells untuk header area
      if (!ws['!merges']) ws['!merges'] = [];

      // Merge untuk space gambar header
      for (let i = 0; i < imageSpaceRows; i++) {
        const range = XLSX.utils.encode_range({ s: { r: i, c: 0 }, e: { r: i, c: 10 } });
        ws['!merges'].push(XLSX.utils.decode_range(range));
      }

      // Merge untuk title dan info
      for (let i = titleRowIndex; i < titleRowIndex + 4; i++) {
        const range = XLSX.utils.encode_range({ s: { r: i, c: 0 }, e: { r: i, c: 10 } });
        ws['!merges'].push(XLSX.utils.decode_range(range));
      }

      // Style untuk column headers
      const headerRowIndex = titleRowIndex + 4;
      for (let col = 0; col < columnHeaders[0].length; col++) {
        const cellRef = XLSX.utils.encode_cell({ r: headerRowIndex, c: col });
        if (ws[cellRef]) {
          ws[cellRef].s = {
            font: { bold: true, color: { rgb: 'FFFFFF' } },
            fill: { fgColor: { rgb: '4472C4' } },
            alignment: { horizontal: 'center' },
            border: {
              top: { style: 'thin', color: { rgb: '000000' } },
              bottom: { style: 'thin', color: { rgb: '000000' } },
              left: { style: 'thin', color: { rgb: '000000' } },
              right: { style: 'thin', color: { rgb: '000000' } }
            }
          };
        }
      }

      // Style untuk data rows
      const dataStartRow = headerRowIndex + 1;
      for (let row = dataStartRow; row < dataStartRow + formattedData.length; row++) {
        for (let col = 0; col < columnHeaders[0].length; col++) {
          const cellRef = XLSX.utils.encode_cell({ r: row, c: col });
          if (ws[cellRef]) {
            ws[cellRef].s = {
              alignment: { horizontal: 'left' }, // Semua kolom rata kiri
              border: {
                top: { style: 'thin', color: { rgb: 'D9D9D9' } },
                bottom: { style: 'thin', color: { rgb: 'D9D9D9' } },
                left: { style: 'thin', color: { rgb: 'D9D9D9' } },
                right: { style: 'thin', color: { rgb: 'D9D9D9' } }
              }
            };
          }
        }
      }

      try {
        // Import ExcelJS untuk menambahkan gambar
        const ExcelJS = await import('exceljs');

        // Buat workbook baru dengan ExcelJS
        const workbook = new ExcelJS.Workbook();
        const worksheet = workbook.addWorksheet('Wallet Statement');

        // Tambahkan data dari XLSX worksheet ke ExcelJS worksheet
        const range = XLSX.utils.decode_range(ws['!ref'] || 'A1:K1');

        for (let row = range.s.r; row <= range.e.r; row++) {
          for (let col = range.s.c; col <= range.e.c; col++) {
            const cellAddress = XLSX.utils.encode_cell({ r: row, c: col });
            const cell = ws[cellAddress];
            if (cell && cell.v !== undefined) {
              const excelCell = worksheet.getCell(row + 1, col + 1);
              excelCell.value = cell.v;

              // Apply styles
              if (cell.s) {
                if (cell.s.font) {
                  excelCell.font = {
                    bold: cell.s.font.bold || false,
                    size: cell.s.font.sz || 11,
                    color: cell.s.font.color ? { argb: cell.s.font.color.rgb } : undefined
                  };
                }
                if (cell.s.fill) {
                  excelCell.fill = {
                    type: 'pattern',
                    pattern: 'solid',
                    fgColor: { argb: cell.s.fill.fgColor.rgb }
                  };
                }
                if (cell.s.alignment) {
                  excelCell.alignment = {
                    horizontal: cell.s.alignment.horizontal || 'left'
                  };
                }
                if (cell.s.border) {
                  excelCell.border = {
                    top: cell.s.border.top ? { style: 'thin' } : undefined,
                    bottom: cell.s.border.bottom ? { style: 'thin' } : undefined,
                    left: cell.s.border.left ? { style: 'thin' } : undefined,
                    right: cell.s.border.right ? { style: 'thin' } : undefined
                  };
                }
              }
            }
          }
        }

        // Set column widths
        colWidths.forEach((width, index) => {
          worksheet.getColumn(index + 1).width = width.wch;
        });

        // Merge cells
        if (ws['!merges']) {
          ws['!merges'].forEach((merge) => {
            worksheet.mergeCells(merge.s.r + 1, merge.s.c + 1, merge.e.r + 1, merge.e.c + 1);
          });
        }

        // Tambahkan gambar header
        try {
          const response = await fetch(
            toAbsoluteUrl('/media/avatars/KopDetailWalletStatement.png')
          );
          if (response.ok) {
            const imageBuffer = await response.arrayBuffer();

            const imageId = workbook.addImage({
              buffer: imageBuffer,
              extension: 'png'
            });

            // Posisikan gambar di area header
            worksheet.addImage(imageId, {
              tl: { col: 1.7, row: 1 },
              ext: { width: 1100, height: 180 }
            });
          }
        } catch (imageError) {
          console.warn('Could not load header image, continuing without it:', imageError);
        }

        // Export file
        const fileName = `wallet_statement_${selectedWallet?.ID}_${format(new Date(), 'yyyyMMdd_HHmmss')}.xlsx`;
        const buffer = await workbook.xlsx.writeBuffer();

        // Download file
        const blob = new Blob([buffer], {
          type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
        });
        const url = window.URL.createObjectURL(blob);
        const link = document.createElement('a');
        link.href = url;
        link.download = fileName;
        link.click();
        window.URL.revokeObjectURL(url);
      } catch (excelJSError) {
        console.warn('ExcelJS not available, falling back to XLSX without image:', excelJSError);

        XLSX.utils.book_append_sheet(wb, ws, 'Wallet Statement');
        const fileName = `wallet_statement_${selectedWallet?.ID}_${format(new Date(), 'yyyyMMdd_HHmmss')}.xlsx`;
        XLSX.writeFile(wb, fileName);
      }
    } catch (error) {
      console.error('Error exporting to Excel:', error);
      toast.error('Failed to export Excel');
    }
  };

  const doExportPDF = async () => {
    try {
      const allData = await getAllTransactionData();
      const formattedData = formatTransactionData(allData);

      const pdf = new jsPDF({
        orientation: 'landscape',
        unit: 'mm',
        format: 'a4'
      });

      const headerImageUrl = toAbsoluteUrl('/media/avatars/KopDetailWalletStatement.png');

      try {
        const pageWidth = pdf.internal.pageSize.getWidth();
        const imageWidth = 250;
        const imageHeight = 40;
        const xPosition = (pageWidth - imageWidth) / 2;

        pdf.addImage(headerImageUrl, 'PNG', xPosition, 10, imageWidth, imageHeight);

        let currentY = 55;

        pdf.setDrawColor(0, 0, 0);
        pdf.setLineWidth(0.5);
        pdf.line(20, currentY, pageWidth - 20, currentY);

        currentY += 10;

        pdf.setFontSize(16);
        pdf.setFont('helvetica', 'bold');
        pdf.text('Wallet Statement Details', pageWidth / 2, currentY, { align: 'center' });

        currentY += 10;

        pdf.setFontSize(10);
        pdf.setFont('helvetica', 'normal');
        pdf.text(`Export Date: ${format(new Date(), 'dd MMM yyyy HH:mm:ss')}`, 20, currentY);
        pdf.text(`Wallet ID: ${selectedWallet?.ID || '-'}`, 20, currentY + 6);

        currentY += 20;

        const tableHeaders = [
          'Transaction Code',
          'MSISDN Reffer',
          'Transaction Type',
          'Type',
          'Pre Amount',
          'Amount',
          'Post Amount',
          'Category',
          'Date',
          'Purpose',
          'Notes'
        ];

        const tableData = formattedData.map((item) => [
          item['Transaction Code'],
          item['MSISDN Reffer'],
          item['Transaction Type'],
          item['Type'],
          item['Pre Amount'],
          item['Amount'],
          item['Post Amount'],
          item['Category'],
          item['Date'],
          item['Purpose'],
          item['Notes']
        ]);

        const calculateLeftMargin = (
          columnStyles: Record<number, { cellWidth: number }>,
          pageWidth: number
        ): number => {
          const totalTableWidth = Object.values(columnStyles).reduce(
            (sum, col) => sum + col.cellWidth,
            0
          );

          return (pageWidth - totalTableWidth) / 2;
        };
        const columnStyles = {
          0: { cellWidth: 25, halign: 'left' as const },
          1: { cellWidth: 20, halign: 'left' as const },
          2: { cellWidth: 25, halign: 'left' as const },
          3: { cellWidth: 15, halign: 'center' as const },
          4: { cellWidth: 18, halign: 'right' as const },
          5: { cellWidth: 18, halign: 'right' as const },
          6: { cellWidth: 18, halign: 'right' as const },
          7: { cellWidth: 20, halign: 'left' as const },
          8: { cellWidth: 30, halign: 'left' as const },
          9: { cellWidth: 25, halign: 'left' as const },
          10: { cellWidth: 25, halign: 'left' as const }
        };

        const leftMargin = calculateLeftMargin(columnStyles, pageWidth);

        autoTable(pdf, {
          head: [tableHeaders],
          body: tableData,
          startY: currentY,
          styles: {
            fontSize: 7,
            cellPadding: 2,
            overflow: 'linebreak',
            halign: 'center'
          },
          headStyles: {
            fillColor: [68, 114, 196],
            textColor: [255, 255, 255],
            fontStyle: 'bold',
            halign: 'center'
          },
          columnStyles,
          tableWidth: 'wrap',
          margin: { top: currentY, left: leftMargin },
          didDrawCell: (data: any) => {
            if (data.section === 'body') {
              pdf.setDrawColor(200, 200, 200);
              pdf.setLineWidth(0.1);
            }
          }
        });

        const fileName = `wallet_statement_${selectedWallet?.ID}_${format(new Date(), 'yyyyMMdd_HHmmss')}.pdf`;
        pdf.save(fileName);
      } catch (imageError) {
        console.error('Error loading header image:', imageError);
      }
    } catch (error) {
      console.error('Error exporting to PDF:', error);
      toast.error('Failed to export PDF');
    }
  };

  const doExportData = async (sorting: any, filter: any) => {
    const user = localStorage.getItem(
      `${import.meta.env.VITE_APP_NAME}-auth-v${import.meta.env.VITE_APP_VERSION}`
    );

    const parsedUser = user ? JSON.parse(user) : null;
    sorting = sorting.length === 0 ? [{ id: 'created_at', desc: false }] : sorting;
    filter = filter && filter.length > 0 ? filter : [];

    let dataFilter: any = {};

    if (filter && filter.length > 0) {
      filter.forEach((f: any) => {
        if (f.id === 'username') {
          dataFilter['username'] = { like: f.value };
        } else if (f.id === 'created_at') {
          dataFilter['created_at'] = f.value;
        }
      });
    }

    if (!dataFilter['created_at']) {
      const defaultFrom = new Date(new Date().setMonth(new Date().getMonth() - 1));
      const defaultTo = new Date();

      dataFilter['created_at'] = {
        from: `${format(defaultFrom, 'yyyy-MM-dd')} 00:00:00`,
        to: `${format(defaultTo, 'yyyy-MM-dd')} 23:59:59`
      };
    }

    let param = {
      order_field: sorting[0].id || 'created_at',
      order_direction: sorting[0].desc ? 'DESC' : 'ASC',
      with_deleted: false,
      filter: JSON.stringify(dataFilter),
      token: parsedUser?.access_token
    };

    let url = `${apiConfig.service_wallet}/dashboard/balance/list-balance-download/${selectedWallet?.ID}`;

    GetExportData(url, param, 'user_activity_export_');
  };

  return (
    <showDetailWalletContext.Provider value={{ doExportData, doExportExcel, doExportPDF }}>
      <Toaster expand visibleToasts={9} duration={3000} />
      <Dialog open={showDetailDialog} onOpenChange={setShowDetailDialog}>
        <DialogContent className="w-screen max-w-screen max-h-screen p-4 overflow-hidden">
          <DialogHeader>
            <DialogTitle>Details Wallet Statement</DialogTitle>
          </DialogHeader>
          <DialogDescription />

          <DialogBody>
            <FilterSection
              filters={filters}
              setFilters={setFilters}
              transaction={transaction}
              categoryMap={categoryMap}
            />

            <div className="py-4 max-h-[70vh] overflow-y-auto">
              <DataGridProvider
                key={JSON.stringify(filters)}
                columns={columns}
                pagination={{ size: 5 }}
                layout={{ card: true }}
                sorting={[{ id: 'amount', desc: false }]}
                serverSide={true}
                onFetchData={({ pageIndex, pageSize, sorting, columnFilters }) =>
                  getTransactionLists(pageIndex, pageSize, sorting, columnFilters)
                }
              />
            </div>
          </DialogBody>
        </DialogContent>
      </Dialog>
    </showDetailWalletContext.Provider>
  );
};

export default ShowDetailWalletDialog;
