import _ from 'lodash'
import { render } from 'preact'
import { useEffect, useState } from 'preact/hooks'
import semesterData from './semester-data.json'

// import { ToolOverlay } from './components/ToolOverlay.jsx'
//
// import {
//     EventsView,
//     MODE_COURSES,
//     MODE_SCHEDULE,
// } from './components/EventsView.jsx'

import { HamburgerMenu } from './components/HamburgerMenu.jsx'
import { Help } from './components/Help.jsx'
import { Icon } from './components/Icon.jsx'
import { OptionBar } from './components/OptionBar.jsx'
import { Popup } from './components/Popup.jsx'
import { Toolbar } from './components/Toolbar.jsx'
import { Courses } from './components/view/Courses.jsx'
import { Schedule } from './components/view/Schedule.jsx'
import { prettyAulaName, prettyProfName, usePersistentState } from './utils.jsx'

import { SettingsBar } from './components/SettingsBar.jsx'

// Che fanno queste due righe?
window._ = _
window.dataBuffer = {}

// NOTA: magistrale *non* è quello con i corsi a cavallo
const TIMETABLE_IDS = semesterData.timetableIds

// const DEFAULT_DATE_RANGE = {
//     from: '2023-10-09T00:00:00.000Z',
//     to: '2023-10-14T00:00:00.000Z',
// }

// const DATE_RANGES = {
//     '64a7c1c651f079001d52e9c8': DEFAULT_DATE_RANGE,
//     '6308e2dc09352a0208fefdd9': DEFAULT_DATE_RANGE,
//     '6308e42a1df5cb026699ced4': DEFAULT_DATE_RANGE,
//     '64a7c7091ab813002c5d9ede': DEFAULT_DATE_RANGE,
// }

function specialEventPatches(eventi) {
    // Il laboratorio del primo anno in realtà è in due gruppi separati
    eventi.forEach(evento => {
        console.log(evento.id, evento.nome, evento.dataInizio, evento.dataFine)

        if (
            evento.nome === 'LABORATORIO DI INTRODUZIONE ALLA MATEMATICA COMPUTAZIONALE'
        ) {
            if (evento.evento.dettagliDidattici[0].partizione.descrizione === 'CORSO A') {
                evento.nome += ' (A)'
            }
            if (evento.evento.dettagliDidattici[0].partizione.descrizione === 'CORSO B') {
                evento.nome += ' (B)'
            }
        }
    })

    return eventi
}

function formatEvents(timetable) {
    return timetable.map(({ nome, dataInizio, dataFine, docenti, aule }) => {
        return {
            id: nome,
            name: _.split(nome, '-', 1)[0].trim(),
            start: new Date(dataInizio),
            end: new Date(dataFine),
            docenti: docenti.map(({ nome, cognome }) => prettyProfName(nome, cognome)),
            aule: aule.map(aula => prettyAulaName(aula.codice)),
        }
    })
}

async function loadCalendari(date) {
    function getMonday(d) {
        const day = d.getDay()
        const diff = d.getDate() - day + (day === 0 ? -6 : 1)
        const monday = new Date(d.setDate(diff))
        monday.setUTCHours(0, 0, 0, 0)
        return monday
    }
    const monday = getMonday(date)
    const saturday = new Date(monday)
    saturday.setDate(monday.getDate() + 5)

    async function req(id) {
        // Almost directly copy-pasted from Chrome Dev Tools
        const req = await fetch(
            'https://apache.prod.up.cineca.it/api/Impegni/getImpegniCalendarioPubblico',
            {
                headers: {
                    'content-type': 'application/json;charset=UTF-8',
                    'sec-fetch-dest': 'empty',
                    'sec-fetch-mode': 'cors',
                    'sec-fetch-site': 'same-site',
                },
                body: JSON.stringify({
                    mostraImpegniAnnullati: true,
                    mostraIndisponibilitaTotali: false,
                    linkCalendarioId: id,
                    clienteId: '628de8b9b63679f193b87046',
                    pianificazioneTemplate: false,
                    dataInizio: monday.toISOString(),
                    dataFine: saturday.toISOString(),
                }),
                method: 'POST',
                mode: 'cors',
                credentials: 'omit',
            },
        )

        return await req.json()
    }

    const requests = [
        req(TIMETABLE_IDS['anno-1']),
        req(TIMETABLE_IDS['anno-2']),
        req(TIMETABLE_IDS['anno-3']),
        req(TIMETABLE_IDS['magistrale']),
    ]
    const results = await Promise.all(requests)
    const timetablesRaw = results.map(timetable =>
        specialEventPatches(_.uniqBy(timetable, 'id')),
    )
    const allRaw = _.uniqBy(specialEventPatches(_.concat(...results)), 'id')

    return {
        'anno-1': formatEvents(timetablesRaw[0]),
        'anno-2': formatEvents(timetablesRaw[1]),
        'anno-3': formatEvents(timetablesRaw[2]),
        'magistrale': formatEvents(timetablesRaw[3]),
        'tutti': formatEvents(allRaw),
    }
}

