import { Table as RawTable, Typography } from 'antd'
import { Fragment, memo, useCallback, useEffect, useState } from 'react'

import LoaderPortal from '@components/LoaderPortal'
import { invokeWebApiWrapperAsync } from '@components/factory'
import { WellSelector } from '@components/selectors/WellSelector'
import { makeGroupColumn, makeNumericColumn, makeNumericRender, makeTextColumn, Table } from '@components/Table'
import { OperationStatService, WellOperationService } from '@api'
import { arrayOrDefault } from '@utils'

import '@styles/index.css'
import '@styles/statistics.less'

const { Text } = Typography
const { Summary } = RawTable
const { Cell, Row } = Summary

const numericRender = makeNumericRender()
const speedNumericRender = (section) => numericRender(section?.speed)

const makeSectionSorter = (key, name) => (a, b) => (a?.[key]?.[name] ?? 0) - (b?.[key]?.[name] ?? 0)
export const makeSectionColumn = (title, key, { speedRender } = {}) => makeGroupColumn(title, [
    makeNumericColumn('Проходка', key, null, null, (section => numericRender(section?.depth)), 100, {
        sorter: makeSectionSorter(key, 'depth'),
    }),
    makeNumericColumn('Время', key, null, null, (section => numericRender(section?.time)), 100, {
        sorter: makeSectionSorter(key, 'time'),
    }),
    makeNumericColumn((<>V<sub>рейсовая</sub></>), key, null, null, speedRender ?? speedNumericRender, 100, {
        sorter: makeSectionSorter(key, 'speed'),
    }),
])

export const defaultColumns = [
    //makeTextColumn('Куст', 'cluster', null, null, null, { fixed: 'left', width: 100 }),
    makeTextColumn('Скважина', 'caption', null, null, null, { fixed: 'left', width: 100 }),
]

const scrollSettings = { scrollToFirstRowOnChange: true, x: 100, y: 200 }
const summaryColSpan = 1 /// TODO: Когда добавится куст изменить на 2

const getWellData = async (wellsList) => {
    const stats = arrayOrDefault(await OperationStatService.getWellsStat(wellsList))
    const wellData = stats.map((well) => {
        const stat = {
            // cluster: null,
            caption: well.caption,
        }

        well.sections?.forEach(({ id, fact }) => {
            if (!fact) return
            stat[`section_${id}`] = {
                time: (+new Date(fact.end) - +new Date(fact.start)) / 3600_000,
                depth: fact.wellDepthEnd - fact.wellDepthStart,
                speed: fact.routeSpeed,
            }
        })

        return stat
    })

    return wellData
}

