import { useState, useEffect, useMemo } from "react";
import {
  Game,
  Source,
  GameList as GameListProto,
  Person as PersonProto,
  Opinion,
  AddOpinionRequest,
  RemoveOpinionRequest,
} from "../items";
import { Link, useLocation } from "react-router-dom";
import { apiFetch, get_auth_status } from "./api";
import { GameImage } from "./GameImage";
import type { ToastType } from "./Toast";
import { EmptyState } from "./components/EmptyState";

interface Props {
  onShowToast?: (message: string, type?: ToastType) => void;
}

export function GameList({ onShowToast }: Props) {
  const [games, setGames] = useState<Game[]>([]);
  const [title, setTitle] = useState("");
  const [source, setSource] = useState<Source>(Source.STEAM);
  const [minPlayers, setMinPlayers] = useState(1);
  const [maxPlayers, setMaxPlayers] = useState(1);
  const [price, setPrice] = useState(0);
  const [remoteId, setRemoteId] = useState(0);
  const [isSubmitting, setIsSubmitting] = useState(false);
  const [remoteIdError, setRemoteIdError] = useState("");
  const [opinions, setOpinions] = useState<Opinion[]>([]);
  const [gamesLoading, setGamesLoading] = useState(true);
  const [searchQuery, setSearchQuery] = useState("");

  const filteredGames = useMemo(() => {
    if (!searchQuery) return games;
    return games.filter(game =>
      game.title.toLowerCase().includes(searchQuery.toLowerCase())
    );
  }, [games, searchQuery]);

  const fetchGames = () => {
    setGamesLoading(true);
    apiFetch("/api/games")
      .then((res) => res.arrayBuffer())
      .then((buffer) => {
        try {
          const list = GameListProto.decode(new Uint8Array(buffer));
          setGames(list.games);
        } catch (e) {
          console.error("Failed to decode games:", e);
          onShowToast?.("Failed to load games", "error");
        }
      })
      .catch((err) => {
        console.error(err);
        onShowToast?.("Failed to fetch games", "error");
      })
      .finally(() => setGamesLoading(false));
  };

  useEffect(() => {
    get_auth_status().then((user) => {
      apiFetch(`/api/${user?.username}`)
        .then((res) => res.arrayBuffer())
        .then((buffer) => {
          try {
            const person = PersonProto.decode(new Uint8Array(buffer));
            const opinions = person.opinion;
            setOpinions(opinions);
          } catch (e) {
            console.error("Failed to decode games:", e);
          }
        });
    });
  }, []);

  // Scroll to Existing Games section if hash is present
  const location = useLocation();
  useEffect(() => {
    if (location.hash === "#existing-games") {
      const el = document.getElementById("existing-games");
      if (el) {
        setTimeout(() => {
          el.scrollIntoView({ behavior: "smooth", block: "start" });
        }, 100);
      } else {
        console.error("Element not found");
      }
    }
  }, [location]);

  useEffect(() => {
    fetchGames();
  }, []);

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();

    if (remoteId === 0) {
      setRemoteIdError("Remote ID must be greater than 0");
      return;
    }

    setRemoteIdError("");
    setIsSubmitting(true);
    const game = {
      title,
      source,
      minPlayers,
      maxPlayers,
      price,
      remoteId,
    };

    try {
      const encoded = Game.encode(game).finish();
      const res = await apiFetch("/api/game", {
        method: "POST",
        headers: {
          "Content-Type": "application/octet-stream",
        },
        body: encoded,
      });

      if (res.ok) {
        onShowToast?.("Game added successfully!", "success");
        setTitle("");
        setMinPlayers(1);
        setMaxPlayers(1);
        setPrice(0);
        setRemoteId(0);
        fetchGames();
      } else {
        onShowToast?.("Failed to add game. Please try again.", "error");
      }
    } catch (err) {
      console.error(err);
      onShowToast?.("An error occurred while adding the game.", "error");
    } finally {
      setIsSubmitting(false);
    }
  };

  const formCardStyles: React.CSSProperties = {
    background:
      "linear-gradient(135deg, var(--secondary-bg) 0%, var(--secondary-alt-bg) 100%)",
    borderRadius: "20px",
    padding: "0",
    maxWidth: "520px",
    boxShadow: "0 20px 40px rgba(0, 0, 0, 0.3), 0 0 0 1px var(--border-color)",
    overflow: "hidden",
  };

  const formHeaderStyles: React.CSSProperties = {
    background:
      "linear-gradient(135deg, var(--accent-color) 0%, var(--secondary-accent) 100%)",
    padding: "1.5rem 2rem",
    display: "flex",
    alignItems: "center",
    gap: "1rem",
  };

  const formBodyStyles: React.CSSProperties = {
    padding: "2rem",
  };

  const sectionStyles: React.CSSProperties = {
    marginBottom: "1.5rem",
  };

  const sectionTitleStyles: React.CSSProperties = {
    fontSize: "0.75rem",
    textTransform: "uppercase",
    letterSpacing: "0.1em",
    color: "var(--text-muted)",
    marginBottom: "1rem",
    display: "flex",
    alignItems: "center",
    gap: "0.5rem",
  };

  const inputGroupStyles: React.CSSProperties = {
    position: "relative",
    marginBottom: "1rem",
  };

  const labelStyles: React.CSSProperties = {
    fontSize: "0.85rem",
    color: "var(--text-muted)",
    marginBottom: "0.5rem",
    display: "block",
    fontWeight: 500,
  };

  const inputStyles: React.CSSProperties = {
    width: "100%",
    padding: "0.875rem 1rem",
    backgroundColor: "var(--tertiary-bg)",
    border: "2px solid var(--border-color)",
    borderRadius: "12px",
    color: "var(--text-color)",
    fontSize: "1rem",
    transition: "all 0.2s ease",
    boxSizing: "border-box",
  };

  const gridStyles: React.CSSProperties = {
    display: "grid",
    gridTemplateColumns: "1fr 1fr",
    gap: "1rem",
  };

  const dividerStyles: React.CSSProperties = {
    height: "1px",
    background:
      "linear-gradient(90deg, transparent, var(--border-color), transparent)",
    margin: "1.5rem 0",
  };

  const submitButtonStyles: React.CSSProperties = {
    width: "100%",
    padding: "1rem",
    background:
      "linear-gradient(135deg, var(--accent-color) 0%, var(--secondary-accent) 100%)",
    border: "none",
    borderRadius: "12px",
    color: "white",
    fontSize: "1rem",
    fontWeight: 600,
    cursor: isSubmitting ? "not-allowed" : "pointer",
    transition: "all 0.3s ease",
    display: "flex",
    alignItems: "center",
    justifyContent: "center",
    gap: "0.5rem",
    opacity: isSubmitting ? 0.7 : 1,
    transform: isSubmitting ? "none" : undefined,
  };

  return (
    <div>
      <style>
        {`
          @keyframes slideIn {
            from {
              opacity: 0;
              transform: translateY(-10px);
            }
            to {
              opacity: 1;
              transform: translateY(0);
            }
          }
          .add-game-input:focus {
            border-color: var(--accent-color) !important;
            box-shadow: 0 0 0 4px rgba(9, 109, 192, 0.15) !important;
            outline: none;
          }
          .add-game-input:hover:not(:focus) {
            border-color: var(--text-muted);
          }
          .submit-btn:hover:not(:disabled) {
            transform: translateY(-2px);
            box-shadow: 0 8px 20px rgba(9, 109, 192, 0.4);
          }
          .submit-btn:active:not(:disabled) {
            transform: translateY(0);
          }
        `}
      </style>

      <div style={formCardStyles}>
        <div style={formHeaderStyles}>
          <div
            style={{
              width: "48px",
              height: "48px",
              borderRadius: "14px",
              backgroundColor: "rgba(255, 255, 255, 0.2)",
              display: "flex",
              alignItems: "center",
              justifyContent: "center",
              fontSize: "1.5rem",
            }}
          >
            🎮
          </div>
          <div>
            <h2
              style={{
                margin: 0,
                fontSize: "1.5rem",
                fontWeight: 700,
                color: "white",
              }}
            >
              Add New Game
            </h2>
            <p
              style={{
                margin: 0,
                fontSize: "0.9rem",
                color: "rgba(255, 255, 255, 0.8)",
              }}
            >
              Add a game to your collection
            </p>
          </div>
        </div>

        <div style={formBodyStyles}>
          <form onSubmit={handleSubmit}>
            {/* Basic Info Section */}
            <div style={sectionStyles}>
              <div style={sectionTitleStyles}>
                <span>📝</span>
                Basic Information
              </div>

              <div style={inputGroupStyles}>
                <label style={labelStyles}>Game Title</label>
                <input
                  type="text"
                  value={title}
                  onChange={(e) => setTitle(e.target.value)}
                  required
                  placeholder="Enter game title..."
                  style={inputStyles}
                  className="add-game-input"
                />
              </div>

              <div style={inputGroupStyles}>
                <label style={labelStyles}>Platform Source</label>
                <select
                  value={source}
                  onChange={(e) => setSource(Number(e.target.value))}
                  style={{
                    ...inputStyles,
                    cursor: "pointer",
                    appearance: "none",
                    backgroundImage: `url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='%23a0a0a0' viewBox='0 0 16 16'%3E%3Cpath d='M8 11L3 6h10l-5 5z'/%3E%3C/svg%3E")`,
                    backgroundRepeat: "no-repeat",
                    backgroundPosition: "right 1rem center",
                    paddingRight: "2.5rem",
                  }}
                  className="add-game-input"
                >
                  <option value={Source.STEAM}>🎮 Steam</option>
                  <option value={Source.ROBLOX}>🟢 Roblox</option>
                </select>
              </div>
            </div>

            <div style={dividerStyles}></div>

            {/* Player Count Section */}
            <div style={sectionStyles}>
              <div style={sectionTitleStyles}>
                <span>👥</span>
                Player Count
              </div>

              <div style={gridStyles}>
                <div style={inputGroupStyles}>
                  <label style={labelStyles}>Minimum Players</label>
                  <input
                    type="number"
                    value={minPlayers}
                    onChange={(e) => setMinPlayers(Number(e.target.value))}
                    min="1"
                    style={inputStyles}
                    className="add-game-input"
                  />
                </div>
                <div style={inputGroupStyles}>
                  <label style={labelStyles}>Maximum Players</label>
                  <input
                    type="number"
                    value={maxPlayers}
                    onChange={(e) => setMaxPlayers(Number(e.target.value))}
                    min="1"
                    style={inputStyles}
                    className="add-game-input"
                  />
                </div>
              </div>
            </div>

            <div style={dividerStyles}></div>

            {/* Additional Info Section */}
            <div style={sectionStyles}>
              <div style={sectionTitleStyles}>
                <span>💰</span>
                Additional Details
              </div>

              <div style={gridStyles}>
                <div style={inputGroupStyles}>
                  <label style={labelStyles}>Price (€)</label>
                  <input
                    type="number"
                    value={price}
                    onChange={(e) => setPrice(Number(e.target.value))}
                    min="0"
                    step="0.01"
                    style={inputStyles}
                    className="add-game-input"
                  />
                </div>
                <div style={inputGroupStyles}>
                  <label style={labelStyles}>Remote ID</label>
                  <input
                    type="number"
                    value={remoteId}
                    onChange={(e) => {
                      setRemoteId(Number(e.target.value));
                      setRemoteIdError("");
                    }}
                    min="0"
                    style={{
                      ...inputStyles,
                      borderColor: remoteIdError ? "#f44336" : undefined,
                    }}
                    className="add-game-input"
                  />
                  {remoteIdError && (
                    <div
                      style={{
                        color: "#f44336",
                        fontSize: "0.75rem",
                        marginTop: "0.25rem",
                      }}
                    >
                      {remoteIdError}
                    </div>
                  )}
                </div>
              </div>
            </div>

            <button
              type="submit"
              disabled={isSubmitting}
              style={submitButtonStyles}
              className="submit-btn"
            >
              {isSubmitting ? (
                <>
                  <span
                    style={{
                      width: "18px",
                      height: "18px",
                      border: "2px solid rgba(255,255,255,0.3)",
                      borderTopColor: "white",
                      borderRadius: "50%",
                      animation: "spin 0.8s linear infinite",
                    }}
                  ></span>
                  Adding Game...
                </>
              ) : (
                <>
                  <span style={{ fontSize: "1.1rem" }}>➕</span>
                  Add Game to Collection
                </>
              )}
            </button>
          </form>
        </div>
      </div>

      <style>
        {`
          @keyframes spin {
            to { transform: rotate(360deg); }
          }
        `}
      </style>

      <div style={{ marginTop: "3rem" }}>
        <div
          style={{
            display: "flex",
            justifyContent: "space-between",
            alignItems: "center",
            marginBottom: "1rem",
            flexWrap: "wrap",
            gap: "1rem"
          }}
        >
          <h3
            id="existing-games"
            style={{
              scrollMarginBottom: "0",
              margin: 0
            }}
          >
            Existing Games {filteredGames.length > 0 && <span style={{ fontSize: "0.7em", color: "var(--text-muted)" }}>({filteredGames.length})</span>}
          </h3>
          <input
            type="text"
            placeholder="🔍 Search games..."
            value={searchQuery}
            onChange={(e) => setSearchQuery(e.target.value)}
            style={{
              padding: "0.5rem 1rem",
              fontSize: "0.9rem",
              minWidth: "200px"
            }}
          />
        </div>
        {gamesLoading ? (
          <div className="grid-container">
            {Array.from({ length: 6 }).map((_, i) => (
              <div
                key={i}
                style={{
                  backgroundColor: "var(--secondary-alt-bg)",
                  border: "1px solid var(--border-color)",
                  borderRadius: "5px",
                  padding: "1rem",
                  minHeight: "100px",
                  animation: "shimmer 1.5s infinite"
                }}
              >
                <div
                  style={{
                    width: "70%",
                    height: "20px",
                    backgroundColor: "var(--tertiary-bg)",
                    borderRadius: "4px",
                    marginBottom: "0.75rem",
                    animation: "shimmer 1.5s infinite"
                  }}
                ></div>
                <div
                  style={{
                    width: "40%",
                    height: "40px",
                    backgroundColor: "var(--tertiary-bg)",
                    borderRadius: "8px",
                    marginTop: "0.5rem",
                    animation: "shimmer 1.5s infinite 0.2s"
                  }}
                ></div>
              </div>
            ))}
            <style>{`
              @keyframes shimmer {
                0%, 100% { opacity: 0.5; }
                50% { opacity: 1; }
              }
            `}</style>
          </div>
        ) : filteredGames.length === 0 ? (
          <EmptyState
            icon="🎮"
            title={searchQuery ? "No games found" : "No games yet"}
            description={searchQuery ? "Try a different search term" : "Add your first game to get started"}
          />
        ) : (
          <ul className="grid-container">
          {filteredGames.map((game) => {
            const opinion = opinions.find((op) => op.title === game.title);
            function handleOpinion(title: string, number: number): void {
              if (number == 2) {
                apiFetch("/api/opinion", {
                  method: "PATCH",
                  headers: {
                    "Content-Type": "application/octet-stream",
                  },
                  body: RemoveOpinionRequest.encode(
                    RemoveOpinionRequest.create({
                      gameTitle: title,
                    })
                  ).finish(),
                })
                  .then((res) => res.arrayBuffer())
                  .then((resBuffer) => {
                    const response = PersonProto.decode(
                      new Uint8Array(resBuffer)
                    );

                    setOpinions(response.opinion);
                    onShowToast?.(`Updated opinion for ${title}`, "info");
                  })
                  .catch((err) => {
                    console.error(err);
                    onShowToast?.("Failed to update opinion", "error");
                  });
                return;
              }
              const wouldPlay = number == 1;
              apiFetch(`/api/opinion`, {
                method: "POST",
                headers: {
                  "Content-Type": "application/octet-stream",
                },
                body: AddOpinionRequest.encode(
                  AddOpinionRequest.create({
                    gameTitle: title,
                    wouldPlay,
                  })
                ).finish(),
              })
                .then((res) => res.arrayBuffer())
                .then((resBuffer) => {
                  const response = PersonProto.decode(
                    new Uint8Array(resBuffer)
                  );

                  setOpinions(response.opinion);
                  onShowToast?.(`Updated opinion for ${title}`, "info");
                })
                .catch((err) => {
                  console.error(err);
                  onShowToast?.("Failed to update opinion", "error");
                });
            }

            return (
              <div
                style={{
                  display: "flex",
                  flexDirection: "column",
                  height: "100%",
                }}
              >
                <Link
                  to={`/game/${encodeURIComponent(game.title)}`}
                  key={game.title}
                  className="list-item"
                  style={{
                    textDecoration: "none",
                    color: "inherit",
                    display: "flex",
                    justifyContent: "space-between",
                    alignItems: "center",
                    flex: "1",
                    borderColor: opinion
                      ? opinion.wouldPlay
                        ? "#4caf50" // would play (green)
                        : "#f44336" // would not play (red)
                      : "#ffff00", // no opinion (yellow)
                  }}
                >
                  <strong
                    style={{
                      textShadow: opinion
                        ? opinion.wouldPlay
                          ? "0 0 10px #4caf50" // would play (green)
                          : "0 0 10px #f44336" // would not play (red)
                        : "0 0 10px #ffff00", // no opinion (yellow)
                    }}
                  >
                    {game.title}
                  </strong>
                  <GameImage game={game.title} />
                </Link>
                <div
                  style={{
                    display: "flex",
                    gap: "1rem",
                    marginTop: "1rem",
                    width: "100%",
                  }}
                >
                  <button
                    onClick={() => handleOpinion(game.title, 1)}
                    className="theme-btn game-btn"
                    style={{
                      width: "33%",
                      borderColor: opinion?.wouldPlay
                        ? "#4caf50"
                        : "transparent",
                      background: "rgba(76, 175, 80, 0.1)",
                      fontSize: "1.2rem",
                    }}
                    title="Would Play"
                  >
                    👍
                  </button>
                  <button
                    onClick={() => handleOpinion(game.title, 2)}
                    className="theme-btn game-btn"
                    style={{
                      width: "33%",
                      borderColor: !opinion ? "#ffff00" : "transparent",
                      background: "rgba(255, 255, 0, 0.1)",
                      fontSize: "1.2rem",
                    }}
                    title="Neutral"
                  >
                    😐
                  </button>
                  <button
                    onClick={() => handleOpinion(game.title, 0)}
                    className="theme-btn game-btn"
                    style={{
                      width: "33%",
                      borderColor:
                        opinion && !opinion.wouldPlay
                          ? "#f44336"
                          : "transparent",
                      background: "rgba(244, 67, 54, 0.1)",
                      fontSize: "1.2rem",
                    }}
                    title="Would Not Play"
                  >
                    👎
                  </button>
                </div>
              </div>
            );
          })}
        </ul>
        )}
      </div>
    </div>
  );
}