const View = ({ view, selection, setSelection, timetables }) => {
    if (view === 'orario') {
        return <Schedule selection={selection} timetables={timetables} />
    } else if (view === 'lista') {
        return (
            <Courses
                selection={selection}
                setSelection={setSelection}
                source={'tutti'}
                timetables={timetables}
                hideOtherCourses={true}
            />
        )
    } else {
        return (
            <Courses
                selection={selection}
                setSelection={setSelection}
                source={view}
                timetables={timetables}
                hideOtherCourses={false}
            />
        )
    }
}
const App = ({}) => {
    // Clear persistent states unless state_token corresponds to the one passed
    // as the argument. Useful with breaking updates. Change this token if your
    // (breaking) update needs a reset of persistent states to avoid crashes.
    //
    // Use any random string of your choice
    // clearOldPersistentStates('e73cba02')

    const [date, setDate] = useState(new Date().toISOString())

    // Data Sources
    const [view, setView] = usePersistentState('view', 'tutti')
    const [timetables, setTimetables] = useState(null)
    useEffect(async () => {
        setTimetables(await loadCalendari(new Date(date)))
    }, [date])

    // View Modes
    // const [mode, setMode] = usePersistentState('orario.mode', MODE_COURSES)

    // Selection
    const [selectedCourses, setSelectedCourses] = usePersistentState('selection', [])

    // Menus
    const [helpVisible, setHelpVisible] = useState(false)
    const [showMobileMenu, setShowMobileMenu] = useState(false)

    const [theme, setTheme] = usePersistentState(
        'theme',
        'light',
        // window.matchMedia('(prefers-color-scheme: dark)').matches
        //     ? 'dark'
        //     : 'light'
    )

    document.body.classList.toggle('dark-mode', theme === 'dark')

    return (
        <>
            <Toolbar
                {...{
                    source: view,
                    setSource: setView,
                    date: date,
                    setDate: setDate,
                    showMobileMenu: showMobileMenu,
                    setShowMobileMenu: setShowMobileMenu,
                    onHelp: () => setHelpVisible(true),
                    theme,
                    setTheme,
                }}
            />
            {showMobileMenu ? (
                <SettingsBar
                    {...{
                        theme,
                        setTheme,
                        date,
                        setDate,
                    }}
                />
            ) : (
                <OptionBar
                    {...{
                        view: view,
                        setView: setView,
                        onHelp: () => setHelpVisible(true),
                    }}
                    orizzontale
                />
            )}

            <div class="content">
                {timetables &&
                    (showMobileMenu ? (
                        <HamburgerMenu
                            {...{
                                date,
                                setDate,
                                theme,
                                setTheme,
                                onClose: () => {
                                    setShowMobileMenu(false)
                                },
                            }}
                        />
                    ) : timetables['tutti'].length === 0 ? (
                        <div class="warning">
                            <p>
                                Non esistono corsi per la settimana selezionata: buone
                                vacanze! 🎉
                            </p>
                            <p>
                                Clicca sul bottone qua sotto per vedere la prima settimana
                                completa di lezioni:
                            </p>
                            <button
                                onClick={() => {
                                    setDate(semesterData.firstMondayDate)
                                }}
                            >
                                {semesterData.buttonText}
                            </button>

                            {/* <p>
                                Per cambiare settimana puoi usare il widget Calendario (
                                <Icon name="calendar_month" />) in alto a destra
                                <br />
                                In versione mobile, il widget Calendario è situato dentro
                                il Menu (
                                <Icon name="menu" />)
                            </p> */}
                        </div>
                    ) : (
                        <View
                            selection={selectedCourses}
                            setSelection={setSelectedCourses}
                            view={view}
                            timetables={timetables}
                        />
                    ))}
            </div>

            {/* showMobileMenu && (
            ) */}
            {helpVisible && (
                <Popup
                    title={
                        <>
                            <Icon name="info" /> Guida
                        </>
                    }
                    onClose={() => setHelpVisible(false)}
                >
                    <Help />
                </Popup>
            )}
        </>
    )
}

render(<App />, document.body)
