import React, { useState, useEffect, useContext } from 'react';

import { Card, Button, Typography, Table, Skeleton, Input } from 'antd';

import { Location, Apiutils, FormCreator, GlobalContext, ExportReactCSV, getExportData } from './../../../../lib/';


import { CoreScripts } from './../../../../models/'

import moment from 'moment-timezone';

import { Link } from 'react-router-dom';

import './reporting-dashboard.scss';

import { ReloadOutlined } from '@ant-design/icons';

var genericComponents = require('./../../../../lib/modules/index');

const { Search } = Input;

const { Title, Text } = Typography;

export default function ReportingDashboard({ match, CustomComponents, reportId }) {

    const [config, setConfig] = useState({});

    const [formLayout, setFormLayout] = useState('inline');

    const [loading, setLoading] = useState(true);

    const [formContents, setformContents] = useState({});

    //In case of reports from core_script , there will be id from params 
    // In case of normal menu we need to take id from props
    const id = reportId ? reportId : match.params.id;

    const { CustomModels = {} } = useContext(GlobalContext);



    // let loadedModel = require('./../../../models/');

    // let details = [
    //     { "field": "start", "caption": "Date", "type": "date" },
    //     { "field": "end", "caption": "Date", "type": "date" },
    //     { "options": [0, 1, 2], "caption": "Quantity", "type": "select" },
    //     { "caption": "Time", "type": "datetime" },
    //     { "caption": "Appointments", field: 'appointment_name', "type": "reference-select", modelName: 'Appointments', label: 'da_fname' }
    // ]


    // 
    const [details, setDetails] = useState([]);

    const [columns, setColumns] = useState([]); // To set columns

    const [summaryColumns, setSummaryColumns] = useState([]);

    const [patients, setPatients] = useState([]); //Patients list array

    //PatiantData fetching function
    async function getPatientDetails() {

        setPatients([])

        CoreScripts.getRecord({ id }).then(({ result }) => {


            prepareInputParameters(result.input_parameters);

            setColumns(JSON.parse(result.display_columns));

            if (result.summary_columns) {

                setSummaryColumns(JSON.parse(result.summary_columns))

            }

            setConfig({ ...result });

            // initialLoding(result.input_parameters);

        });

    }
    /**
      * 
      * 
      * Manage initial render
      */
    useEffect(() => {

        getPatientDetails();

    }, []);

    /**
    * 
    * 
    * Will trigger if the report id is changes
    */
    useEffect(() => {

        getPatientDetails();

    }, [match.params.id]);


    let parameters;

    /**
     * Some parameters would need binding with the model
     * 
     * @param {*} input_parameters 
     */
    async function prepareInputParameters(input_parameters) {


        setLoading(true)

        let urlParams = Location.search()

        parameters = JSON.parse(input_parameters);

        let formContent = {}

        parameters = await parameters.map((record) => {

            // Only if the url params does have a matching value , 
            // we should not consider the default  value 

            if (urlParams[record.field]) {


                if (record.type === 'date') {


                    formContent[record.field] = moment.utc(urlParams[record.field]);

                }

                // return formContent;

            } else {

                // let StartDate, EndDate;
                switch (record.default) {

                    case "startOfDay":


                        formContent[record.field] = moment().utc().startOf('day'); //Start of the current day
                        break;

                    case "endOfDay":
                        formContent[record.field] = moment().utc().endOf('day'); // End of the current day
                        break;

                    case "startOfWeek":
                        formContent[record.field] = moment().utc().startOf('week').toDate();
                        break;

                    case "endOfWeek":
                        formContent[record.field] = moment().utc().endOf('week').toDate();
                        break;

                    case "currentDate":
                        formContent[record.field] = moment().utc();// current day

                        break;

                    default:
                        break;
                }



            }


            if (['reference-select', 'reference-search', 'select'].indexOf(record.type) !== -1) {

                // let model = "";
                let model = CustomModels[record.modelName];

                return {
                    ...record,
                    model,
                    required: record.required
                }
            } else {

                return {
                    ...record,
                    required: true
                }
            }


        });

        setformContents(formContent);

        onFinish(formContent);

        setLoading(false)

        setDetails([...parameters]);

    }


    function refresh() {
        getPatientDetails();
    }

    const onFinish = async (values) => {

        setLoading(true)

        // Cheacking if there is data and making the data url friendly, ie, if there is date in url
        if (config.input_parameters) {

            let urlsToUpdate = {}

            let parameterValue = JSON.parse(config.input_parameters);

            // Variable to store/update the form initial Values
            let formContent = {}

            parameters = await parameterValue.map((parameter) => {

                //Getting url friendly value by matching the url values and input_parameter values 
                let urlFriendlyValue = values[parameter.field];
                // Cheacking if the typr is date
                if (parameter.type === 'date') {

                    let field = parameter.field;
                    // Preparing formContent 
                    formContent = {
                        ...formContent,
                        [field]: urlFriendlyValue

                    }

                    // Converting the urlFriendlyValue to the format to be passed to date piker
                    urlFriendlyValue = moment(urlFriendlyValue).format('YYYY-MM-DD')

                    urlsToUpdate[parameter.field] = urlFriendlyValue;

                }

            })

            setformContents(formContent)

            Location.search({ ...urlsToUpdate })

        }

        if (values.date) {
            values.date = moment(values.date).format('YYYY-MM-DD')
        }
        let formBody = {
            "body": values
        }
        await CoreScripts.getReportingLisitng(id, formBody).then((result) => {

            //These changes done when the reporting dashboard breaks if there is no data, 
            // this happen due to the format of data coming in 2 different cases and following are the cases
            // In case of nura, by default the result comes as follows
            let resultDetails = result[0];
            // In case of Your centre, by default the result comes as follows 
            if (result?.result && result?.result[0]) {
                resultDetails = result.result[0]
            }
            setPatients(resultDetails);


            setLoading(false)

            return;

        });

    };

    let model = {
        "fields": details
    }

    return (
        <section className="reporting-dashboard card card-shadow">
            {/* Page Header */}
            {/* <div className="page-header">
                <div>
                    <Title style={{ marginBottom: '0px' }} level={4}>
                        {config.caption || 'Report'}
                    </Title>
                </div>

                <div className="right">
                    <div className="date-and-fltr">
                        <Button onClick={refresh} type="secondary" size={'small'}>
                            <ReloadOutlined />
                        </Button>
                    </div>
                </div>
            </div> */}
            {/* Page Header Ends */}

            {/* Content Below */}
            {
                loading ?
                    (
                        <>
                            <Skeleton active />
                        </>
                    )
                    :
                    (
                        <>
                            <div>

                                {/* <Card className="form-card" style={{ padding: '10px 10px' }}> */}
                                {
                                    details && details[0] && !loading ?


                                        <FormCreator
                                            {...formLayout}
                                            layout={formLayout}
                                            initialValues={{
                                                layout: formLayout,
                                            }}

                                            styles={{ paddingRight: '15px', alignItems: 'center' }}
                                            fields={details}
                                            formContent={formContents}
                                            // formContent={{ [model]: {} }}
                                            modelIndex='requestId'
                                            model={model}
                                            onSubmit={onFinish}
                                            callback={() => {

                                                // history.goBack();

                                            }}
                                        />
                                        :
                                        null
                                }
                                {/* </Card> */}
                            </div>
                            <GuestList patients={patients} columns={columns} summaryColumns={summaryColumns}

                                CustomComponents={{ ...CustomComponents, ...genericComponents }} refresh={refresh} />
                        </>
                    )
            }
        </section>
    );
}

