import React, { useContext, useEffect, useMemo, useRef, useState, useCallback } from 'react';
import 'bootstrap/dist/css/bootstrap.min.css';
import { EVENT_DISCONNECT, EVENT_MESSAGE, EVENT_PENDING_QR, SocketContext } from './context/socket';
import { useAuth } from './context/auth';
import Login from './Login';
import { Alert, Button, Col, Form, Row, Table } from 'react-bootstrap';
import Header from './components/Header';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import PizzaOrderList from './components/PizzaOrderList';
import SelectSearch, { SelectedOptionValue, SelectSearchOption } from 'react-select-search';
import 'react-select-search/style.css';
import './App.scss';
import { faCircleCheck, faNoteSticky, faTrashCan, faComment } from '@fortawesome/free-regular-svg-icons';
import { useSettings } from './context/settings';
import Footer from './components/Footer';
import { faBasketShopping, faChainBroken, faChevronLeft, faChevronRight, faGear, faMoneyBillTransfer, faSatelliteDish, faSearch, faTriangleExclamation } from '@fortawesome/free-solid-svg-icons';
import Loader from './components/Loader';
import { getHumanDateTime, isInTheFuture, formatDateString } from './Utils';
import NoteModal from './components/modals/NoteModal';
import PayForAllModal from './components/modals/PayForAllModal';
import { useEasterEgg } from './context/eggs';
import { ClientData, Food, MealSlot, PendingQr, PizzaOrder, DepartureTime, PizzaDayState, Restaurant, RestaurantDayMenu, RestaurantDayMenuMap, LunchChoice, LocationLunchChoicesMap, UserLunchChoice, PizzaVariant, getData, getEasterEggImage, addPizza, removePizza, updatePizzaDayNote, createPizzaDay, deletePizzaDay, lockPizzaDay, unlockPizzaDay, finishOrder, finishDelivery, addChoice, jdemeObed, removeChoices, removeChoice, updateNote, changeDepartureTime, setBuyer, dismissQr, generateQr } from '../../types';
import { getLunchChoiceName } from './enums';
// import FallingLeaves, { LEAF_PRESETS, LEAF_COLOR_THEMES } from './FallingLeaves';
// import './FallingLeaves.scss';

const EVENT_CONNECT = "connect"

// Fixní styl pro všechny easter egg obrázky
const EASTER_EGG_STYLE = {
  zIndex: 1,
  animationName: "bounce-in",
  animationTimingFunction: "ease"
}

// Mapování čísel alergenů na jejich názvy
const ALLERGENS: { [key: number]: string } = {
  1: "Obiloviny obsahující lepek",
  2: "Korýši a výrobky z nich",
  3: "Vejce a výrobky z nich",
  4: "Ryby a výrobky z nich",
  5: "Arašidy a výrobky z nich",
  6: "Sója a výrobky z nich",
  7: "Mléko a výrobky z nich (včetně laktózy)",
  8: "Skořápkové plody",
  9: "Celer a výrobky z něj",
  10: "Hořčice a výrobky z ní",
  11: "Sezamová semena a výrobky z nich",
  12: "Oxid siřičitý a siřičitany",
  13: "Vlčí bob (Lupina) a výrobky z něj",
  14: "Měkkýši a výrobky z nich"
}

const LINK_ALLERGENS = 'https://www.strava.cz/Strava/Napoveda/cz/Prilohy/alergeny.pdf';

// Výchozí doba trvání animace v sekundách, pokud není přetíženo v konfiguračním JSONu
const EASTER_EGG_DEFAULT_DURATION = 0.75;

