import { Grid, Typography, Divider, FormControl, InputLabel, Select, MenuItem, makeStyles, Button } from '@material-ui/core'
import { useTranslation } from 'react-i18next'
import CustomTable from '../../../Common/CustomTable/CustomTable'
import { getMarginColumns } from './Margin.columns'
import AddIcon from '@material-ui/icons/Add';
import { useCallback, useEffect, useReducer, useState } from 'react';
import MarginInputDialog from '../../../Dialogs/MarginInputDialog/MarginInputDialog';
import { DEFAULT, MOVEMENT_TYPES, USER_ROLES } from '../../../../Types/Constants';
import { MarginReducer } from './Margin.reducer';
import { IMarginFee, IMarginFeeSettingConfig } from '../../../../../../Application/DTOs/MarginFeeSettingsDto/MarginFeeSettingsDto.types';
import { formatForTableRows } from '../../../../Utilities/Formatting';
import { Company } from '../../../../Api/Company/Company';
import { ICompanyInfo } from '../../../../../../Application/DTOs/CompanyDto/CompanyDto.type';
import { setLoader } from '../../../../Redux/Loader/actions';
import { useDispatch, useSelector } from 'react-redux';
import { toast } from 'react-toastify';
import { GridCellParams, GridRowParams } from '@material-ui/data-grid';
import { isEmpty, isNil } from 'lodash';
import CheckIcon from '@material-ui/icons/Check';
import { AdminSettings } from '../../../../Api/AdminSettings/AdminSettings';
import { AppState } from '../../../../Redux';

const {
    EMPTY_PARK,
    FCL,
    FULL_TRUCK_LOAD,
    LAND_FREIGHT,
    LCL,
    LOOSE_CARGO,
    OTHER,
    RAIL,
    SEA_FREIGHT,
    WHARF,
    ALL
} = MOVEMENT_TYPES

const useStyles = makeStyles(() => ({
    formControl: {
        minWidth: '100%',
    },
    updateBtn: {
        backgroundColor: 'green',
        color: 'white',
        '&:hover': {
            backgroundColor: 'green',
            color: 'white',
        }
    }
}))

const generateInitialState = (): IMarginFeeSettingConfig => {
    return Object.values(MOVEMENT_TYPES).reduce<IMarginFeeSettingConfig>((config, movementType) => {
        config[movementType] = []

        return config
    }, {})
}

const initialState = generateInitialState()

const companyApi = new Company()

const adminSettingsApi = new AdminSettings()

const {
    ADMIN_USER
} = USER_ROLES