function GuestList({ patients, columns, summaryColumns, CustomComponents, refresh }) {

    var [query, setQuery] = useState('');

    const [exportData, setExportData] = useState({});

    const [data, setData] = useState([]);

    const { user = {}, isMobile, dispatch } = useContext(GlobalContext);

    const [view, setView] = useState(isMobile ? true : false); //Need to check this condition

    const cols = [
        ...[
            {
                title: '#',
                dataIndex: 'index',
                render: (value, item, index) => index + 1,
                key: 'ColumnIndex'
            },
        ],
        ...columns.map((entry) => {

            // if (entry.sort) {
            //     return {
            //         render: (record) => {
            //             if (entry.render) {
            //                 return entry.render(record);
            //             } else {
            //                 return record[entry.dataIndex]
            //             }
            //         },
            //         title: entry.title,
            //         key: entry.field,
            //         sorter: (a, b) => entry.sort(a, b),
            //         sortDirections: ['ascend', 'descend', 'ascend'],
            //     };
            // } else {
            return {
                render: (record) => {


                    // We can have x types of components that is to be rendered here
                    // 1. Column Data
                    // 2. Action 
                    // 3. Custom Component - In future .  

                    if (entry.render) {

                        return entry.render(record);

                        // The type of component can be differentiated by type/ we can also reuse 
                        // any field present in the columns to avoid any additional field
                    } else if (entry.field === 'action') {

                        let redirectLink = entry.redirect_link;

                        // The variables to be replaced can be maintained 
                        // as a configuration in the entry or the column configuration

                        // We iterate through all the variables that are present in the configuration
                        // and replace the link to generate the final link 

                        entry.replace_variables.forEach((replacement) => {

                            redirectLink = redirectLink.replace(new RegExp('@' + replacement.field + ';', 'g'), record[replacement.field])

                        });

                        return <Link to={`${redirectLink}`}>View</Link>;

                    } else if (entry.field === 'custom') {

                        // Make all the components in modules available for use in custom column of core script
                        // var genericComponents = require('./../../../../../../../nura-api-new/nura-desk/src/modules');
                        var genericComponents = CustomComponents;

                        // Arrive the component name
                        let componentName = entry.component;

                        let LoadedComponent = null;
                        // If there is custom components mensioned in the display_columns, 
                        // then matching the custom components with the generic components
                        if (componentName) {

                            if (componentName && genericComponents[componentName]) {

                                LoadedComponent = genericComponents[componentName]

                            }
                        }

                        let propValue = {};
                        // If there is props value
                        if (entry.props) {

                            // Looping the props from the props mensioned in display_columns, 
                            // Matching the field of record props field with the and return the 
                            entry.props.forEach((values) => {
                                // Matching the fields of record with the props field
                                let valueCreation = record[values.field];
                                // Returning the values of field matched by fields 
                                propValue[values.value] = valueCreation

                            })
                        }

                        return <LoadedComponent

                            // Configuration will define 
                            {...entry.config}

                            callback={() => {
                                refresh();
                            }}

                            // record={record}

                            {...record}

                            // assigning the props
                            {...propValue}

                        />;

                    }

                    else {

                        return record[entry.field]
                    }
                },
                field: entry.field,
                title: entry.title,
                key: entry.field,
                exportDefinition: (record) => {
                    //Custom components should not be downloaded
                    return entry.field === 'custom' ? null : record[entry.field]

                },
            };
            // }
        }),
        // ...[
        //     {
        //         title: '',
        //         key: 'action',
        //         render: (text, record) => {
        //             let detail = model.slice(0, model.length - 1);

        //             return (
        //                 <Space size="middle">
        //                     {!schema.hideView && !actions.length ? <Link to={`/${city}/${model}/${text.id}`}>View</Link> : null}

        //                     {actions.map((action) => (
        //                         <Link to={action.url(record)}>{action.caption}</Link>
        //                     ))}
        //                 </Space>
        //             );
        //         },
        //     },
        // ],

        // ...[
        //     {
        //         title: '',
        //         key: 'action',
        //         render: (text, record) => {
        //             let detail = model.slice(0, model.length - 1);

        //             return (
        //                 <Link to={`${menu.path.replace(':id',visitid)}?op_no=${OpNo}`}>
        //                     <Button size={'small'}>
        //                         <PlayCircleOutlined />
        //                         Go to Menu
        //                     </Button>
        //                 </Link>
        //             );
        //         },
        //     },
        // ],

    ];


    function changeView(result) {
        setView(result);
    }


    function onSearch(event) {

        setQuery(event.target.value);
    }


    useEffect(() => {
        //Cheaking if there is patient data exists
        if (patients) {

            let data = patients?.map((entry) => {
                entry.rowIndex = entry.opb_id;

                entry.dispatch = dispatch;

                return entry;
            });

            setData(data);

            // Define export data
            let exportDatas = getExportData(patients, cols);

            if (exportDatas.exportDataColumns.length && exportDatas.exportDataHeaders.length) {
                setExportData({ exportDatas });
            }
        }

    }, [patients]);


    let filtered;

    if (patients) {
        filtered = patients.filter((record) => {

            if (query) {

                // Keys
                let keys = Object.keys(record);

                let flag = false;

                keys.forEach((key) => {

                    let ele = record[key]

                    if (ele && typeof ele === 'string' && ele.toLowerCase().indexOf(query.toLowerCase()) !== -1) {

                        flag = true;
                    }
                })

                return flag;

            } else {
                return true;
            }
        })

    }

    return (
        <>
            <div className="table-header">

                <div>

                    <Search placeholder="Enter Search Value" allowClear onChange={onSearch} />

                    {/* <p className="size-hint">{patients.length} records.</p> */}

                </div>

                <div>

                    {/*table data export to csc component*/}
                    {exportData.exportDatas && <ExportReactCSV headers={exportData.exportDatas.exportDataHeaders} csvData={exportData.exportDatas.exportDataColumns} />}

                </div>

            </div>

            <div>
                {/* {view ? (
                    <>
                        <CardList dataSource={data} columns={columns} />
                    </>
                ) : (
                    <> */}
                <Card>
                    <Table
                        size="small"
                        scroll={{ x: true }}
                        rowKey={(record) => record.OpNo}
                        dataSource={filtered ? filtered : patients} // In case if there is no filtered values we can use patient data
                        columns={cols}
                        pagination={false}
                        summary={(pageData) => {

                            // Variable to save the summary data
                            let summary = {};

                            let summaryColumns = [{ "field": "opb_amt", "title": 'Amount' }, { "field": "opb_netamt", "title": 'Net Amount' }];

                            let tableColumns = cols;

                            // Creating a copy of columns to append the summary configuration that is needed to set
                            tableColumns.forEach((record, index) => {

                                summaryColumns.forEach((inner) => {

                                    if (record.field === inner.field) {

                                        tableColumns[index].summary = inner;

                                    }
                                })
                            })

                            // Initialize
                            summaryColumns.map((item) => {
                                return summary[item.field] = 0
                            })

                            // Find the total
                            summaryColumns.map((item) => {
                                pageData.forEach((entry) => {
                                    return summary[item.field] = summary[item.field] + entry[item.field]
                                })
                            })

                            return (
                                <>
                                    <Table.Summary.Row>

                                        {
                                            tableColumns.map((column, key) => {

                                                return (<Table.Summary.Cell key={key}>

                                                    {
                                                        column.summary
                                                            ?
                                                            <>

                                                                {summary[column.summary.field]}

                                                            </>
                                                            :
                                                            null
                                                    }
                                                </Table.Summary.Cell>)

                                            })
                                        }

                                    </Table.Summary.Row>
                                </>
                            );
                        }}
                    />
                    {/*If patient data exists show the number else to 0 */}
                    <p className="size-hint">{patients ? patients.length : 0} records. </p>

                </Card>
                {/* </> */}
                {/* )} */}
            </div>
        </>
    );
}

//Mobile view card Section
function CardList({ dataSource, columns, url }) {
    const { user = {}, isMobile, dispatch } = useContext(GlobalContext);

    function onClick(item) {
        Location.navigate({
            url: `/lab-detail/${item.BillID}`,
        });

        dispatch({ type: 'index', payload: item.rowIndex });
    }

    return dataSource.map((item, index) => {
        // to={`/lab-detail/${item.BillID}`}
        return (
            <div
                key={index}
                className="report-item"
                onClick={() => {
                    onClick(item);
                }}
            >
                <GuestCard record={item} />
            </div>
        );
    });
}

function GuestCard({ record }) {
    return (
        <Card className="card vehicle-card">
            <div className="card">
                <h2 className="title">{record.PName}</h2>

                <h4 className="values">{record.OpNo}</h4>

                <h3 className="values">{record.Test}</h3>

                <h3 className="values">Primary Result : {record.PrimaryResult || 'Pending'}</h3>

                <Text type="secondary">{record.Mobile}</Text>

                <h4 className="values">{record.Date}</h4>
            </div>
        </Card>
    );
}