export const Statistics = memo(({ idWell }) => {
    const [sectionTypes, setSectionTypes] = useState([])
    const [avgColumns, setAvgColumns] = useState(defaultColumns)
    const [cmpColumns, setCmpColumns] = useState(defaultColumns)
    const [isAvgTableLoading, setIsAvgTableLoading] = useState(false)
    const [isCmpTableLoading, setIsCmpTableLoading] = useState(false)
    const [isPageLoading, setIsPageLoading] = useState(false)
    const [avgWells, setAvgWells] = useState([])
    const [cmpWells, setCmpWells] = useState([])
    const [avgData, setAvgData] = useState([])
    const [cmpData, setCmpData] = useState([])
    const [avgRow, setAvgRow] = useState({})

    const cmpSpeedRender = useCallback((key) => (section) => {
        let spanClass = ''
        // Дополнительная проверка на "null" необходима, чтобы значение "0" не стало исключением
        if ((avgRow[key]?.speed ?? null) !== null && (section?.speed ?? null) !== null) {
            const avgSpeed = avgRow[key].speed - section.speed
            if (avgSpeed < 0)
                spanClass = 'high-efficienty'
            else if (avgSpeed > 0)
                spanClass = 'low-efficienty'
        }

        return (
            <span className={spanClass}>
                {numericRender(section?.speed)}
            </span>
        )
    }, [avgRow])

    useEffect(() => invokeWebApiWrapperAsync(
        async () => {
            const types = await WellOperationService.getSectionTypes(idWell)
            setSectionTypes(Object.entries(types))
        },
        setIsPageLoading,
        `Не удалось получить типы секции`,
        `Получение списка возможных секций`,
    ), [idWell])

    useEffect(() => invokeWebApiWrapperAsync(
        async () => {
            const filteredSections = avgData?.length > 0 ? sectionTypes.filter(([id, _]) => avgData.some((row) => `section_${id}` in row)) : sectionTypes

            setAvgColumns([
                ...defaultColumns,
                ...filteredSections.map(([id, name]) => makeSectionColumn(name, `section_${id}`)),
            ])
            setCmpColumns([
                ...defaultColumns,
                ...filteredSections.map(([id, name]) => makeSectionColumn(name, `section_${id}`, {
                    speedRender: cmpSpeedRender(`section_${id}`)
                }))
            ])
        },
        setIsPageLoading,
        'Не удалось установить необходимые столбцы'
    ), [sectionTypes, avgData, cmpSpeedRender])

    useEffect(() => invokeWebApiWrapperAsync(
        async () => {
            const avgData = await getWellData(avgWells)
            setAvgData(avgData)

            const avgRow = {}

            avgData.forEach((row) => row && Object.keys(row).forEach((key) => {
                if (!key.startsWith('section_')) return
                if (!avgRow[key]) avgRow[key] = { depth: 0, time: 0, speed: 0, count: 0 }
                avgRow[key].depth += row[key].depth ?? 0
                avgRow[key].time += row[key].time ?? 0
                avgRow[key].speed += row[key].speed ?? 0
                avgRow[key].count++
            }))

            Object.values(avgRow).forEach((section) => section.speed /= section.count)

            setAvgRow(avgRow)
        },
        setIsAvgTableLoading,
        'Не удалось загрузить данные для расчёта средних значений',
    ), [avgWells])

    useEffect(() => invokeWebApiWrapperAsync(
        async () => {
            const cmpData = await getWellData(cmpWells)
            setCmpData(cmpData)
        },
        setIsCmpTableLoading,
        'Не удалось получить скважины для сравнения',
    ), [cmpWells])

    const getStatisticsAvgSummary = useCallback((data) => (
        <Summary fixed={'bottom'}>
            <Row>
                <Cell index={0} colSpan={summaryColSpan}>
                    <Text>Итого:</Text>
                </Cell>
                {sectionTypes.map(([id, _], i) => (
                    <Fragment key={id ?? i}>
                        <Cell index={3 * i + summaryColSpan}>
                            <Text>{numericRender(avgRow[`section_${id}`]?.depth)}</Text>
                        </Cell>
                        <Cell index={3 * i + summaryColSpan + 1}>
                            <Text>{numericRender(avgRow[`section_${id}`]?.time)}</Text>
                        </Cell>
                        <Cell index={3 * i + summaryColSpan + 2}>
                            <Text>{numericRender(avgRow[`section_${id}`]?.speed)}</Text>
                        </Cell>
                    </Fragment>
                ))}
            </Row>
        </Summary>
    ), [avgRow, sectionTypes])

    return (
        <div className={'statistics-page'}>
            <LoaderPortal show={isPageLoading}>
                <h2 style={{ padding: '10px' }}>Расчёт средних значений без Цифровой буровой</h2>
                <div className={'average-table'}>
                    <div className={'well-selector'}>
                        <span className={'well-selector-label'}>Выберите скважины для расчёта средних значений:</span>
                        <WellSelector
                            idWell={idWell}
                            value={avgWells}
                            style={{ flex: 100 }}
                            onChange={setAvgWells}
                            placeholder={'Ничего не выбрано'}
                        />
                    </div>
                    <Table
                        bordered
                        size={'small'}
                        pagination={false}
                        columns={avgColumns}
                        dataSource={avgData}
                        scroll={scrollSettings}
                        loading={isAvgTableLoading}
                        summary={getStatisticsAvgSummary}
                    />
                </div>
                <div className={'compare-table'}>
                    <div className={'well-selector'}>
                        <span className={'well-selector-label'}>Выберите скважины сравнения:</span>
                        <WellSelector
                            idWell={idWell}
                            value={cmpWells}
                            style={{ flex: 100 }}
                            onChange={setCmpWells}
                            placeholder={'Ничего не выбрано'}
                        />
                    </div>
                    <Table
                        bordered
                        size={'small'}
                        pagination={false}
                        columns={cmpColumns}
                        dataSource={cmpData}
                        scroll={scrollSettings}
                        loading={isCmpTableLoading}
                    />
                </div>
            </LoaderPortal>
        </div>
    )
})

export default Statistics