function Margin() {
    const [t] = useTranslation('Margin')
    const classes = useStyles()
    const dispatch = useDispatch()
    const user = useSelector((state: AppState) => state.user)
    const isUserAdmin = user.response?.type === ADMIN_USER
    const [isMarginInputOpen, setIsMarginInputOpen] = useState(false)
    const [marginFeeSettingConfigState, localDispatch] = useReducer(MarginReducer, initialState)
    const [selectedMarginFeeIndex, setSelectedMarginFeeIndex] = useState<number | null>(null)
    const [selectedMarginFee, setSelectedMarginFee] = useState<IMarginFee | undefined>(undefined)
    const [selectedCompanyId, setSelectedCompanyId] = useState(DEFAULT)
    const [selectedMovementType, setSelectedMovementType] = useState(ALL)
    const [companies, setCompanies] = useState<ICompanyInfo[]>([])

    useEffect(() => {
        if (isUserAdmin) {
            setSelectedCompanyId('')
        }

    }, [isUserAdmin])

    const getConfig = useCallback(
        (companyId: string) => {
            dispatch(setLoader(true))
            adminSettingsApi.getMarginFeeConfig(companyId)
                .then((response) => {
                    const config: IMarginFeeSettingConfig = response.data

                    if (isEmpty(config)) {
                        localDispatch({
                            type: 'SET',
                            payload: initialState
                        })
                    } else {
                        localDispatch({
                            type: 'SET',
                            payload: config
                        })
                    }

                    dispatch(setLoader(false))
                })
                .catch(err => {
                    console.log('err', err)
                    toast.error(t('error_getting_margin_config'))
                    dispatch(setLoader(false))
                })
        },
        [t, dispatch],
    )

    const handleMarginDialogClose = useCallback(
        () => {
            setIsMarginInputOpen(false)
            if (selectedMarginFee) {
                setSelectedMarginFee(undefined)
            }
        },
        [selectedMarginFee],
    )

    const handleOnDeleteCallback = useCallback(
        (cellParams: GridCellParams) => {
            if (!isNil(cellParams.rowIndex)) {
                localDispatch({
                    type: 'REMOVE',
                    payload: {
                        indexToRemove: cellParams.rowIndex,
                        movementType: selectedMovementType
                    }
                })
            } else {
                console.error('Margin Index not set!')
            }

        },
        [selectedMovementType],
    )

    const columns = getMarginColumns(t, handleOnDeleteCallback)

    const handleOnAddClick = useCallback(
        () => {
            setIsMarginInputOpen(true)
        },
        [],
    )

    useEffect(() => {
        dispatch(setLoader(true))
        companyApi.getAll(isUserAdmin ? user.response?.country : undefined)
            .then(response => {
                const companies: ICompanyInfo[] = response.data
                setCompanies(companies)
                dispatch(setLoader(false))
            })
            .catch(err => {
                console.log('err', err)
                toast.error(t('error_getting_all_companies'))
                dispatch(setLoader(false))
            })
    }, [dispatch, t, isUserAdmin, user.response?.country])

    const handleMarginInputOnSave = useCallback(
        (isCreated: boolean, marginPrice: IMarginFee) => {
            if (isCreated) {
                localDispatch({
                    type: 'ADD',
                    payload: {
                        marginFee: marginPrice,
                        movementType: selectedMovementType
                    }
                })
            } else {
                if (!isNil(selectedMarginFeeIndex)) {
                    localDispatch({
                        type: 'UPDATE',
                        payload: {
                            index: selectedMarginFeeIndex,
                            item: marginPrice,
                            movementType: selectedMovementType
                        }
                    })
                } else {
                    console.error(`Margin index was not set!`)
                }
            }

            handleMarginDialogClose()
        },
        [selectedMarginFeeIndex, selectedMovementType, handleMarginDialogClose],
    )

    useEffect(() => {
        if (selectedCompanyId === '') {
            setSelectedMovementType(ALL)

            localDispatch({
                type: 'SET',
                payload: initialState
            })

            return
        }


        if (selectedCompanyId === DEFAULT) {
            setSelectedMovementType(ALL)
        }

        getConfig(selectedCompanyId)

    }, [selectedCompanyId, getConfig])

    const handleOnRowClick = useCallback(
        (rowParams: GridRowParams) => {
            const marginFee: IMarginFee = rowParams.row as any
            setSelectedMarginFeeIndex(rowParams.getValue('id') as number)
            setSelectedMarginFee(marginFee)
            setIsMarginInputOpen(true)
        },
        [],
    )

    const handleOnUpdateClick = useCallback(
        () => {
            dispatch(setLoader(true))
            adminSettingsApi.updateMarginConfig(selectedCompanyId, marginFeeSettingConfigState)
                .then(() => {
                    toast.success(t('success_updating_margin_config'))
                    dispatch(setLoader(false))
                    getConfig(selectedCompanyId)
                })
                .catch(err => {
                    console.log('err', err)
                    toast.error(t('error_updating_margin_config'))
                    dispatch(setLoader(false))
                })
        },
        [dispatch, t, marginFeeSettingConfigState, selectedCompanyId, getConfig],
    )

    return (
        <>
            <MarginInputDialog currentMarginFee={selectedMarginFee} onSaveClick={handleMarginInputOnSave} open={isMarginInputOpen} handleClose={handleMarginDialogClose} />
            <Grid
                container
                direction="column"
                justifyContent="space-between"
                alignItems="stretch"
                spacing={5}
            >
                <Grid item>
                    <Typography>
                        {t('margin')}
                    </Typography>
                </Grid>
               
                <Grid item>
                    <Grid
                        container
                        spacing={2}
                    >
                        <Grid item md={12}>
                            <FormControl variant="filled" className={classes.formControl}>
                                <InputLabel style={{ fontWeight: 'bold' }}>{t('select_company')}</InputLabel>
                                <Select
                                    value={selectedCompanyId}
                                    onChange={(e) => setSelectedCompanyId(e.target.value as string)}
                                >

                                    {
                                        !isUserAdmin
                                            ? <MenuItem value={DEFAULT}>{t(DEFAULT)}</MenuItem>
                                            : null
                                    }

                                    {
                                        companies.map(company => (<MenuItem key={company.id} value={company.id}>{company.companyName}</MenuItem>))
                                    }
                                </Select>
                            </FormControl>
                        </Grid>
                        <Grid item md={12}>
                            <FormControl variant="filled" className={classes.formControl}>
                                <InputLabel style={{ fontWeight: 'bold' }}>{t('movement_type')}</InputLabel>
                                <Select
                                    value={selectedMovementType}
                                    onChange={(e) => setSelectedMovementType(e.target.value as string)}
                                    disabled={selectedCompanyId === DEFAULT || selectedCompanyId === ''}
                                >
                                    <MenuItem value={ALL}>{t(ALL)}</MenuItem>
                                    <MenuItem value={EMPTY_PARK}>{t(EMPTY_PARK)}</MenuItem>
                                    <MenuItem value={FCL}>{t(FCL)}</MenuItem>
                                    <MenuItem value={FULL_TRUCK_LOAD}>{t(FULL_TRUCK_LOAD)}</MenuItem>
                                    <MenuItem value={LAND_FREIGHT}>{t(LAND_FREIGHT)}</MenuItem>
                                    <MenuItem value={LCL}>{t(LCL)}</MenuItem>
                                    <MenuItem value={LOOSE_CARGO}>{t(LOOSE_CARGO)}</MenuItem>
                                    <MenuItem value={OTHER}>{t(OTHER)}</MenuItem>
                                    <MenuItem value={RAIL}>{t(RAIL)}</MenuItem>
                                    <MenuItem value={SEA_FREIGHT}>{t(SEA_FREIGHT)}</MenuItem>
                                    <MenuItem value={WHARF}>{t(WHARF)}</MenuItem>
                                </Select>
                            </FormControl>
                        </Grid>
                        <Grid item md={2}>
                            <Button onClick={handleOnAddClick} fullWidth variant="contained" startIcon={<AddIcon />} color="primary">
                                {t('add')}
                            </Button>
                        </Grid>
                        <Grid item md={10}>
                            {/* GAP */}
                        </Grid>
                        <Grid item md={12}>
                            <CustomTable
                                columns={columns}
                                rows={selectedCompanyId === '' ? [] : formatForTableRows(marginFeeSettingConfigState[selectedMovementType])}
                                onRowClick={handleOnRowClick}
                            />
                        </Grid>
                        <Grid item md={2}>
                            <Button onClick={handleOnUpdateClick} startIcon={<CheckIcon />} fullWidth className={classes.updateBtn} variant="contained">
                                {t('update')}
                            </Button>
                        </Grid>
                    </Grid>
                </Grid>
            </Grid>
        </>
    )
}

export default Margin