import { Link } from "@tanstack/react-router";
import { useMutation, useQueryClient } from "@tanstack/react-query";
import type { FormEvent } from "react";
import { useMemo, useState } from "react";

import { api } from "../../api";
import type { ActivityCategory, ActivityEquipment, CatalogKind, Difficulty, MeasurementType } from "../../types";
import { useAuth } from "../auth/AuthContext";
import { CatalogCard } from "./CatalogCard";
import { useCatalog } from "./hooks";
import { categoryLabels, categoryOptions, difficultyLabels, difficultyOptions, equipmentLabels, equipmentOptions, measurementLabels, measurementOptions } from "./meta";

type CatalogView = CatalogKind | "mine";

const categoryTabs: Array<ActivityCategory | "all" | "arms"> = ["all", "chest", "back", "legs", "shoulders", "arms", "core", "cardio"];

function categoryTabLabel(category: ActivityCategory | "all" | "arms") {
  if (category === "all") return "Все";
  if (category === "arms") return "Руки";
  return categoryLabels[category];
}

export function CatalogPage({ kind = "exercise" }: { kind?: CatalogView }) {
  const { auth } = useAuth();
  const token = auth.accessToken;
  const queryClient = useQueryClient();
  const { sources } = useCatalog(token);
  const [title, setTitle] = useState("");
  const [description, setDescription] = useState("");
  const [category, setCategory] = useState<ActivityCategory>("other");
  const [equipment, setEquipment] = useState<ActivityEquipment>("other");
  const [measurementType, setMeasurementType] = useState<MeasurementType>("weight_reps");
  const [difficulty, setDifficulty] = useState<Difficulty>("intermediate");
  const [file, setFile] = useState<File | null>(null);
  const [search, setSearch] = useState("");
  const [categoryFilter, setCategoryFilter] = useState<ActivityCategory | "all" | "arms">("all");

  const createKind: CatalogKind = kind === "machine" ? "machine" : "exercise";
  const list = useMemo(() => {
    const needle = search.trim().toLowerCase();
    return (sources.data ?? []).filter((entity) => {
      if (kind === "mine") {
        if (entity.owner_user_id !== auth.user.id) return false;
      } else if (entity.kind !== kind) {
        return false;
      }
      if (categoryFilter === "arms" && entity.category !== "biceps" && entity.category !== "triceps") return false;
      if (categoryFilter !== "all" && categoryFilter !== "arms" && entity.category !== categoryFilter) return false;
      if (!needle) return true;
      return `${entity.title} ${entity.description ?? ""}`.toLowerCase().includes(needle);
    });
  }, [auth.user.id, categoryFilter, kind, search, sources.data]);

  const createMutation = useMutation({
    mutationFn: async () => {
      const image = file ? await api.uploadImage(token, createKind, file) : {};
      return api.createActivitySource(token, {
        kind: createKind,
        title,
        description: description || null,
        category,
        equipment,
        measurement_type: measurementType,
        difficulty,
        ...image,
      });
    },
    onSuccess: () => {
      setTitle("");
      setDescription("");
      setFile(null);
      void queryClient.invalidateQueries({ queryKey: ["catalog", "activity-sources"] });
    },
  });

  function submit(event: FormEvent) {
    event.preventDefault();
    createMutation.mutate();
  }

  return (
    <section className="stack">
      <div className="page-header">
        <div>
          <p className="eyebrow">Catalog</p>
          <h2>{kind === "machine" ? "Тренажеры" : kind === "mine" ? "Мой каталог" : "Упражнения"}</h2>
        </div>
        <div className="segmented">
          <Link to="/catalog/exercises" activeProps={{ className: "active" }}>Упражнения</Link>
          <Link to="/catalog/equipment" activeProps={{ className: "active" }}>Тренажеры</Link>
          <Link to="/catalog" activeProps={{ className: "active" }} activeOptions={{ exact: true }}>Мои</Link>
        </div>
      </div>

      <section className="card catalog-controls">
        <input placeholder="Поиск по названию" value={search} onChange={(event) => setSearch(event.target.value)} />
        <div className="chip-row">
          {categoryTabs.map((tab) => (
            <button key={tab} className={categoryFilter === tab ? "active" : ""} onClick={() => setCategoryFilter(tab)}>
              {categoryTabLabel(tab)}
            </button>
          ))}
        </div>
      </section>

      <form className="card form-grid catalog-form" onSubmit={submit}>
        <label>
          Название
          <input value={title} onChange={(event) => setTitle(event.target.value)} required />
        </label>
        <label>
          Категория
          <select value={category} onChange={(event) => setCategory(event.target.value as ActivityCategory)}>
            {categoryOptions.map((option) => <option key={option} value={option}>{categoryLabels[option]}</option>)}
          </select>
        </label>
        <label>
          Оборудование
          <select value={equipment} onChange={(event) => setEquipment(event.target.value as ActivityEquipment)}>
            {equipmentOptions.map((option) => <option key={option} value={option}>{equipmentLabels[option]}</option>)}
          </select>
        </label>
        <label>
          Логирование
          <select value={measurementType} onChange={(event) => setMeasurementType(event.target.value as MeasurementType)}>
            {measurementOptions.map((option) => <option key={option} value={option}>{measurementLabels[option]}</option>)}
          </select>
        </label>
        <label>
          Сложность
          <select value={difficulty} onChange={(event) => setDifficulty(event.target.value as Difficulty)}>
            {difficultyOptions.map((option) => <option key={option} value={option}>{difficultyLabels[option]}</option>)}
          </select>
        </label>
        <label>
          Описание
          <input value={description} onChange={(event) => setDescription(event.target.value)} />
        </label>
        <label>
          Картинка
          <input type="file" accept="image/png,image/jpeg,image/webp,image/avif" onChange={(event) => setFile(event.target.files?.[0] ?? null)} />
        </label>
        <button className="primary" disabled={createMutation.isPending}>{createMutation.isPending ? "Сохранение..." : "Добавить"}</button>
        {createMutation.error && <p className="error">{createMutation.error.message}</p>}
      </form>

      <div className="catalog-grid">
        {list.map((entity) => <CatalogCard entity={entity} key={entity.id} />)}
      </div>
      {list.length === 0 && <p className="muted">Ничего не найдено.</p>}
    </section>
  );
}