function App() {
  const auth = useAuth();
  const settings = useSettings();
  const [easterEgg, _] = useEasterEgg(auth);
  const [isConnected, setIsConnected] = useState<boolean>(false);
  const [data, setData] = useState<ClientData>();
  const [food, setFood] = useState<RestaurantDayMenuMap>();
  const [myOrder, setMyOrder] = useState<PizzaOrder>();
  const [foodChoiceList, setFoodChoiceList] = useState<Food[]>();
  const [closed, setClosed] = useState<boolean>(false);
  const socket = useContext(SocketContext);
  const choiceRef = useRef<HTMLSelectElement>(null);
  const foodChoiceRef = useRef<HTMLSelectElement>(null);
  const departureChoiceRef = useRef<HTMLSelectElement>(null);
  const pizzaPoznamkaRef = useRef<HTMLInputElement>(null);
  const [failure, setFailure] = useState<boolean>(false);
  const [dayIndex, setDayIndex] = useState<number>();
  const [loadingPizzaDay, setLoadingPizzaDay] = useState<boolean>(false);
  const [noteModalOpen, setNoteModalOpen] = useState<boolean>(false);
  const [payForAllLocationKey, setPayForAllLocationKey] = useState<LunchChoice | null>(null);
  const [eggImage, setEggImage] = useState<Blob>();
  const eggRef = useRef<HTMLImageElement>(null);
  // Prazvláštní workaround, aby socket.io listener viděl aktuální hodnotu
  // https://medium.com/@kishorkrishna/cant-access-latest-state-inside-socket-io-listener-heres-how-to-fix-it-1522a5abebdb
  const dayIndexRef = useRef<number | undefined>(dayIndex);

  // Načtení dat po přihlášení
  useEffect(() => {
    if (!auth?.login) {
      return
    }
    getData().then(response => {
      const data = response.data
      if (data) {
        setData(data);
        setDayIndex(data.dayIndex);
        dayIndexRef.current = data.dayIndex;
        setFood(data.menus);
      }
    }).catch(e => {
      setFailure(true);
    })
  }, [auth, auth?.login]);

  // Přenačtení pro zvolený den
  useEffect(() => {
    if (!auth?.login) {
      return
    }
    getData({ query: { dayIndex: dayIndex } }).then(response => {
      const data = response.data;
      setData(data);
      if (data) {
        setFood(data.menus);
      }
    }).catch(e => {
      setFailure(true);
    })
  }, [dayIndex, auth]);

  // Registrace socket eventů
  useEffect(() => {
    socket.on(EVENT_CONNECT, () => {
      setIsConnected(true);
    });
    socket.on(EVENT_DISCONNECT, () => {
      setIsConnected(false);
    });
    socket.on(EVENT_MESSAGE, (newData: ClientData) => {
      // console.log("Přijata nová data ze socketu", newData);
      if (newData.slot === MealSlot.EXTRA) return;
      // Aktualizujeme pouze, pokud jsme dostali data pro den, který máme aktuálně zobrazený
      if (dayIndexRef.current == null || newData.dayIndex === dayIndexRef.current) {
        setData(newData);
      }
    });
    socket.on(EVENT_PENDING_QR, (pendingQr: PendingQr) => {
      setData(prev => prev ? { ...prev, pendingQrs: [...(prev.pendingQrs ?? []), pendingQr] } : prev);
    });

    return () => {
      socket.off(EVENT_CONNECT);
      socket.off(EVENT_DISCONNECT);
      socket.off(EVENT_MESSAGE);
      socket.off(EVENT_PENDING_QR);
    }
  }, [socket]);

  // Připojení do osobní socket místnosti po přihlášení
  useEffect(() => {
    if (auth?.login) {
      socket.emit('join', auth.login);
    }
  }, [auth?.login, socket]);

  useEffect(() => {
    if (!auth?.login || !data?.choices) {
      return
    }
    // Pre-fill form refs from existing choices
    let foundKey: LunchChoice | undefined;
    let foundChoice: UserLunchChoice | undefined;
    for (const key of Object.keys(data.choices)) {
      const locationKey = key as LunchChoice;
      const locationChoices = data.choices[locationKey];
      if (locationChoices && auth.login in locationChoices) {
        foundKey = locationKey;
        foundChoice = locationChoices[auth.login];
        break;
      }
    }
    if (foundKey && choiceRef.current) {
      choiceRef.current.value = foundKey;
      const restaurantKey = Object.keys(Restaurant).indexOf(foundKey);
      if (restaurantKey > -1 && food) {
        const restaurant = Object.keys(Restaurant)[restaurantKey] as Restaurant;
        setFoodChoiceList(food[restaurant]?.food);
        setClosed(food[restaurant]?.closed ?? false);
      }
    }
    if (foundChoice?.departureTime && departureChoiceRef.current) {
      departureChoiceRef.current.value = foundChoice.departureTime;
    }
  }, [auth, auth?.login, data?.choices])

  // Reference na mojí objednávku
  useEffect(() => {
    if (data?.pizzaDay?.orders) {
      const myOrder = data.pizzaDay.orders.find(o => o.customer === auth?.login);
      setMyOrder(myOrder);
    }
  }, [auth?.login, data?.pizzaDay?.orders])

  // Kontrola, zda má uživatel vybranou volbu PIZZA
  const userHasPizzaChoice = useMemo(() => {
    return auth?.login ? data?.choices?.PIZZA?.[auth.login] != null : false;
  }, [data?.choices?.PIZZA, auth?.login]);

  useEffect(() => {
    if (choiceRef?.current?.value && choiceRef.current.value !== "") {
      const locationKey = choiceRef.current.value as LunchChoice;
      const restaurantKey = Object.keys(Restaurant).indexOf(locationKey);
      if (restaurantKey > -1 && food) {
        const restaurant = Object.keys(Restaurant)[restaurantKey] as Restaurant;
        setFoodChoiceList(food[restaurant]?.food);
        setClosed(food[restaurant]?.closed ?? false);
      } else {
        setFoodChoiceList(undefined);
        setClosed(false);
      }
    } else {
      setFoodChoiceList(undefined);
      setClosed(false);
    }
  }, [choiceRef.current?.value, food])

  // Navigace mezi dny pomocí klávesových šípek
  const handleKeyDown = useCallback((e: any) => {
    if (e.keyCode === 37 && dayIndex != null && dayIndex > 0) {
      handleDayChange(dayIndex - 1);
    } else if (e.keyCode === 39 && dayIndex != null && dayIndex < 4) {
      handleDayChange(dayIndex + 1);
    }
  }, [dayIndex]);

  useEffect(() => {
    document.addEventListener('keydown', handleKeyDown);
    return () => {
      document.removeEventListener('keydown', handleKeyDown);
    }
  }, [handleKeyDown]);

  // Stažení a nastavení easter egg obrázku
  useEffect(() => {
    if (auth?.login && easterEgg?.url && !eggImage) {
      getEasterEggImage({ path: { url: easterEgg.url } }).then(response => {
        if (response.data) {
          setEggImage(response.data);
          // Smazání obrázku z DOMu po animaci
          setTimeout(() => {
            if (eggRef?.current) {
              eggRef.current.remove();
            }
          }, (easterEgg.duration || EASTER_EGG_DEFAULT_DURATION) * 1000);
        }
      });
    }
  }, [auth?.login, easterEgg?.duration, easterEgg?.url, eggImage]);

  // Pomocná funkce pro kontrolu a potvrzení změny volby při existujícím Pizza day
  const checkPizzaDayBeforeChange = async (newLocationKey: LunchChoice): Promise<boolean> => {
    if (!auth?.login || !data) return false;

    // Kontrola, zda uživatel má vybranou PIZZA a mění na něco jiného
    const hasPizzaChoice = data.choices?.PIZZA?.[auth.login] != null;
    const isCreator = data.pizzaDay?.creator === auth.login;
    const isPizzaDayCreated = data.pizzaDay?.state === PizzaDayState.CREATED;

    // Pokud není vybraná PIZZA nebo přepínáme na PIZZA, není potřeba kontrolovat
    if (!hasPizzaChoice || newLocationKey === LunchChoice.PIZZA) {
      return true;
    }

    // Pokud uživatel není zakladatel Pizza day, není potřeba dialogu
    if (!isCreator || !data?.pizzaDay) {
      return true;
    }

    // Uživatel je zakladatel Pizza day a mění volbu z PIZZA
    if (!isPizzaDayCreated) {
      // Pizza day není ve stavu CREATED, nelze změnit volbu
      alert(`Nelze změnit volbu. Pizza day je ve stavu "${data.pizzaDay.state}" a musí být nejprve dokončen.`);
      return false;
    }

    // Pizza day je CREATED, zobrazit potvrzovací dialog
    const confirmed = window.confirm(
      'Jsi zakladatel aktivního Pizza day. Změna volby smaže celý Pizza day včetně všech objednávek. Pokračovat?'
    );

    if (!confirmed) {
      return false;
    }

    // Uživatel potvrdil, smazat Pizza day
    try {
      await deletePizzaDay();
      return true;
    } catch (error: any) {
      alert(`Chyba při mazání Pizza day: ${error.message || error}`);
      return false;
    }
  };

  const doAddClickFoodChoice = async (location: LunchChoice, foodIndex?: number) => {
    if (document.getSelection()?.type !== 'Range') { // pouze pokud se nejedná o výběr textu
      if (canChangeChoice && auth?.login) {
        // Kontrola Pizza day před změnou volby
        const canProceed = await checkPizzaDayBeforeChange(location);
        if (!canProceed) {
          return;
        }

        try {
          await addChoice({ body: { locationKey: location, foodIndex, dayIndex } });
          await tryAutoSelectDepartureTime();
        } catch (error: any) {
          alert(`Chyba při změně volby: ${error.message || error}`);
        }
      }
    }
  }

  const doAddChoice = async (event: React.ChangeEvent<HTMLSelectElement>) => {
    const locationKey = event.target.value as LunchChoice;
    if (canChangeChoice && auth?.login) {
      // Kontrola Pizza day před změnou volby
      const canProceed = await checkPizzaDayBeforeChange(locationKey);
      if (!canProceed) {
        // Uživatel zrušil akci nebo došlo k chybě, reset výběru zpět na PIZZA
        if (choiceRef.current) {
          choiceRef.current.value = LunchChoice.PIZZA;
        }
        return;
      }

      try {
        await addChoice({ body: { locationKey, dayIndex } });
        if (foodChoiceRef.current?.value) {
          foodChoiceRef.current.value = "";
        }
        choiceRef.current?.blur();
        // Automatický výběr času odchodu pouze pro restaurace s menu
        if (Object.keys(Restaurant).includes(locationKey)) {
          await tryAutoSelectDepartureTime();
        }
      } catch (error: any) {
        alert(`Chyba při změně volby: ${error.message || error}`);
        // Reset výběru zpět
        const hasPizzaChoice = data?.choices?.PIZZA?.[auth.login] != null;
        if (choiceRef.current && hasPizzaChoice) {
          choiceRef.current.value = LunchChoice.PIZZA;
        } else if (choiceRef.current) {
          choiceRef.current.value = "";
        }
      }
    }
  }

  const doJdemeObed = async () => {
    if (auth?.login) {
      await jdemeObed();
    }
  }

  const doAddFoodChoice = async (event: React.ChangeEvent<HTMLSelectElement>) => {
    if (event.target.value && foodChoiceList?.length && choiceRef.current?.value) {
      const locationKey = choiceRef.current.value as LunchChoice;
      if (auth?.login) {
        await addChoice({ body: { locationKey, foodIndex: Number(event.target.value), dayIndex } });
        await tryAutoSelectDepartureTime();
      }
    }
  }

  const doRemoveChoices = async (locationKey: LunchChoice) => {
    if (auth?.login) {
      await removeChoices({ body: { locationKey, dayIndex } });
      // Vyresetujeme výběr, aby bylo jasné pro který případně vybíráme jídlo
      if (choiceRef?.current?.value) {
        choiceRef.current.value = "";
      }
      if (foodChoiceRef?.current?.value) {
        foodChoiceRef.current.value = "";
      }
    }
  }

  const doRemoveFoodChoice = async (locationKey: LunchChoice, foodIndex: number) => {
    if (auth?.login) {
      await removeChoice({ body: { locationKey, foodIndex, dayIndex } });
      if (choiceRef?.current?.value) {
        choiceRef.current.value = "";
      }
      if (foodChoiceRef?.current?.value) {
        foodChoiceRef.current.value = "";
      }
    }
  }

  const saveNote = async (note?: string) => {
    if (auth?.login) {
      await updateNote({ body: { note, dayIndex } });
      setNoteModalOpen(false);
    }
  }

  const copyNote = async (note: string) => {
    if (auth?.login && note) {
      await updateNote({ body: { note, dayIndex } });
    }
  }

  const markAsBuyer = async () => {
    if (auth?.login) {
      await setBuyer();
    }
  }

  const handleCreatePizzaDay = async () => {
    if (!window.confirm('Opravdu chcete založit Pizza day?')) return;
    setLoadingPizzaDay(true);
    await createPizzaDay().then(() => setLoadingPizzaDay(false));
  }

  const handleDeletePizzaDay = async () => {
    if (!window.confirm('Opravdu chcete smazat Pizza day? Budou smazány i všechny dosud zadané objednávky.')) return;
    await deletePizzaDay();
  }

  const handleLockPizzaDay = async () => {
    if (!window.confirm('Opravdu chcete uzamknout objednávky? Po uzamčení nebude možné přidávat ani odebírat objednávky.')) return;
    await lockPizzaDay();
  }

  const handleUnlockPizzaDay = async () => {
    if (!window.confirm('Opravdu chcete odemknout objednávky? Uživatelé budou moci opět upravovat své objednávky.')) return;
    await unlockPizzaDay();
  }

  const handleFinishOrder = async () => {
    if (!window.confirm('Opravdu chcete označit objednávky jako objednané? Objednávky zůstanou zamčeny.')) return;
    await finishOrder();
  }

  const handleReturnToLocked = async () => {
    if (!window.confirm('Opravdu chcete vrátit stav zpět do "uzamčeno" (před objednáním)?')) return;
    await lockPizzaDay();
  }

  const handleFinishDelivery = async () => {
    if (!window.confirm(`Opravdu chcete označit pizzy jako doručené?${settings?.bankAccount && settings?.holderName ? ' Uživatelům bude vygenerován QR kód pro platbu.' : ''}`)) return;
    await finishDelivery({ body: { bankAccount: settings?.bankAccount, bankAccountHolder: settings?.holderName } });
  }

  const pizzaSuggestions = useMemo(() => {
    if (!data?.pizzaList && !data?.salatList) {
      return [];
    }
    const suggestions: SelectSearchOption[] = [];
    data.pizzaList?.forEach((pizza, index) => {
      const group: SelectSearchOption = { name: pizza.name, type: "group", items: [] }
      pizza.sizes.forEach((size, sizeIndex) => {
        const name = `${size.size} (${size.price} Kč)`;
        const value = `pizza|${index}|${sizeIndex}`;
        group.items?.push({ name, value });
      })
      suggestions.push(group);
    });
    if (data.salatList?.length) {
      const salatGroup: SelectSearchOption = { name: "Saláty", type: "group", items: [] }
      data.salatList.forEach((salat, index) => {
        salatGroup.items?.push({ name: `${salat.name} (${salat.price} Kč)`, value: `salat|${index}` });
      });
      suggestions.push(salatGroup);
    }
    return suggestions;
  }, [data?.pizzaList, data?.salatList]);

  const handlePizzaChange = async (value: SelectedOptionValue | SelectedOptionValue[]) => {
    if (auth?.login) {
      if (typeof value !== 'string') {
        throw new TypeError('Nepodporovaný typ hodnoty: ' + typeof value);
      }
      const s = value.split('|');
      if (s[0] === 'salat') {
        const salatIndex = Number.parseInt(s[1]);
        await addPizza({ body: { salatIndex } });
      } else {
        const pizzaIndex = Number.parseInt(s[1]);
        const pizzaSizeIndex = Number.parseInt(s[2]);
        await addPizza({ body: { pizzaIndex, pizzaSizeIndex } });
      }
    }
  }

  const handlePizzaDelete = async (pizzaOrder: PizzaVariant) => {
    await removePizza({ body: { pizzaOrder } });
  }

  const handlePizzaPoznamkaChange = async () => {
    if (pizzaPoznamkaRef.current?.value && pizzaPoznamkaRef.current.value.length > 70) {
      alert("Poznámka může mít maximálně 70 znaků");
      return;
    }
    updatePizzaDayNote({ body: { note: pizzaPoznamkaRef.current?.value } });
  }

  const handleChangeDepartureTime = async (event: React.ChangeEvent<HTMLSelectElement>) => {
    if (foodChoiceList?.length && choiceRef.current?.value) {
      await changeDepartureTime({ body: { time: event.target.value as DepartureTime, dayIndex } });
    }
  }

  // Automaticky nastaví preferovaný čas odchodu 10:45, pokud tento čas ještě nenastal (nebo jde o budoucí den)
  const tryAutoSelectDepartureTime = async () => {
    const preferredTime = "10:45" as DepartureTime;
    const isToday = dayIndex === data?.todayDayIndex;
    if ((!isToday || isInTheFuture(preferredTime)) && departureChoiceRef.current) {
      departureChoiceRef.current.value = preferredTime;
      await changeDepartureTime({ body: { time: preferredTime, dayIndex } });
    }
  }

  const handleDayChange = async (dayIndex: number) => {
    setDayIndex(dayIndex);
    dayIndexRef.current = dayIndex;
    if (choiceRef?.current?.value) {
      choiceRef.current.value = "";
    }
    if (foodChoiceRef?.current?.value) {
      foodChoiceRef.current.value = "";
    }
    if (departureChoiceRef?.current?.value) {
      departureChoiceRef.current.value = "";
    }
  }

  const renderFoodTable = (location: Restaurant, menu: RestaurantDayMenu) => {
    let content;
    if (menu?.closed) {
      content = <div className="restaurant-closed">Zavřeno</div>
    } else if (menu?.food?.length && menu.food.length > 0) {
      const hideSoups = settings?.hideSoups;
      content = <Table className="food-table">
        <tbody style={{ cursor: canChangeChoice ? 'pointer' : 'default' }}>
          {menu.food.map((f: Food, index: number) =>
            (!hideSoups || !f.isSoup) &&
            <tr key={f.name} onClick={() => doAddClickFoodChoice(location, index)}>
              <td>
                <div className="food-name">
                  {f.name}
                  {f.allergens && f.allergens.length > 0 && (
                    <span className="food-allergens">
                      {' '}({f.allergens.map((a, idx) => (
                        <span key={a}>
                          <span className="allergen-link" title={ALLERGENS[a]} onClick={e => {
                            e.stopPropagation();
                            window.open(LINK_ALLERGENS, '_blank');
                          }}>{a}</span>
                          {idx < f.allergens!.length - 1 && ', '}
                        </span>
                      ))})
                    </span>
                  )}
                </div>
                <div className="food-meta">
                  {f.amount && f.amount !== '-' && <span className="food-amount">{f.amount}</span>}
                  <span className="food-price">{f.price}</span>
                </div>
              </td>
            </tr>
          )}
        </tbody>
      </Table>
    } else {
      content = <div className="restaurant-error">Chyba načtení dat</div>
    }
    return <Col md={6} lg={3} className='mt-3'>
      <div className="restaurant-card">
        <div className="restaurant-header" style={{ cursor: canChangeChoice ? 'pointer' : 'default' }} onClick={() => doAddClickFoodChoice(location)}>
          <div className="restaurant-header-content">
            <h3>
              {getLunchChoiceName(location)}
            </h3>
            {menu?.lastUpdate && <small>Aktualizace: {getHumanDateTime(new Date(menu.lastUpdate))}</small>}
          </div>
          {menu?.warnings && menu.warnings.length > 0 && (
            <span className="restaurant-warning" title={menu.warnings.join('\n')}>
              <FontAwesomeIcon icon={faTriangleExclamation} />
            </span>
          )}
        </div>
        {content}
      </div>
    </Col>
  }

  if (!auth?.login) {
    return <Login />;
  }

  if (!isConnected) {
    return <Loader
      icon={faSatelliteDish}
      description={'Zdá se, že máme problémy se spojením se serverem. Pokud problém přetrvává, kontaktujte správce systému.'}
      animation={'fa-beat-fade'}
    />
  }

  if (failure) {
    return <Loader
      title="Něco se nám nepovedlo :("
      icon={faChainBroken}
      description={'Ale to nevadí. To se stává, takový je život. Kontaktujte správce systému, který zajistí nápravu.'}
    />
  }

  if (!data || !food) {
    return <Loader
      icon={faSearch}
      description={'Hledáme, co dobrého je aktuálně v nabídce'}
      animation={'fa-bounce'}
    />
  }

  const noOrders = data?.pizzaDay?.orders?.length === 0;
  const canChangeChoice = dayIndex == null || data.todayDayIndex == null || dayIndex >= data.todayDayIndex;

  const { path, url, startOffset, endOffset, duration, ...style } = easterEgg || {};

  return (
    <div className="app-container">
      {easterEgg && eggImage && <img ref={eggRef} alt='' src={URL.createObjectURL(eggImage)} style={{ position: 'absolute', ...EASTER_EGG_STYLE, ...style, animationDuration: `${duration ?? EASTER_EGG_DEFAULT_DURATION}s` }} />}
      <Header choices={data?.choices} dayIndex={dayIndex} />
      <div className='wrapper'>
        {data.todayDayIndex != null && data.todayDayIndex > 4 &&
          <Alert variant="info" className="mb-3">
            Zobrazujete uplynulý týden
          </Alert>
        }
        <>
          {dayIndex != null &&
            <div className='day-navigator'>
              <span title='Předchozí den'>
                <FontAwesomeIcon icon={faChevronLeft} style={{ cursor: "pointer", visibility: dayIndex > 0 ? "initial" : "hidden" }} onClick={() => handleDayChange(dayIndex - 1)} />
              </span>
              <h1 className={`title ${dayIndex !== data.todayDayIndex ? 'text-muted' : ''}`}>{data.date}</h1>
              <span title="Následující den">
                <FontAwesomeIcon icon={faChevronRight} style={{ cursor: "pointer", visibility: dayIndex < 4 ? "initial" : "hidden" }} onClick={() => handleDayChange(dayIndex + 1)} />
              </span>
            </div>
          }
          <Row className='food-tables'>
            {Object.keys(Restaurant).map(key => {
              const locationKey = key as Restaurant;
              return food[locationKey] && renderFoodTable(locationKey, food[locationKey]);
            })}
          </Row>
          <div className='content-wrapper'>
            <div className='content'>
              {canChangeChoice && <div className="choice-section fade-in">
                <p>{`Jak to ${dayIndex == null || dayIndex === data.todayDayIndex ? 'dnes' : 'tento den'} vidíš s obědem?`}</p>
                <Form.Select ref={choiceRef} onChange={doAddChoice}>
                  <option value="">Vyber možnost...</option>
                  {Object.entries(LunchChoice)
                    .filter(entry => {
                      const locationKey = entry[0] as Restaurant;
                      return !food[locationKey]?.closed;
                    })
                    .map(entry => <option key={entry[0]} value={entry[0]}>{getLunchChoiceName(entry[1])}</option>)}
                </Form.Select>
                <small>Je možné vybrat jen jednu možnost. Výběr jiné odstraní předchozí.</small>
                {foodChoiceList && !closed && <>
                  <p className="mt-3">Na co dobrého?</p>
                  <Form.Select ref={foodChoiceRef} onChange={doAddFoodChoice}>
                    <option value="">Vyber jídlo...</option>
                    {foodChoiceList.map((food, index) => <option key={food.name} value={index}>{food.name}</option>)}
                  </Form.Select>
                </>}
                {foodChoiceList && !closed && <>
                  <p className="mt-3">V kolik hodin preferuješ odchod?</p>
                  <Form.Select ref={departureChoiceRef} onChange={handleChangeDepartureTime}>
                    <option value="">Vyber čas...</option>
                    {Object.values(DepartureTime)
                      .filter(time => dayIndex !== data.todayDayIndex || isInTheFuture(time))
                      .map(time => <option key={time} value={time}>{time}</option>)}
                  </Form.Select>
                </>}
              </div>}
              {Object.keys(data.choices).length > 0 ?
                <Table className='choices-table mt-4 fade-in'>
                  <tbody>
                    {Object.keys(data.choices).map(key => {
                      const locationKey = key as LunchChoice;
                      const locationName = getLunchChoiceName(locationKey);
                      const loginObject = data.choices[locationKey];
                      if (!loginObject) {
                        return null;
                      }
                      const locationLoginList = Object.entries(loginObject);
                      const locationPickCount = locationLoginList.length
                      return (
                        <tr key={key}>
                          <td>
                            {locationName}
                            {(locationPickCount ?? 0) > 1 && <span className="ms-1">({locationPickCount})</span>}
                            {locationPickCount >= 2 && auth.login && loginObject[auth.login] !== undefined
                              && locationKey !== LunchChoice.PIZZA && locationKey !== LunchChoice.NEOBEDVAM && locationKey !== LunchChoice.ROZHODUJI
                              && settings?.bankAccount && settings?.holderName && (
                              <span title='Zaplatit za všechny a vygenerovat QR kódy ostatním' className="ms-2">
                                <FontAwesomeIcon
                                  icon={faMoneyBillTransfer}
                                  onClick={() => setPayForAllLocationKey(locationKey)}
                                  className='action-icon'
                                  style={{ cursor: 'pointer' }}
                                />
                              </span>
                            )}
                          </td>
                          <td className='p-0'>
                            <Table className="nested-table">
                              <tbody>
                                {locationLoginList.map((entry: [string, UserLunchChoice]) => {
                                  const login = entry[0];
                                  const userPayload = entry[1];
                                  const userChoices = userPayload?.selectedFoods;
                                  const trusted = userPayload?.trusted || false;
                                  const isBuyer = userPayload?.isBuyer || false;
                                  return <tr key={entry[0]}>
                                    <td>
                                      <div className="user-row">
                                        <div className="user-info">
                                          {trusted && <span className='trusted-icon' title='Uživatel ověřený doménovým přihlášením'>
                                            <FontAwesomeIcon icon={faCircleCheck} style={{ cursor: "help" }} />
                                          </span>}
                                          <strong>{login}</strong>
                                          {userPayload.departureTime && <small className="ms-2" style={{ color: 'var(--luncher-text-muted)' }}>({userPayload.departureTime})</small>}
                                          {userPayload.note && <span className="ms-2" style={{ fontSize: 'small', color: 'var(--luncher-text-secondary)' }}>({userPayload.note})</span>}
                                        </div>
                                        <div className="user-actions">
                                          {login === auth.login && canChangeChoice && locationKey === LunchChoice.OBJEDNAVAM && <span title='Označit/odznačit se jako objednávající'>
                                            <FontAwesomeIcon onClick={() => {
                                              markAsBuyer();
                                            }} icon={faBasketShopping} className={isBuyer ? 'buyer-icon' : 'action-icon'} style={{ cursor: 'pointer' }} />
                                          </span>}
                                          {login !== auth.login && locationKey === LunchChoice.OBJEDNAVAM && isBuyer && <span title='Objednávající'>
                                            <FontAwesomeIcon onClick={() => {
                                              copyNote(userPayload.note!);
                                            }} icon={faBasketShopping} className='buyer-icon' />
                                          </span>}
                                          {login !== auth.login && canChangeChoice && userPayload?.note?.length && <span title='Převzít poznámku'>
                                            <FontAwesomeIcon onClick={() => {
                                              copyNote(userPayload.note!);
                                            }} className='action-icon' icon={faComment} />
                                          </span>}
                                          {login === auth.login && canChangeChoice && <span title='Upravit poznámku'>
                                            <FontAwesomeIcon onClick={() => {
                                              setNoteModalOpen(true);
                                            }} className='action-icon' icon={faNoteSticky} />
                                          </span>}
                                          {login === auth.login && canChangeChoice && <span title={`Odstranit volbu ${locationName}, včetně případných zvolených jídel`}>
                                            <FontAwesomeIcon onClick={() => {
                                              doRemoveChoices(key as LunchChoice);
                                            }} className='action-icon' icon={faTrashCan} />
                                          </span>}
                                        </div>
                                      </div>
                                      {userChoices && userChoices.length > 0 && food && (
                                        <div className="food-choices">
                                          {userChoices.map(foodIndex => {
                                            const restaurantKey = key as Restaurant;
                                            const foodName = food[restaurantKey]?.food?.[foodIndex].name;
                                            return <div key={foodIndex} className="food-choice-item">
                                              <span className="food-choice-name">{foodName}</span>
                                              {login === auth.login && canChangeChoice &&
                                                <span title={`Odstranit ${foodName}`}>
                                                  <FontAwesomeIcon onClick={() => {
                                                    doRemoveFoodChoice(restaurantKey, foodIndex);
                                                  }} className='action-icon' icon={faTrashCan} />
                                                </span>}
                                            </div>
                                          })}
                                        </div>
                                      )}
                                    </td>
                                  </tr>
                                }
                                )}
                              </tbody>
                            </Table>
                          </td>
                        </tr>)
                    }
                    )}
                  </tbody>
                </Table>
                : <div className='no-votes mt-4'>Zatím nikdo nehlasoval...</div>
              }
            </div>
            {dayIndex === data.todayDayIndex && userHasPizzaChoice &&
              <div className='pizza-section fade-in'>
                {!data.pizzaDay &&
                  <>
                    <h3>Pizza Day</h3>
                    <p>Pro dnešní den není aktuálně založen Pizza day.</p>
                    {loadingPizzaDay ?
                      <span style={{ color: 'var(--luncher-primary)' }}>
                        <FontAwesomeIcon icon={faGear} className='fa-spin me-2' /> Zjišťujeme dostupné pizzy
                      </span>
                      :
                      <div>
                        <Button onClick={handleCreatePizzaDay}>Založit Pizza day</Button>
                        <Button variant="outline-primary" onClick={doJdemeObed}>Jdeme na oběd!</Button>
                      </div>
                    }
                  </>
                }
                {data.pizzaDay &&
                  <>
                    <h3>Pizza Day</h3>
                    {
                      data.pizzaDay.state === PizzaDayState.CREATED &&
                      <>
                        <p>
                          Pizza Day je založen a spravován uživatelem <strong>{data.pizzaDay.creator}</strong>.<br />
                          Můžete upravovat své objednávky.
                        </p>
                        {
                          data.pizzaDay.creator === auth.login &&
                          <div className="mb-4">
                            <Button variant="danger" title="Smaže kompletně pizza day, včetně dosud zadaných objednávek." onClick={handleDeletePizzaDay}>Smazat Pizza day</Button>
                            <Button title={noOrders ? "Nelze uzamknout - neexistuje žádná objednávka" : "Zamezí přidávat/odebírat objednávky. Použij před samotným objednáním, aby již nemohlo docházet ke změnám."} disabled={noOrders} onClick={handleLockPizzaDay}>Uzamknout</Button>
                          </div>
                        }
                      </>
                    }
                    {
                      data.pizzaDay.state === PizzaDayState.LOCKED &&
                      <>
                        <p>Objednávky jsou uzamčeny uživatelem <strong>{data.pizzaDay.creator}</strong></p>
                        {data.pizzaDay.creator === auth.login &&
                          <div className="mb-4">
                            <Button variant="secondary" title="Umožní znovu editovat objednávky." onClick={handleUnlockPizzaDay}>Odemknout</Button>
                            <Button title={noOrders ? "Nelze objednat - neexistuje žádná objednávka" : "Použij po objednání. Objednávky zůstanou zamčeny."} disabled={noOrders} onClick={handleFinishOrder}>Objednáno</Button>
                          </div>
                        }
                      </>
                    }
                    {
                      data.pizzaDay.state === PizzaDayState.ORDERED &&
                      <>
                        <p>Pizzy byly objednány uživatelem <strong>{data.pizzaDay.creator}</strong></p>
                        {data.pizzaDay.creator === auth.login &&
                          <div className="mb-4">
                            <Button variant="secondary" title="Vrátí stav do předchozího kroku (před objednáním)." onClick={handleReturnToLocked}>Vrátit do "uzamčeno"</Button>
                            <Button title="Nastaví stav na 'Doručeno' - koncový stav." onClick={handleFinishDelivery}>Doručeno</Button>
                          </div>
                        }
                      </>
                    }
                    {
                      data.pizzaDay.state === PizzaDayState.DELIVERED &&
                      <p>
                        Pizzy byly doručeny.
                        {myOrder?.hasQr ? ` Objednávku můžete uživateli ${data.pizzaDay.creator} uhradit pomocí QR kódu níže.` : ''}
                      </p>
                    }
                    {data.pizzaDay.state === PizzaDayState.CREATED &&
                      <div className="pizza-order-form">
                        <SelectSearch
                          search={true}
                          options={pizzaSuggestions}
                          placeholder='Vyhledat pizzu nebo salát...'
                          onChange={handlePizzaChange}
                          onBlur={_ => { }}
                          onFocus={_ => { }}
                        />
                        <div className="d-flex align-items-center gap-2">
                          <label style={{ color: 'var(--luncher-text-secondary)' }}>Poznámka:</label>
                          <input ref={pizzaPoznamkaRef} type="text" placeholder="Např. bez cibule" onKeyDown={event => {
                            if (event.key === 'Enter') {
                              handlePizzaPoznamkaChange();
                            }
                            event.stopPropagation();
                          }} />
                          <Button
                            disabled={!myOrder?.pizzaList?.length}
                            onClick={handlePizzaPoznamkaChange}>
                            Uložit
                          </Button>
                        </div>
                      </div>
                    }
                    <PizzaOrderList state={data.pizzaDay.state!} orders={data.pizzaDay.orders!} onDelete={handlePizzaDelete} creator={data.pizzaDay.creator!} />
                    {
                      data.pizzaDay.state === PizzaDayState.DELIVERED && myOrder?.hasQr && (() => {
                        const pizzaQr = data.pendingQrs?.find(qr => qr.creator === data.pizzaDay?.creator);
                        return pizzaQr ? (
                          <div className='qr-code'>
                            <h3>QR platba</h3>
                            <img src={`/api/qr?login=${auth.login}&id=${pizzaQr.id}`} alt='QR kód' />
                          </div>
                        ) : null;
                      })()
                    }
                  </>
                }
              </div>
            }
          </div>
          {data.pendingQrs && data.pendingQrs.length > 0 &&
            <div className='pizza-section fade-in mt-4'>
              <h3>Nevyřízené platby</h3>
              <p>Máte neuhrazené platby.</p>
              {data.pendingQrs.map(qr => (
                <div key={qr.id} className='qr-code mb-3'>
                  <p>
                    <strong>{formatDateString(qr.date)}</strong> — {qr.creator} ({qr.totalPrice} Kč)
                    {qr.purpose && <><br /><span className="text-muted">{qr.purpose}</span></>}
                  </p>
                  <img src={`/api/qr?login=${auth.login}&id=${qr.id}`} alt='QR kód' />
                  <div className='mt-2'>
                    <Button variant="success" onClick={async () => {
                      await dismissQr({ body: { id: qr.id } });
                      const response = await getData({ query: { dayIndex } });
                      if (response.data) {
                        setData(response.data);
                      }
                    }}>
                      Zaplatil jsem
                    </Button>
                  </div>
                </div>
              ))}
            </div>
          }
        </>
      </div>
      {/* <FallingLeaves
        numLeaves={LEAF_PRESETS.NORMAL}
        leafVariants={LEAF_COLOR_THEMES.AUTUMN}
      /> */}
      <Footer />
      <NoteModal isOpen={noteModalOpen} onClose={() => setNoteModalOpen(false)} onSave={saveNote} />
      {payForAllLocationKey && data && (
        <PayForAllModal
          isOpen
          onClose={() => setPayForAllLocationKey(null)}
          locationKey={payForAllLocationKey}
          locationName={getLunchChoiceName(payForAllLocationKey)}
          locationChoices={data.choices[payForAllLocationKey as keyof typeof data.choices] as LocationLunchChoicesMap}
          menu={food?.[payForAllLocationKey as Restaurant]}
          payerLogin={auth.login ?? ''}
          bankAccount={settings?.bankAccount ?? ''}
          bankAccountHolder={settings?.holderName ?? ''}
        />
      )}
    </div>
  );
}

export default App;
