import React, { useContext, useEffect, useMemo, useRef, useState } from 'react';
import 'bootstrap/dist/css/bootstrap.min.css';
import { EVENT_DISCONNECT, EVENT_MESSAGE, SocketContext } from './context/socket';
import { addPizza, createPizzaDay, deletePizzaDay, finishDelivery, finishOrder, getData, getFood, getPizzy, getQrUrl, lockPizzaDay, removePizza, unlockPizzaDay, updateChoice, updateNote } from './Api';
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 } from 'react-select-search';
import 'react-select-search/style.css';
import './App.css';
import { SelectSearchOption } from 'react-select-search';
import { faTrashCan } from '@fortawesome/free-regular-svg-icons';
import { useBank } from './context/bank';
import { ClientData, Restaurants, Food, Pizza, Order, Locations, PizzaOrder, PizzaDayState } from './types';


const EVENT_CONNECT = "connect"

function App() {
  const auth = useAuth();
  const bank = useBank();
  const [isConnected, setIsConnected] = useState<boolean>(false);
  const [data, setData] = useState<ClientData>();
  const [food, setFood] = useState<{ [key in Restaurants]: Food[] }>();
  const [pizzy, setPizzy] = useState<Pizza[]>();
  const [myOrder, setMyOrder] = useState<Order>();
  const socket = useContext(SocketContext);
  const choiceRef = useRef<HTMLSelectElement>(null);
  const poznamkaRef = useRef<HTMLInputElement>(null);

  // Načtení dat po přihlášení
  useEffect(() => {
    if (!auth || !auth.login) {
      return
    }
    getPizzy().then(pizzy => {
      setPizzy(pizzy);
    });
    getData().then(data => {
      setData(data);
    })
    getFood().then(food => {
      setFood(food);
    })
  }, [auth, auth?.login]);

  // Registrace socket eventů
  useEffect(() => {
    socket.on(EVENT_CONNECT, () => {
      // console.log("Connected!");
      setIsConnected(true);
    });
    socket.on(EVENT_DISCONNECT, () => {
      // console.log("Disconnected!");
      setIsConnected(false);
    });
    socket.on(EVENT_MESSAGE, (newData: ClientData) => {
      // console.log("Přijata nová data ze socketu", newData);
      setData(newData);
    });

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

  useEffect(() => {
    if (!auth || !auth.login) {
      return
    }
    // TODO tohle občas náhodně nezafunguje, nutno přepsat, viz https://medium.com/@teh_builder/ref-objects-inside-useeffect-hooks-eb7c15198780
    if (data?.choices && choiceRef.current) {
      for (let entry of Object.entries(data.choices)) {
        if (entry[1].includes(auth.login)) {
          const value = entry[0] as any as number; // TODO tohle je absurdní
          choiceRef.current.value = Object.values(Locations)[value];
        }
      }
    }
  }, [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])

  const changeChoice = async (event: React.ChangeEvent<HTMLSelectElement>) => {
    const index = Object.values(Locations).indexOf(event.target.value as unknown as Locations);
    if (auth?.login) {
      await updateChoice(index > -1 ? index : null);
    }
  }

  const removeChoice = async (key: string) => {
    if (auth?.login) {
      await updateChoice(null);
      if (choiceRef?.current?.value) {
        choiceRef.current.value = "";
      }
    }
  }

  const pizzaSuggestions = useMemo(() => {
    if (!pizzy) {
      return [];
    }
    const suggestions: SelectSearchOption[] = [];
    pizzy.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 = `${index}|${sizeIndex}`;
        group.items?.push({ name, value });
      })
      suggestions.push(group);
    })
    return suggestions;
  }, [pizzy]);

  const handlePizzaChange = async (value: SelectedOptionValue | SelectedOptionValue[]) => {
    if (auth?.login && pizzy) {
      if (!(typeof value === 'string')) {
        throw Error('Nepodporovaný typ hodnoty');
      }
      const s = value.split('|');
      const pizzaIndex = Number.parseInt(s[0]);
      const pizzaSizeIndex = Number.parseInt(s[1]);
      await addPizza(pizzaIndex, pizzaSizeIndex);
    }
  }

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

  const handlePoznamkaChange = async () => {
    if (poznamkaRef.current?.value && poznamkaRef.current.value.length > 100) {
      alert("Poznámka může mít maximálně 100 znaků");
      return;
    }
    updateNote(poznamkaRef.current?.value);
  }

  // const addToCart = async () => {
  // TODO aktuálně nefunkční - nedokážeme poslat PHPSESSIONID cookie
  // if (data?.pizzaDay?.orders) {
  //   for (const order of data?.pizzaDay?.orders) {
  //     for (const pizzaOrder of order.pizzaList) {
  //       const url = 'https://www.pizzachefie.cz/pridat.html';
  //       const payload = new URLSearchParams();
  //       payload.append('varId', pizzaOrder.varId.toString());
  //       await fetch(url, {
  //         method: "POST",
  //         mode: "no-cors",
  //         cache: "no-cache",
  //         credentials: "same-origin",
  //         headers: {
  //           'Content-Type': 'application/x-www-form-urlencoded',
  //         },
  //         body: payload,
  //       })
  //     }
  //   }
  //   // TODO otevřít košík v nové záložce
  // }
  // }

  const renderFoodTable = (name: string, food: Food[]) => {
    return <Col md={12} lg={4}>
      <h3>{name}</h3>
      <Table striped bordered hover>
        <tbody>
          {food?.length > 0 ? food.map((f: any, index: number) =>
            <tr key={index}>
              <td>{f.amount}</td>
              <td>{f.name}</td>
              <td>{f.price}</td>
            </tr>
          ) : <h1>Hmmmmm podivné.... nic se nevrátilo</h1>}
        </tbody>
      </Table>
    </Col>
  }

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

  if (!data || !isConnected || !food) {
    return <div>Načítám data...</div>
  }

  const noOrders = data?.pizzaDay?.orders?.length === 0;

  return (
    <>
      <Header />
      <div className='wrapper'>
        {data.isWeekend ? <h4>Užívejte víkend :)</h4> : <>
          <Alert variant={'primary'}>
            Poslední změny:
            <ul>
              <li>Oprava parsování při neočekávané velikosti písmen v ceně</li>
              <li>Přidání nedělitelných mezer k cenám</li>
            </ul>
          </Alert>
          <h1 className='title'>Dnes je {data.date}</h1>
          <Row className='food-tables'>
            {renderFoodTable('Sladovnická', food[Restaurants.SLADOVNICKA])}
            {renderFoodTable('U Motlíků', food[Restaurants.UMOTLIKU])}
            {renderFoodTable('TechTower', food[Restaurants.TECHTOWER])}
          </Row>
          <div className='content-wrapper'>
            <div className='content'>
              <p>Jak to dnes vidíš s obědem?</p>
              <Form.Select ref={choiceRef} onChange={changeChoice}>
                <option></option>
                <option value={Locations.SLADOVNICKA}>Sladovnická</option>
                <option value={Locations.UMOTLIKU}>U Motlíků</option>
                <option value={Locations.TECHTOWER}>TechTower</option>
                <option value={Locations.SPSE}>SPŠE</option>
                <option value={Locations.PIZZA}>Pizza day</option>
                <option value={Locations.OBJEDNAVAM}>Budu objednávat (mimo pizzu)</option>
                <option value={Locations.NEOBEDVAM}>Mám vlastní/neobědvám</option>
              </Form.Select>
              <p style={{ fontSize: "12px", marginTop: "5px" }}>
                Aktuálně je možné vybrat pouze jednu variantu.
              </p>
              {Object.keys(data.choices).length > 0 ?
                <Table striped bordered hover className='results-table mt-5'>
                  <tbody>
                    {Object.keys(data.choices).map((key: string, index: number) =>
                      <tr key={index}>
                        <td>{Object.values(Locations)[Number(key)]}</td>
                        <td>
                          <ul>
                            {data.choices[Number(key)].map((p: string, index: number) =>
                              <li key={index}>{p} {p === auth.login && <FontAwesomeIcon onClick={() => {
                                removeChoice(key);
                              }} title='Odstranit' className='trash-icon' icon={faTrashCan} />}</li>
                            )}
                          </ul>
                        </td>
                      </tr>
                    )}
                  </tbody>
                </Table>
                : <div className='mt-5'><i>Zatím nikdo nehlasoval...</i></div>
              }
            </div>
            <div className='mt-5'>
              {!data.pizzaDay &&
                <div style={{ textAlign: 'center' }}>
                  <p>Pro dnešní den není aktuálně založen Pizza day.</p>
                  <Button onClick={async () => {
                    await createPizzaDay();
                  }}>Založit Pizza day</Button>
                </div>
              }
              {data.pizzaDay &&
                <div>
                  <div style={{ textAlign: 'center' }}>
                    <h3>Pizza day</h3>
                    {
                      data.pizzaDay.state === PizzaDayState.CREATED &&
                      <div>
                        <p>
                          Pizza Day je založen a spravován uživatelem {data.pizzaDay.creator}.<br />
                          Můžete upravovat své objednávky.
                        </p>
                        {
                          data.pizzaDay.creator === auth.login &&
                          <>
                            <Button className='danger mb-3' title="Smaže kompletně pizza day, včetně dosud zadaných objednávek." onClick={async () => {
                              await deletePizzaDay();
                            }}>Smazat Pizza day</Button>
                            <Button className='mb-3' style={{ marginLeft: '20px' }} 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={async () => {
                              await lockPizzaDay();
                            }}>Uzamknout</Button>
                          </>
                        }
                      </div>
                    }
                    {
                      data.pizzaDay.state === PizzaDayState.LOCKED &&
                      <div>
                        <p>Objednávky jsou uzamčeny uživatelem {data.pizzaDay.creator}</p>
                        {data.pizzaDay.creator === auth.login &&
                          <>
                            <Button className='danger mb-3' title="Umožní znovu editovat objednávky." onClick={async () => {
                              await unlockPizzaDay();
                            }}>Odemknout</Button>
                            {/* <Button className='danger mb-3' style={{ marginLeft: '20px' }} onClick={async () => {
                          await addToCart();
                        }}>Přidat vše do košíku</Button> */}
                            <Button className='danger mb-3' style={{ marginLeft: '20px' }} title={noOrders ? "Nelze objednat - neexistuje žádná objednávka" : "Použij po objednání. Objednávky zůstanou zamčeny."} disabled={noOrders} onClick={async () => {
                              await finishOrder();
                            }}>Objednáno</Button>
                          </>
                        }
                      </div>
                    }
                    {
                      data.pizzaDay.state === PizzaDayState.ORDERED &&
                      <div>
                        <p>Pizzy byly objednány uživatelem {data.pizzaDay.creator}</p>
                        {data.pizzaDay.creator === auth.login &&
                          <div>
                            <Button className='danger mb-3' title="Vrátí stav do předchozího kroku (před objednáním)." onClick={async () => {
                              await lockPizzaDay();
                            }}>Vrátit do "uzamčeno"</Button>
                            <Button className='danger mb-3' style={{ marginLeft: '20px' }} title="Nastaví stav na 'Doručeno' - koncový stav." onClick={async () => {
                              await finishDelivery(bank?.bankAccount, bank?.holderName);
                            }}>Doručeno</Button>
                          </div>
                        }
                      </div>
                    }
                    {
                      data.pizzaDay.state === PizzaDayState.DELIVERED &&
                      <div>
                        <p>Pizzy byly doručeny. Objednávku můžete uhradit pomocí QR kódu níže.</p>
                      </div>
                    }
                  </div>
                  {data.pizzaDay.state === PizzaDayState.CREATED &&
                    <div style={{ textAlign: 'center' }}>
                      <SelectSearch
                        search={true}
                        options={pizzaSuggestions}
                        placeholder='Vyhledat pizzu...'
                        onChange={handlePizzaChange}
                      />
                      Poznámka: <input ref={poznamkaRef} className='mt-3' type="text" onKeyDown={event => {
                        if (event.key === 'Enter') {
                          handlePoznamkaChange();
                        }
                      }} />
                      <Button
                        style={{ marginLeft: '20px' }}
                        disabled={!myOrder?.pizzaList?.length}
                        onClick={handlePoznamkaChange}>
                        Uložit
                      </Button>
                    </div>
                  }
                  <PizzaOrderList state={data.pizzaDay.state} orders={data.pizzaDay.orders} onDelete={handlePizzaDelete} />
                  {
                    data.pizzaDay.state === PizzaDayState.DELIVERED && myOrder?.hasQr &&
                    <div className='qr-code'>
                      <h3>QR platba</h3>
                      <div>Částka: {myOrder.totalPrice} Kč</div>
                      <img src={getQrUrl(auth.login)} alt='QR kód' />
                      <p>Generování QR kódů je v experimentální fázi - doporučujeme si překontrolovat údaje před odesláním platby.</p>
                    </div>
                  }
                </div>
              }
            </div>
          </div>
        </>}
      </div>
    </>
  );
}

export default App;
