import { useEffect, useState, type FormEvent } from "react";
import { classById } from "../app/characterCatalog";
import { selectedCharacter, useShellStore } from "../app/shellStore";
import { useOnlineGroupStore } from "../app/onlineGroupStore";
import {
  classCanFillPartyRole,
  partyRolesForClass,
  PARTY_ROLE_LABELS,
  type PartyRole,
} from "../game/partyRoles";

export function OnlineGroupPanel() {
  const [username, setUsername] = useState("");
  const [panelOpen, setPanelOpen] = useState(false);
  const session = useShellStore((state) => state.session);
  const character = useShellStore(selectedCharacter);
  const snapshot = useOnlineGroupStore((state) => state.snapshot);
  const busy = useOnlineGroupStore((state) => state.busy);
  const error = useOnlineGroupStore((state) => state.error);
  const fillWithAi = useOnlineGroupStore((state) => state.fillWithAi);
  const invite = useOnlineGroupStore((state) => state.invite);
  const respond = useOnlineGroupStore((state) => state.respond);
  const leave = useOnlineGroupStore((state) => state.leave);
  const remove = useOnlineGroupStore((state) => state.remove);
  const updateMember = useOnlineGroupStore((state) => state.updateMember);
  const clearActivity = useOnlineGroupStore((state) => state.clearActivity);
  const setFillWithAi = useOnlineGroupStore((state) => state.setFillWithAi);

  useEffect(() => {
    if (snapshot.invitations.length > 0) setPanelOpen(true);
  }, [snapshot.invitations.length]);

  if (!session || session.kind !== "account" || !session.accessToken) return null;
  const group = snapshot.group;
  const currentMember = group?.members.find((member) => member.accountId === session.ownerId) ?? null;
  const leader = group?.leaderAccountId === session.ownerId;
  const roles = character ? partyRolesForClass(character.classId) : [];
  const readyCount = group?.members.filter((member) => member.character && member.role).length ?? 0;

  const submitInvite = async (event: FormEvent) => {
    event.preventDefault();
    if (!username.trim()) return;
    if (await invite(session, username.trim())) setUsername("");
  };
  const chooseRole = (role: PartyRole) => {
    if (character && classCanFillPartyRole(character.classId, role)) void updateMember(session, character, role);
  };

  return (
    <details className="online-group-panel" open={panelOpen} onToggle={(event) => setPanelOpen(event.currentTarget.open)}>
      <summary>
        <span aria-hidden="true">◎</span>
        <strong>Online group</strong>
        <small>{group ? `${group.members.length} / 5 players · ${readyCount} ready` : "Optional co-op"}</small>
      </summary>
      <div className="online-group-panel__body">
        {snapshot.invitations.length > 0 && (
          <section className="online-group-invites" aria-label="Group invitations">
            <strong>Invitations</strong>
            {snapshot.invitations.map((invitation) => (
              <div key={invitation.id}>
                <span><b>{invitation.inviterUsername}</b><small>wants you in their group</small></span>
                <button type="button" disabled={busy} onClick={() => void respond(session, invitation.id, true)}>Accept</button>
                <button type="button" disabled={busy} onClick={() => void respond(session, invitation.id, false)}>Decline</button>
              </div>
            ))}
          </section>
        )}

        {group && (
          <section className="online-group-roster" aria-label="Online group roster">
            <header><strong>Party roster</strong><small>{leader ? "You are the leader" : "Waiting for the leader"}</small></header>
            {group.members.map((member) => {
              const memberClass = member.character ? classById(member.character.classId as Parameters<typeof classById>[0]) : null;
              return (
                <div className="online-group-member" key={member.accountId}>
                  <span className={member.character && member.role ? "is-ready" : ""} aria-hidden="true" />
                  <p>
                    <strong>{member.username}{group.leaderAccountId === member.accountId ? " ★" : ""}</strong>
                    <small>{member.character
                      ? `${member.character.name} · Level ${member.character.level} ${memberClass?.name ?? member.character.classId}`
                      : "Choosing a character"}</small>
                  </p>
                  <b>{member.role ? PARTY_ROLE_LABELS[member.role] : "Not ready"}</b>
                  {leader && member.accountId !== session.ownerId && (
                    <button type="button" disabled={busy} onClick={() => void remove(session, member.accountId)}>Remove</button>
                  )}
                </div>
              );
            })}
          </section>
        )}

        {group && character && currentMember && (
          <section className="online-group-role" aria-label="Your group role">
            <strong>Your role</strong>
            <div>
              {roles.map((role) => (
                <button
                  type="button"
                  key={role}
                  className={currentMember.role === role ? "is-active" : ""}
                  disabled={busy || Boolean(group.activity)}
                  aria-pressed={currentMember.role === role}
                  onClick={() => chooseRole(role)}
                >
                  {PARTY_ROLE_LABELS[role]}
                </button>
              ))}
            </div>
          </section>
        )}

        {group?.activity && (
          <div className="online-group-activity" role="status">
            <span>
              <strong>Launching {group.activity.type === "dungeon" ? "dungeon" : "Manastorm"}</strong>
              <small>{group.activity.fillWithAi ? `Party filled to ${group.activity.partySize} with AI` : `${group.activity.partySize} players only`}</small>
            </span>
            {leader && <button type="button" disabled={busy} onClick={() => void clearActivity(session)}>Reset</button>}
          </div>
        )}

        {leader && group && !group.activity && (
          <label className="online-group-ai-toggle">
            <input type="checkbox" checked={fillWithAi} onChange={(event) => setFillWithAi(event.target.checked)} />
            <span><strong>Fill open slots with AI</strong><small>Turn off to enter with only grouped players.</small></span>
          </label>
        )}

        {(!group || leader) && (
          <form className="online-group-invite-form" onSubmit={submitInvite}>
            <label htmlFor="online-group-username">Invite account name</label>
            <div>
              <input
                id="online-group-username"
                value={username}
                maxLength={20}
                autoComplete="off"
                placeholder="PlayerName"
                onChange={(event) => setUsername(event.target.value)}
              />
              <button type="submit" disabled={busy || !username.trim() || (group?.members.length ?? 0) >= 5}>Invite</button>
            </div>
          </form>
        )}

        {group && (
          <button className="online-group-leave" type="button" disabled={busy} onClick={() => void leave(session)}>
            {leader && group.members.length > 1 ? "Leave and transfer leadership" : "Leave group"}
          </button>
        )}
        {error && <p className="online-group-error" role="alert">{error}</p>}
      </div>
    </details>
  );
}
