import { useEffect, useState } from "react";
import { useParams, useNavigate } from "react-router-dom";
import { useTranslation } from "react-i18next";
import { useSessionStore } from "@/stores/sessionStore";
import { useToastStore } from "@/stores/toastStore";
import { toErrorMessage } from "@/lib/api";
import { Button } from "@/components/ui/Button";
import { Card } from "@/components/ui/Card";
import { Spinner } from "@/components/ui/Spinner";
import { ChatView } from "@/components/sessions/ChatView";
import { ActionInput } from "@/components/sessions/ActionInput";
import { SseStatus } from "@/components/sessions/SseStatus";
import type { Environment, PlotRail } from "@/types";

export function PlayPage() {
  const { id } = useParams<{ id: string }>();
  const { t } = useTranslation();
  const navigate = useNavigate();
  const pushToast = useToastStore((s) => s.push);

  const world = useSessionStore((s) => s.world);
  const environment = useSessionStore((s) => s.environment);
  const nextActions = useSessionStore((s) => s.nextActions);
  const recentSteps = useSessionStore((s) => s.recentSteps);
  const loading = useSessionStore((s) => s.loading);
  const error = useSessionStore((s) => s.error);
  const submitting = useSessionStore((s) => s.submitting);
  const sseStatus = useSessionStore((s) => s.sseStatus);
  const fetchState = useSessionStore((s) => s.fetchState);
  const sendAction = useSessionStore((s) => s.sendAction);
  const retry = useSessionStore((s) => s.retry);
  const rollback = useSessionStore((s) => s.rollback);
  const reset = useSessionStore((s) => s.reset);

  const [rollbackOpen, setRollbackOpen] = useState(false);
  const [redirected, setRedirected] = useState(false);

  useEffect(() => {
    if (!id) return;
    void fetchState(id).catch((err) => pushToast("error", toErrorMessage(err, t("play.load_failed"))));
    return () => {
      reset();
    };
  }, [id, fetchState, reset, pushToast, t]);

  // Redirect non-ready worlds to the edit page (once we have the world loaded).
  useEffect(() => {
    if (!id) return;
    if (world && world.status !== "ready" && !redirected) {
      pushToast("warning", t("play.not_ready"));
      setRedirected(true);
      navigate(`/worlds/${id}/edit`, { replace: true });
    }
  }, [id, world, redirected, navigate, pushToast, t]);

  if (!id) return null;

  if (loading && !world) {
    return (
      <div className="flex items-center gap-2 p-8 text-sm text-fg-muted">
        <Spinner /> {t("common.loading")}
      </div>
    );
  }
  if (error && !world) {
    return (
      <div className="p-4">
        <p className="text-sm text-err">{t("play.load_failed")}: {error}</p>
        <Button className="mt-3" variant="secondary" onClick={() => navigate("/worlds")}>
          {t("common.back")}
        </Button>
      </div>
    );
  }
  if (!world) return null;
  if (world.status !== "ready") return null;

  const player = environment?.player;
  const plotRails: PlotRail[] = Array.isArray(world.plot_rails) ? world.plot_rails : [];
  const noSteps = recentSteps.length === 0;

  const handleSend = (action: string) => {
    void sendAction(id, action, "manual").catch((err) => {
      pushToast("error", toErrorMessage(err, "Failed"));
    });
  };

  const handleSuggested = (action: string) => {
    void sendAction(id, action, "suggested").catch((err) => {
      pushToast("error", toErrorMessage(err, "Failed"));
    });
  };

  const handleRetry = () => {
    void retry(id).catch((err) => {
      pushToast("error", toErrorMessage(err, "Failed"));
    });
  };

  const handleRollback = async () => {
    setRollbackOpen(false);
    try {
      await rollback(id);
      pushToast("success", t("play.rolled_back"));
    } catch (err) {
      pushToast("error", toErrorMessage(err, "Failed"));
    }
  };

  return (
    <div className="mx-auto flex h-[calc(100vh-3.5rem)] max-w-7xl flex-col lg:flex-row gap-3 p-3">
      {/* Environment panel */}
      <aside className="order-2 lg:order-1 lg:w-72 lg:shrink-0 overflow-y-auto space-y-3">
        <Card title={t("play.environment")}>
          <dl className="space-y-1 text-sm">
            <EnvRow label={t("play.location")} value={environment?.location} />
            <EnvRow label={t("play.time_of_day")} value={environment?.time_of_day} />
            <EnvRow label={t("play.weather")} value={environment?.weather} />
          </dl>
        </Card>

        {player && (
          <Card title={t("play.player")}>
            <dl className="space-y-1 text-sm">
              <EnvRow label={t("common.name")} value={player.name} />
              {typeof player.hp === "number" && (
                <EnvRow
                  label={t("play.hp")}
                  value={player.max_hp != null ? `${player.hp} / ${player.max_hp}` : String(player.hp)}
                />
              )}
              {typeof player.level === "number" && (
                <EnvRow label={t("play.level")} value={String(player.level)} />
              )}
              {Array.isArray(player.conditions) && player.conditions.length > 0 && (
                <div>
                  <p className="text-xs uppercase text-fg-dim">{t("play.conditions")}</p>
                  <div className="mt-1 flex flex-wrap gap-1">
                    {player.conditions.map((c, i) => (
                      <span key={i} className="badge bg-warn/15 text-warn">{c}</span>
                    ))}
                  </div>
                </div>
              )}
              {Array.isArray(player.inventory) && player.inventory.length > 0 && (
                <div>
                  <p className="text-xs uppercase text-fg-dim">{t("play.inventory")}</p>
                  <ul className="mt-1 list-disc pl-5 text-fg-muted">
                    {player.inventory.slice(0, 8).map((it, i) => (
                      <li key={i}>{typeof it === "string" ? it : (it as { name?: string }).name || JSON.stringify(it)}</li>
                    ))}
                    {player.inventory.length > 8 && <li>… +{player.inventory.length - 8}</li>}
                  </ul>
                </div>
              )}
            </dl>
          </Card>
        )}

        {plotRails.length > 0 && (
          <Card title={t("play.plot_rails")}>
            <ul className="space-y-1.5 text-sm">
              {plotRails.map((r, i) => (
                <li key={r.id || i} className="rounded-md bg-bg-soft p-2">
                  <p className="font-medium text-fg">{r.title || `Rail ${i + 1}`}</p>
                  {r.description && <p className="text-xs text-fg-muted">{r.description}</p>}
                  {r.status && (
                    <span className="badge mt-1 bg-bg-card text-fg-muted">{r.status}</span>
                  )}
                </li>
              ))}
            </ul>
          </Card>
        )}

        <Card>
          <div className="flex flex-col gap-2">
            <Button
              size="sm"
              variant="secondary"
              onClick={handleRetry}
              disabled={submitting || noSteps}
              className={noSteps ? "opacity-50 cursor-not-allowed" : ""}
              title={noSteps ? t("play.no_steps_to_retry") : undefined}
            >
              {t("play.retry_last")}
            </Button>
            <Button
              size="sm"
              variant="ghost"
              onClick={() => setRollbackOpen(true)}
              disabled={submitting || noSteps}
              className={noSteps ? "opacity-50 cursor-not-allowed" : ""}
              title={noSteps ? t("play.no_steps_to_rollback") : undefined}
            >
              {t("play.rollback")}
            </Button>
          </div>
        </Card>
      </aside>

      {/* Chat area */}
      <main className="order-1 lg:order-2 flex min-h-0 flex-1 flex-col">
        <Card className="flex min-h-0 flex-1 flex-col p-0">
          <header className="flex items-center justify-between border-b border-fg-dim/20 p-3">
            <div>
              <h2 className="text-base font-semibold text-fg">{world.name}</h2>
              <p className="text-xs text-fg-muted">
                {world.current_time ? `${t("worlds.current_time")}: ${world.current_time}` : ""}
              </p>
            </div>
            <SseStatus status={sseStatus} />
          </header>
          <ChatView className="flex-1 min-h-0" />
          <footer className="border-t border-fg-dim/20 p-3">
            <ActionInput
              onSubmit={handleSend}
              onSuggestedClick={handleSuggested}
              submitting={submitting}
              suggestedActions={nextActions}
              placeholder={t("play.action_placeholder")}
            />
          </footer>
        </Card>
      </main>

      {/* Rollback confirm modal */}
      {rollbackOpen && (
        <div className="fixed inset-0 z-50 flex items-center justify-center p-4">
          <div className="absolute inset-0 bg-black/60" onClick={() => setRollbackOpen(false)} />
          <div className="relative z-10 w-full max-w-sm rounded-lg border border-fg-dim/30 bg-bg-card p-4 shadow-2xl">
            <p className="text-sm text-fg">{t("play.rollback_confirm")}</p>
            <div className="mt-4 flex justify-end gap-2">
              <Button variant="ghost" onClick={() => setRollbackOpen(false)}>
                {t("common.cancel")}
              </Button>
              <Button variant="danger" onClick={handleRollback}>
                {t("play.rollback")}
              </Button>
            </div>
          </div>
        </div>
      )}
    </div>
  );
}

function EnvRow({ label, value }: { label: string; value: unknown }) {
  if (value == null || value === "") return null;
  const text = typeof value === "string" ? value : typeof value === "object" ? JSON.stringify(value) : String(value);
  return (
    <div className="flex items-start justify-between gap-2">
      <dt className="text-xs text-fg-dim">{label}</dt>
      <dd className="text-right text-sm text-fg">{text}</dd>
    </div>
  );
}
