import { Button, Card, Input } from 'antd';
import Table, { ColumnProps } from 'antd/lib/table';
import moment from 'moment';
import React, { useEffect, useRef, useState } from 'react';
import { SearchOutlined, DownloadOutlined } from '@ant-design/icons';
import Highlighter from 'react-highlight-words';
import { CollectionsService } from 'libs/shared-services/finance/src/lib/collections-service';
import { Excel } from 'antd-table-saveas-excel';
import { AlertMessages } from "@gtpl/shared-utils/alert-messages";

const ExpectedReceivablesReport = () => {
  const [searchText, setSearchText] = useState('');
  const searchInput = useRef(null);
  const [searchedColumn, setSearchedColumn] = useState('');
  const [page, setPage] = useState(1);
  const CollectionService = new CollectionsService();
  const [report, setReport] = useState([]);
  const [columns, setColumns] = useState<ColumnProps<any>[]>([]);
  const [dynamicColumns, setDynamicColumns] = useState<string[]>([]);

  useEffect(() => {
    getActivateReceivables();
  }, []);

  const getActivateReceivables = () => {
    CollectionService.getExpectedReceivablesReport().then((res) => {
      if (res.status) {
        const data = res.data;
        
        // Process the data to add balance receivable to the respective dynamic column
        const dynamicCols = new Set<string>();
        data.forEach(record => {
          if (record?.dueDate) {
            const dueDate = moment(record.dueDate.split(' ')[0]);
            const weekOfMonth = getWeekOfMonth(dueDate);
            const dynamicColTitle = `${weekOfMonth}th week of ${dueDate.format("MMMM")} month`;
            dynamicCols.add(dynamicColTitle);
            
            // Initialize the dynamic column in the record if it doesn't exist
            record[dynamicColTitle] = record[dynamicColTitle] || 0;
            
            // Calculate the balance receivable and add it to the dynamic column
            const invoiceAmt = parseFloat(record.invoiceAmt) || 0;
            const collection = parseFloat(record.collection) || 0;
            const balanceReceivable = invoiceAmt - collection;
            record[dynamicColTitle] += balanceReceivable;
          }
        });

        setDynamicColumns(Array.from(dynamicCols));
        updateColumns(Array.from(dynamicCols));
        setReport(data);
      } else {
        AlertMessages.getErrorMessage(res.internalMessage);
        setReport([]);
      }
    }).catch((err) => {
      AlertMessages.getErrorMessage(err.message);
      setReport([]);
    });
  };

  const handleSearch = (selectedKeys, confirm, dataIndex) => {
    confirm();
    setSearchText(selectedKeys[0]);
    setSearchedColumn(dataIndex);
  };

  const handleReset = (clearFilters) => {
    clearFilters();
    setSearchText('');
  };

  const getColumnSearchProps = (dataIndex) => ({
    filterDropdown: ({ setSelectedKeys, selectedKeys, confirm, clearFilters }) => (
      <div style={{ padding: 8 }}>
        <Input
          ref={searchInput}
          placeholder={`Search ${dataIndex}`}
          value={selectedKeys[0]}
          onChange={e => setSelectedKeys(e.target.value ? [e.target.value] : [])}
          onPressEnter={() => handleSearch(selectedKeys, confirm, dataIndex)}
          style={{ width: 188, marginBottom: 8, display: 'block' }}
        />
        <Button
          type="primary"
          onClick={() => handleSearch(selectedKeys, confirm, dataIndex)}
          icon={<SearchOutlined />}
          size="small"
          style={{ width: 90, marginRight: 8 }}
        >
          Search
        </Button>
        <Button onClick={() => handleReset(clearFilters)} size="small" style={{ width: 90 }}>
          Reset
        </Button>
      </div>
    ),
    filterIcon: filtered => (
      <SearchOutlined type="search" style={{ color: filtered ? '#1890ff' : undefined }} />
    ),
    onFilter: (value, record) =>
      record[dataIndex]
        ? record[dataIndex]
          .toString()
          .toLowerCase()
          .includes(value.toLowerCase())
        : false,
    onFilterDropdownVisibleChange: visible => {
      if (visible) { setTimeout(() => searchInput.current.select()); }
    },
    render: text =>
      text ? (
        searchedColumn === dataIndex ? (
          <Highlighter
            highlightStyle={{ backgroundColor: '#ffc069', padding: 0 }}
            searchWords={[searchText]}
            autoEscape
            textToHighlight={text.toString()}
          />
        ) : text
      ) : null
  });

 const preprocessDataForExport = (data) => {
  return data.map((record, index) => {
    const datePart = record.dueDate ? record.dueDate.split(' ')[0] : null;
    const dueDate = datePart ? moment(datePart) : null;
    const weekOfMonth = dueDate ? getWeekOfMonth(dueDate) : 'Invalid date';

    const invoiceAmt = parseFloat(record.invoiceAmt) || 0;
    const exchangeRate = parseFloat(record.exchangeRate) || 0;
    const collection = parseFloat(record.collection) || 0;

    const invoiceINR = (invoiceAmt && exchangeRate) ? (invoiceAmt * exchangeRate) : 0;
    const balanceReceivable = invoiceINR - collection;

    const currentDate = moment();
    const delayInDays = dueDate ? currentDate.diff(dueDate, 'days') : 0;

    let aging = '-';
    if (record.invoiceDate) {
      const invoiceDate = moment(record.invoiceDate, 'YYYY-MM-DD');
      if (invoiceDate.isValid()) {
        const agingDays = currentDate.diff(invoiceDate, 'days');
        aging = agingDays.toString();
      } else {
        aging = 'Invalid Date';
      }
    }

    return {
      ...record,
      id: index + 1,
      invoiceAmt: invoiceAmt.toFixed(2),
      invoiceDate: record.invoiceDate ? moment(record.invoiceDate).format('DD-MM-YYYY') : '-',
      eta: record.eta ? moment(record.eta).format('DD-MM-YYYY') : '-',
      invoiceINR: invoiceINR ? invoiceINR.toFixed(2) : '-',
      balanceReceivable: (invoiceINR && !isNaN(balanceReceivable)) ? balanceReceivable.toFixed(2) : '-',
      dynamicColumn: dueDate ? balanceReceivable.toFixed(2) : '-',
      delayInDates: delayInDays > 0 ? `${delayInDays} days delayed` : '-',
      aging
    };
  });
};

  
 const exportExcel = () => {
  const preprocessedData = preprocessDataForExport(report);

  let totalInvoiceAmt = 0;
  let totalInvoiceINR = 0;
  let totalCollection = 0;
  let totalBalanceReceivable = 0;

  preprocessedData.forEach(({ invoiceAmt, exchangeRate, collection }) => {
    const amt = parseFloat(invoiceAmt) || 0;
    const rate = parseFloat(exchangeRate) || 0;
    const coll = parseFloat(collection) || 0;

    const invoiceINR = amt * rate;
    const balance = invoiceINR - coll;

    totalInvoiceAmt += amt;
    totalInvoiceINR += invoiceINR;
    totalCollection += coll;
    totalBalanceReceivable += balance;
  });

  const summaryRow = {
    id: 'Total',
    poNumber: '',
    invoiceNum: '',
    invoiceDate: '',
    eta: '',
    partyName: '',
    invoiceAmt: totalInvoiceAmt.toFixed(2),
    exchangeRate: '',
    invoiceINR: totalInvoiceINR.toFixed(2),
    collection: totalCollection.toFixed(2),
    balanceReceivable: totalBalanceReceivable.toFixed(2),
    bankName: '',
    dueDate: '',
    delayInDates: '',
    aging: '',
    ...dynamicColumns.reduce((acc, col) => ({ ...acc, [col]: '' }), {}),
  };

  const excelData = [...preprocessedData, summaryRow];

  const excel = new Excel();
  excel
    .addSheet('receivables-summary-report')
    .addColumns(transformColumnsToExcelFormat(columns))
    .addDataSource(excelData, { str2num: true })
    .saveAs('receivables-summary.xlsx');
};


  const transformColumnsToExcelFormat = (columns) => {
    return columns.map(col => ({
      title: typeof col.title === 'string' ? col.title : 'Untitled',
      dataIndex: col.dataIndex || col.key,
      key: col.key
    }));
  };



  const getWeekOfMonth = (date) => {
    const startOfMonth = date.clone().startOf('month');
    const endOfMonth = date.clone().endOf('month');
    const startWeek = startOfMonth.week();
    const endWeek = endOfMonth.week();

    return date.week() - startWeek + 1;
  };

  const updateColumns = (dynamicCols) => {
    const baseColumns: ColumnProps<any>[] = [
      {
        title: 'S No',
        key: 'id',
        width: '70px',
        responsive: ['md'],
        align: 'left',
        render: (text, object, index) => (page - 1) * 10 + (index + 1)
      },
      {
        title: 'PO.NO',
        key: 'poNumber',
        dataIndex: 'poNumber',
        width: '70px',
        responsive: ['md'],
        align: 'left',
        ...getColumnSearchProps('poNumber'),
        sorter: (a, b) => a.poNumber?.localeCompare(b.poNumber),
        sortDirections: ['descend', 'ascend']
      },
      {
        title: 'Invoice No',
        key: 'invoiceNum',
        dataIndex: 'invoiceNum',
        width: '70px',
        responsive: ['md'],
        align: 'left',
        ...getColumnSearchProps('invoiceNum'),
        sorter: (a, b) => a.invoiceNum?.localeCompare(b.invoiceNum),
        sortDirections: ['descend', 'ascend']
      },
      {
        title: 'Invoice Date',
        key: 'invoiceDate',
        dataIndex: 'invoiceDate',
        width: '70px',
        render: (text: string) => {
          if (!text) return '-';
      
          return moment(text).format('DD-MM-YYYY');
        },
        
      },
      // {
      //   title: 'BL Date',
      //   key: 'blDate',
      //   dataIndex: 'blDate',
      //   width: '70px',
      //   responsive: ['md'],
      //   align: 'left',
      //   sorter: (a, b) => a.blDate?.localeCompare(b.blDate),
      //   sortDirections: ['descend', 'ascend'],
      //   render: (index, val) => (
      //     <span>{val.blDate ? moment(val.blDate).format("DD-MM-YYYY") : '-'}</span>
      //   )
      // },
      {
        title: 'ETA',
        key: 'eta',
        dataIndex: 'eta',
        width: '70px',
        responsive: ['md'],
        align: 'left',
        sorter: (a, b) => a.eta?.localeCompare(b.eta),
        sortDirections: ['descend', 'ascend'],
        render: (index, val) => (
          <span>{val.eta ? moment(val.eta).format("DD-MM-YYYY") : '-'}</span>
        )
      },
      {
        title: 'Party Name',
        key: 'partyName',
        dataIndex: 'partyName',
        width: '70px',
        responsive: ['md'],
        align: 'left',
        ...getColumnSearchProps('partyName'),
        sorter: (a, b) => a.partyName?.localeCompare(b.partyName),
        sortDirections: ['descend', 'ascend']
      },
      {
        title: 'Invoice Amount',
        key: 'invoiceAmt',
        dataIndex: 'invoiceAmt',
        width: '70px',
        responsive: ['md'],
        align: 'left',
        ...getColumnSearchProps('invoiceAmt'),
        sorter: (a, b) => a.invoiceAmt?.localeCompare(b.invoiceAmt),
        sortDirections: ['descend', 'ascend'],
        render: (text,value) => {
    return isNaN(value.invoiceAmt) ? '0.00' : Number(Number(value.invoiceAmt).toFixed(2)).toLocaleString();
  },
      },
      {
        title: 'Exchange Rate',
        key: 'exchangeRate',
        dataIndex: 'exchangeRate',
        width: '70px',
        responsive: ['md'],
        align: 'left',
        
      },
      {
        title: 'Invoice in INR',
        key: 'invoiceINR',
        width: '70px',
        responsive: ['md'],
        align: 'left',
        render:(_,record) =>{
          const {invoiceAmt, exchangeRate}= record;
          if(!invoiceAmt || !exchangeRate) return '-';
          const invoiceINR = invoiceAmt * exchangeRate;
          return Number(invoiceINR.toFixed(2)).toLocaleString();
        },
        
      },
      {
        title: 'Part Payment Recieved',
        key: 'collection',
        dataIndex: 'collection',
        width: '70px',
        responsive: ['md'],
        align: 'left',
        ...getColumnSearchProps('collection'),
render: (text) => {
    const value = parseFloat(text);
    return isNaN(value) ? '0.00' : Number(value.toFixed(2)).toLocaleString();
  },
  sorter: (a, b) => {
    const valA = parseFloat(a.collection) || 0;
    const valB = parseFloat(b.collection) || 0;
    return valA - valB;
  },        sortDirections: ['descend', 'ascend']
      },
      {
        title: 'Balance Receivable',
        key: 'balanceReceivable',
        dataIndex: 'balanceReceivable',
        width: '70px',
        responsive: ['md'],
        align: 'left',
       render: (_, record) => {
    const invoiceAmt = parseFloat(record.invoiceAmt);
    const exchangeRate = parseFloat(record.exchangeRate);
    const collection = parseFloat(record.collection) || 0;

    if (!invoiceAmt || !exchangeRate) return '0.00';

    const invoiceINR = invoiceAmt * exchangeRate;
    const balanceReceivable = invoiceINR - collection;
    return <span>{Number(balanceReceivable.toFixed(2)).toLocaleString()}</span>;
  },
  sorter: (a, b) => {
    const invoiceA = parseFloat(a.invoiceAmt) * parseFloat(a.exchangeRate) || 0;
    const collectionA = parseFloat(a.collection) || 0;
    const invoiceB = parseFloat(b.invoiceAmt) * parseFloat(b.exchangeRate) || 0;
    const collectionB = parseFloat(b.collection) || 0;

    const balanceA = invoiceA - collectionA;
    const balanceB = invoiceB - collectionB;

    return balanceA - balanceB;
  },
  sortDirections: ['descend', 'ascend'],

      },
      {
        title: 'Bank',
        key: 'bankName',
        dataIndex: 'bankName',
        width: '70px',
        responsive: ['md'],
        align: 'left',
        ...getColumnSearchProps('bankName'),
        sorter: (a, b) => a.bankName?.localeCompare(b.bankName),
        sortDirections: ['descend', 'ascend']
      },
      {
        title: 'FDA Cleared/Due Date',
        key: 'dueDate',
        dataIndex: 'dueDate'
      },
      
      {
        title: 'Aging',
        key:'aging',
        render:(text,record)=>{
          if (!record.invoiceDate) return '-';

          const invoiceDate = moment(record.invoiceDate, 'YYYY-MM-DD');
          if (!invoiceDate.isValid()) return 'Invalid Date';

          const today = moment();
          const agingDays = today.diff(invoiceDate, 'days');
          let color = 'green';
          if(agingDays > 30 ) color = 'red';
          else if(agingDays >15) color = 'yellow'

          return (
            <span style={{color, fontWeight: 'bold' }}>
              {agingDays}
            </span>
          );
        },
      },
    ];

    const dynamicColumnDefs = dynamicCols.map(col => ({
      title: col,
      key: col,
      dataIndex: col,
      width: 100,
      responsive: ['md'],
      align: 'left',
      sorter: (a, b) => a[col]?.localeCompare(b[col]),
      sortDirections: ['descend', 'ascend']
      }));

      const delayInDatesColumn: ColumnProps<any> = {
      title: 'Delay In Dates',
      key: 'delayInDates',
      width: '70px',
      responsive: ['md'],
      align: 'left',
      render: (index, val) => {
        const currentDate = moment();
        const dueDate = val.dueDate != null || val.dueDate != undefined ? moment(val.dueDate.split(' ')[0]) : null;
        const delayInDays = dueDate ? currentDate.diff(dueDate, 'days') : 0;

        return (
          <span>{delayInDays > 0 ? `${delayInDays} days delayed` : '-'}</span>
        );
      }
    };

    setColumns([...baseColumns, ...dynamicColumnDefs, delayInDatesColumn]);
  };

  return (
    <div>
      <Card
        title={<span style={{ color: 'white' }}>Expected Receivables Report</span>}
        extra={
          <div>
            <Button icon={<DownloadOutlined />} onClick={exportExcel} style={{ marginRight: 30 }}>
              Get Excel
            </Button>
          </div>
        }
        style={{ textAlign: 'center' }}
        headStyle={{ backgroundColor: '#69c0ff', border: 0 }}
      ></Card>
      <Table
        columns={columns}
        dataSource={report}
        scroll={{ x: true }}
        pagination={{
          onChange(current) {
            setPage(current);
          }
        }}
        bordered
        summary={pageData => {
          let totalInvoiceAmt = 0;
          let totalInvoiceINR = 0;
          let totalCollection = 0;
          let totalBalanceReceivable = 0;

          pageData.forEach(({ invoiceAmt,exchangeRate, collection }) => {
            const invoiceINR = (parseFloat(invoiceAmt) || 0) * (parseFloat(exchangeRate) || 1);
            totalInvoiceAmt += parseFloat(invoiceAmt) || 0;
            totalInvoiceINR += invoiceINR;
            totalCollection += parseFloat(collection) || 0;
            totalBalanceReceivable += (parseFloat(invoiceAmt) || 0) - (parseFloat(collection) || 0);
          });

          return (
            <Table.Summary.Row>
              <Table.Summary.Cell index={0} colSpan={6}>Total</Table.Summary.Cell>
              <Table.Summary.Cell index={7}>{Number(totalInvoiceAmt.toFixed(2)).toLocaleString()}</Table.Summary.Cell>
              <Table.Summary.Cell index={8}></Table.Summary.Cell>
              <Table.Summary.Cell index={9}>{Number(totalInvoiceINR.toFixed(2)).toLocaleString()}</Table.Summary.Cell>
              <Table.Summary.Cell index={10}>{Number(totalCollection.toFixed(2)).toLocaleString()}</Table.Summary.Cell>
              <Table.Summary.Cell index={11}>{Number(totalBalanceReceivable.toFixed(2)).toLocaleString()}</Table.Summary.Cell>
            </Table.Summary.Row>
          );
        }}
      />
    </div>
  );
};

export default ExpectedReceivablesReport;
