'use client';

import { FormEvent, useEffect, useMemo, useRef, useState } from 'react';

const defaultApiBase =
  process.env.NODE_ENV === 'production'
    ? 'https://backend.basetracker.lona-development.org'
    : 'https://backend.dev.basetracker.lona-development.org';

// Normalize backend URL so production always uses HTTPS while keeping local HTTP.
function normalizeApiBase(url: string) {
  try {
    const parsed = new URL(url);
    const isLocalhost = ['localhost', '127.0.0.1', '0.0.0.0'].includes(parsed.hostname);
    if (!isLocalhost && parsed.protocol === 'http:') {
      parsed.protocol = 'https:';
    }
    return parsed.toString().replace(/\/$/, '');
  } catch (_error) {
    return url.replace(/\/$/, '');
  }
}

const API_BASE = normalizeApiBase(process.env.NEXT_PUBLIC_BACKEND_URL ?? defaultApiBase);

const API = {
  signup: `${API_BASE}/auth/signup`,
  login: `${API_BASE}/auth/login`,
  logout: `${API_BASE}/auth/logout`,
  me: `${API_BASE}/auth/me`,
  categories: `${API_BASE}/army-categories`,
  bases: `${API_BASE}/bases`,
  addDefense: (baseId: string) => `${API_BASE}/bases/${baseId}/defenses`,
  defenses: `${API_BASE}/defenses`,
  deleteCategory: (categoryId: string) => `${API_BASE}/army-categories/${categoryId}`,
  updateBase: (baseId: string) => `${API_BASE}/bases/${baseId}`,
  deleteBase: (baseId: string) => `${API_BASE}/bases/${baseId}`,
  addTrophyReset: (baseId: string) => `${API_BASE}/bases/${baseId}/trophy-resets`,
  updateTrophyReset: (resetId: string) => `${API_BASE}/trophy-resets/${resetId}`,
  deleteTrophyReset: (resetId: string) => `${API_BASE}/trophy-resets/${resetId}`,
  updateDefense: (defenseId: string) => `${API_BASE}/defenses/${defenseId}`,
  deleteDefense: (defenseId: string) => `${API_BASE}/defenses/${defenseId}`,
  profiles: `${API_BASE}/profiles`,
  profileDetail: (username: string) => `${API_BASE}/profiles/${encodeURIComponent(username)}`,
};

function resolveImageUrl(url: string | null | undefined) {
  if (!url) {
    return '';
  }
  try {
    return new URL(url, `${API_BASE}/`).toString();
  } catch (_error) {
    return url;
  }
}

type User = {
  id: string;
  username: string;
  createdAt: string;
};

type ArmyCategory = {
  id: string;
  name: string;
  createdAt: string;
};

type TrophyReset = {
  id: string;
  date: string;
  trophiesAtStart: number;
  trophiesLost: number;
  numberOfDefenses: number;
  createdAt: string;
};

type BaseItem = {
  id: string;
  title: string;
  description: string;
  url: string;
  imageUrl: string;
  isPrivate: boolean;
  createdAt: string;
  trophyResets: TrophyReset[];
};

type DefenseItem = {
  id: string;
  stars: number;
  percent: number;
  trophies: number;
  armyCategoryId: string;
  createdAt: string;
  baseId: string;
  baseTitle: string;
  categoryName?: string;
};

type ProfileSummaryItem = {
  id: string;
  username: string;
  createdAt: string;
  publicBaseCount: number;
  publicDefenseCount: number;
};

type ProfileDefense = {
  id: string;
  stars: number;
  percent: number;
  trophies: number;
  createdAt: string;
  armyCategoryId: string;
  armyCategoryName: string;
};

type ProfileBase = {
  id: string;
  title: string;
  description: string;
  url: string;
  imageUrl: string;
  isPrivate: boolean;
  createdAt: string;
  summary: Summary;
  defenses: ProfileDefense[];
  trophyResets: TrophyReset[];
};

type ProfileCategorySummary = Summary & {
  armyCategoryId: string;
  name: string;
};

type ProfileDetail = {
  profile: {
    id: string;
    username: string;
    createdAt: string;
    isOwner: boolean;
    visibleBaseCount: number;
    defenseCount: number;
    summary: Summary;
  };
  bases: ProfileBase[];
};

type Summary = {
  count: number;
  averageStars: number;
  averagePercent: number;
  averageTrophies: number;
};

type BaseSummary = Summary & {
  baseId: string;
  title: string;
  categories: Array<Summary & { categoryId: string; name: string }>;
};

type CategorySummary = Summary & {
  categoryId: string;
  name: string;
  bases: Array<Summary & { baseId: string; title: string }>;
};

type Summaries = {
  overall: Summary;
  categories: CategorySummary[];
  bases: BaseSummary[];
};

type ErrorState = {
  login: string;
  signup: string;
  category: string;
  base: string;
  defense: string;
  trophyReset: string;
};

async function request(method: string, url: string, body?: any, options?: { isForm?: boolean }) {
  const isForm = options?.isForm ?? false;
  const fetchOptions: RequestInit = {
    method,
    credentials: 'include',
  };

  if (isForm && body instanceof FormData) {
    fetchOptions.body = body;
  } else if (body !== undefined) {
    fetchOptions.headers = { 'Content-Type': 'application/json' };
    fetchOptions.body = JSON.stringify(body);
  }

  const response = await fetch(url, fetchOptions);
  const contentType = response.headers.get('content-type') ?? '';
  const data = contentType.includes('application/json') ? await response.json() : {};
  if (!response.ok) {
    const message = (data && data.error) || 'Something went wrong';
    throw new Error(message);
  }
  return data;
}

const initialErrors: ErrorState = {
  login: '',
  signup: '',
  category: '',
  base: '',
  defense: '',
  trophyReset: '',
};

export default function Page() {
  const [authTab, setAuthTab] = useState<'login' | 'signup'>('login');
  const [view, setView] = useState<'dashboard' | 'forms' | 'baseDetail' | 'categoryDetail' | 'profileBaseDetail'>(
    'dashboard'
  );
  const [user, setUser] = useState<User | null>(null);
  const [categories, setCategories] = useState<ArmyCategory[]>([]);
  const [bases, setBases] = useState<BaseItem[]>([]);
  const [defenses, setDefenses] = useState<DefenseItem[]>([]);
  const [summaries, setSummaries] = useState<Summaries | null>(null);
  const [selectedBaseId, setSelectedBaseId] = useState<string | null>(null);
  const [selectedCategoryId, setSelectedCategoryId] = useState<string | null>(null);
  const [errors, setErrors] = useState<ErrorState>(initialErrors);
  const [imageMode, setImageMode] = useState<'upload' | 'url'>('upload');
  const [editImageMode, setEditImageMode] = useState<'keep' | 'upload' | 'url' | 'remove'>('keep');
  const [editingBaseId, setEditingBaseId] = useState<string | null>(null);
  const [editingDefenseId, setEditingDefenseId] = useState<string | null>(null);
  const [editingTrophyResetId, setEditingTrophyResetId] = useState<string | null>(null);
  const [profileSearchTerm, setProfileSearchTerm] = useState('');
  const [profileResults, setProfileResults] = useState<ProfileSummaryItem[]>([]);
  const [profileDetail, setProfileDetail] = useState<ProfileDetail | null>(null);
  const [profileError, setProfileError] = useState('');
  const [profileLoading, setProfileLoading] = useState(false);
  const [profileSelectedBase, setProfileSelectedBase] = useState<ProfileBase | null>(null);
  const [loading, setLoading] = useState(true);
  const isAuthenticatedRef = useRef(false);

  useEffect(() => {
    (async () => {
      try {
        const data = await request('GET', API.me);
        setUser(data.user);
        isAuthenticatedRef.current = true;
        await refreshData();
        setView('dashboard');
      } catch (_err) {
        setUser(null);
        isAuthenticatedRef.current = false;
        setView('dashboard');
      } finally {
        setLoading(false);
      }
    })();
  }, []);

  async function refreshData() {
    if (!isAuthenticatedRef.current) {
      return;
    }
    try {
      const [basesRes, categoriesRes, defensesRes] = await Promise.all([
        request('GET', API.bases),
        request('GET', API.categories),
        request('GET', API.defenses),
      ]);
      const normalizedBases = ((basesRes.bases || []) as BaseItem[]).map((base) => ({
        ...base,
        imageUrl: resolveImageUrl(base.imageUrl),
      }));
      setBases(normalizedBases);
      setCategories(categoriesRes.categories || []);
      setDefenses(defensesRes.defenses || []);
      setSummaries({
        overall: defensesRes.overall,
        categories: defensesRes.categories,
        bases: defensesRes.bases,
      });
    } catch (error) {
      console.error(error);
    }
  }

  const baseSummaryMap = useMemo(() => {
    const map = new Map<string, BaseSummary>();
    summaries?.bases.forEach((baseSummary) => map.set(baseSummary.baseId, baseSummary));
    return map;
  }, [summaries]);

  const categorySummaryMap = useMemo(() => {
    const map = new Map<string, CategorySummary>();
    summaries?.categories.forEach((categorySummary) => map.set(categorySummary.categoryId, categorySummary));
    return map;
  }, [summaries]);

  const baseBeingEdited = useMemo(() => {
    if (!editingBaseId) return null;
    return bases.find((base) => base.id === editingBaseId) ?? null;
  }, [editingBaseId, bases]);

  const defenseBeingEdited = useMemo(() => {
    if (!editingDefenseId) return null;
    return defenses.find((defense) => defense.id === editingDefenseId) ?? null;
  }, [editingDefenseId, defenses]);

  const trophyResetBeingEdited = useMemo(() => {
    if (!editingTrophyResetId) return null;
    const allResets = bases.flatMap((base) => base.trophyResets);
    return allResets.find((reset) => reset.id === editingTrophyResetId) ?? null;
  }, [editingTrophyResetId, bases]);

  const profileSelectedBaseCategories = useMemo(() => {
    if (!profileSelectedBase) {
      return [] as ProfileCategorySummary[];
    }
    const buckets = new Map<string, { name: string; items: ProfileDefense[] }>();
    profileSelectedBase.defenses.forEach((defense) => {
      const key = defense.armyCategoryId || defense.armyCategoryName;
      if (!buckets.has(key)) {
        buckets.set(key, { name: defense.armyCategoryName || '(No category)', items: [] });
      }
      buckets.get(key)!.items.push(defense);
    });
    const summaries: ProfileCategorySummary[] = Array.from(buckets.entries()).map(([armyCategoryId, bucket]) => ({
      armyCategoryId,
      name: bucket.name,
      ...summarizeProfileDefenses(bucket.items),
    }));
    summaries.sort((a, b) => b.count - a.count || a.name.localeCompare(b.name));
    return summaries;
  }, [profileSelectedBase]);

  async function handleLogin(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();
    const formData = new FormData(event.currentTarget);
    const payload = Object.fromEntries(formData.entries());
    try {
      setErrors((prev) => ({ ...prev, login: '' }));
      const data = await request('POST', API.login, payload);
      setUser(data.user);
      isAuthenticatedRef.current = true;
      await refreshData();
      setView('dashboard');
    } catch (error: any) {
      setErrors((prev) => ({ ...prev, login: error.message }));
    }
  }

  async function handleSignup(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();
    const formData = new FormData(event.currentTarget);
    const payload = Object.fromEntries(formData.entries());
    try {
      if ((payload.password as string)?.length < 6) {
        throw new Error('Use at least 6 characters for your password.');
      }
      setErrors((prev) => ({ ...prev, signup: '' }));
      const data = await request('POST', API.signup, payload);
      setUser(data.user);
      isAuthenticatedRef.current = true;
      await refreshData();
      setView('dashboard');
    } catch (error: any) {
      setErrors((prev) => ({ ...prev, signup: error.message }));
    }
  }

  async function handleCategorySubmit(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();
    const form = event.currentTarget;
    const formData = new FormData(form);
    const payload = Object.fromEntries(formData.entries());
    try {
      setErrors((prev) => ({ ...prev, category: '' }));
      await request('POST', API.categories, payload);
      form.reset();
      await refreshData();
    } catch (error: any) {
      setErrors((prev) => ({ ...prev, category: error.message }));
    }
  }

  async function handleBaseSubmit(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();
    const form = event.currentTarget;
    const formData = new FormData(form);
    formData.set('imageMode', imageMode);
    if (imageMode === 'upload') {
      formData.delete('imageUrl');
    } else {
      formData.delete('imageFile');
    }
    const requestedPrivate = formData.get('isPrivate');
    const isPrivate = typeof requestedPrivate === 'string' ? requestedPrivate === 'on' : false;
    formData.set('isPrivate', isPrivate ? 'true' : 'false');
    formData.set('removeImage', 'false');
    try {
      setErrors((prev) => ({ ...prev, base: '' }));
      await request('POST', API.bases, formData, { isForm: true });
      form.reset();
      setImageMode('upload');
      await refreshData();
      await refreshOwnProfileDetail();
    } catch (error: any) {
      setErrors((prev) => ({ ...prev, base: error.message }));
    }
  }

  async function handleDefenseSubmit(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();
    const form = event.currentTarget;
    const formData = new FormData(form);
    const payload = Object.fromEntries(formData.entries());
    try {
      const baseId = payload.baseId as string;
      setErrors((prev) => ({ ...prev, defense: '' }));
      await request('POST', API.addDefense(baseId), payload);
      form.reset();
      await refreshData();
      await refreshOwnProfileDetail();
    } catch (error: any) {
      setErrors((prev) => ({ ...prev, defense: error.message }));
    }
  }

  function startEditingBase(baseId: string) {
    setEditingBaseId(baseId);
    setEditImageMode('keep');
    setErrors((prev) => ({ ...prev, base: '' }));
  }

  function cancelEditingBase() {
    setEditingBaseId(null);
    setEditImageMode('keep');
  }

  async function handleBaseEditSubmit(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();
    if (!editingBaseId || !baseBeingEdited) {
      return;
    }
    const form = event.currentTarget;
    const formData = new FormData(form);
    formData.set('imageMode', editImageMode);
    formData.set('removeImage', editImageMode === 'remove' ? 'true' : 'false');
    const requestedPrivate = formData.get('isPrivate');
    const isPrivate = typeof requestedPrivate === 'string' ? requestedPrivate === 'on' : false;
    formData.set('isPrivate', isPrivate ? 'true' : 'false');
    if (editImageMode === 'upload') {
      formData.delete('imageUrl');
    } else if (editImageMode === 'url') {
      formData.delete('imageFile');
    } else {
      formData.delete('imageFile');
      formData.delete('imageUrl');
    }
    try {
      setErrors((prev) => ({ ...prev, base: '' }));
      await request('PUT', API.updateBase(editingBaseId), formData, { isForm: true });
      setEditingBaseId(null);
      setEditImageMode('keep');
      await refreshData();
      await refreshOwnProfileDetail();
    } catch (error: any) {
      setErrors((prev) => ({ ...prev, base: error.message }));
    }
  }

  async function handleDeleteBase(baseId: string) {
    const base = bases.find((item) => item.id === baseId);
    const name = base ? `"${base.title}"` : 'this base';
    const confirmDelete = window.confirm(`Delete ${name}? This also removes its attacks.`);
    if (!confirmDelete) {
      return;
    }
    try {
      await request('DELETE', API.deleteBase(baseId));
      if (editingBaseId === baseId) {
        setEditingBaseId(null);
        setEditImageMode('keep');
      }
      if (selectedBaseId === baseId) {
        setSelectedBaseId(null);
        setView('dashboard');
      }
      await refreshData();
      await refreshOwnProfileDetail();
    } catch (error: any) {
      setErrors((prev) => ({ ...prev, base: error.message }));
    }
  }

  async function handleDeleteCategory(categoryId: string) {
    const category = categories.find((item) => item.id === categoryId);
    const name = category ? `"${category.name}"` : 'this category';
    const confirmDelete = window.confirm(`Delete ${name}? Attacks tracked for it will also go away.`);
    if (!confirmDelete) {
      return;
    }
    try {
      await request('DELETE', API.deleteCategory(categoryId));
      if (selectedCategoryId === categoryId) {
        setSelectedCategoryId(null);
        setView('dashboard');
      }
      await refreshData();
      await refreshOwnProfileDetail();
    } catch (error: any) {
      setErrors((prev) => ({ ...prev, category: error.message }));
    }
  }

  function startEditingDefense(defenseId: string) {
    setEditingDefenseId(defenseId);
    setErrors((prev) => ({ ...prev, defense: '' }));
  }

  function cancelEditingDefense() {
    setEditingDefenseId(null);
  }

  function startEditingTrophyReset(resetId: string) {
    setEditingTrophyResetId(resetId);
    setErrors((prev) => ({ ...prev, trophyReset: '' }));
  }

  function cancelEditingTrophyReset() {
    setEditingTrophyResetId(null);
  }

  async function handleDefenseEditSubmit(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();
    if (!editingDefenseId || !defenseBeingEdited) {
      return;
    }
    const form = event.currentTarget;
    const formData = new FormData(form);
    const payload = Object.fromEntries(formData.entries());
    try {
      setErrors((prev) => ({ ...prev, defense: '' }));
      await request('PUT', API.updateDefense(editingDefenseId), payload);
      setEditingDefenseId(null);
      await refreshData();
      await refreshOwnProfileDetail();
    } catch (error: any) {
      setErrors((prev) => ({ ...prev, defense: error.message }));
    }
  }

  async function handleDeleteDefense(defenseId: string) {
    const confirmDelete = window.confirm('Delete this attack?');
    if (!confirmDelete) {
      return;
    }
    try {
      await request('DELETE', API.deleteDefense(defenseId));
      if (editingDefenseId === defenseId) {
        setEditingDefenseId(null);
      }
      await refreshData();
      await refreshOwnProfileDetail();
    } catch (error: any) {
      setErrors((prev) => ({ ...prev, defense: error.message }));
    }
  }

  async function handleTrophyResetEditSubmit(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();
    if (!editingTrophyResetId) {
      return;
    }
    const form = event.currentTarget;
    const formData = new FormData(form);
    const payload = Object.fromEntries(formData.entries());
    try {
      setErrors((prev) => ({ ...prev, trophyReset: '' }));
      await request('PUT', API.updateTrophyReset(editingTrophyResetId), payload);
      setEditingTrophyResetId(null);
      await refreshData();
      await refreshOwnProfileDetail();
    } catch (error: any) {
      setErrors((prev) => ({ ...prev, trophyReset: error.message }));
    }
  }

  async function handleDeleteTrophyReset(resetId: string) {
    const confirmDelete = window.confirm('Delete this reset?');
    if (!confirmDelete) {
      return;
    }
    try {
      await request('DELETE', API.deleteTrophyReset(resetId));
      if (editingTrophyResetId === resetId) {
        setEditingTrophyResetId(null);
      }
      await refreshData();
      await refreshOwnProfileDetail();
    } catch (error: any) {
      setErrors((prev) => ({ ...prev, trophyReset: error.message }));
    }
  }

  async function handleProfileSearch(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();
    setProfileError('');
    const term = profileSearchTerm.trim();
    if (!term) {
      setProfileResults([]);
      setProfileDetail(null);
      setProfileSelectedBase(null);
      return;
    }
    try {
      setProfileLoading(true);
      const data = await request('GET', `${API.profiles}?search=${encodeURIComponent(term)}`);
      setProfileResults(data.profiles || []);
      setProfileDetail(null);
      setProfileSelectedBase(null);
    } catch (error: any) {
      setProfileResults([]);
      setProfileDetail(null);
      setProfileSelectedBase(null);
      setProfileError(error.message);
    } finally {
      setProfileLoading(false);
    }
  }

  async function loadProfile(username: string) {
    try {
      setProfileLoading(true);
      setProfileError('');
      setProfileSelectedBase(null);
      const data: ProfileDetail = await request('GET', API.profileDetail(username));
      const normalizedDetail: ProfileDetail = {
        ...data,
        bases: data.bases.map((base) => ({
          ...base,
          imageUrl: resolveImageUrl(base.imageUrl),
        })),
      };
      setProfileDetail(normalizedDetail);
      setView('dashboard');
    } catch (error: any) {
      setProfileDetail(null);
      setProfileSelectedBase(null);
      setProfileError(error.message);
    } finally {
      setProfileLoading(false);
    }
  }

  function clearProfileDetail() {
    setProfileDetail(null);
    setProfileSelectedBase(null);
    setView('dashboard');
  }

  function openProfileBaseDetail(base: ProfileBase) {
    setProfileSelectedBase(base);
    setView('profileBaseDetail');
  }

  function closeProfileBaseDetail() {
    setProfileSelectedBase(null);
    setView('dashboard');
  }

  function goToDashboard() {
    setView('dashboard');
    setProfileSelectedBase(null);
  }

  async function refreshOwnProfileDetail() {
    if (profileDetail && user && profileDetail.profile.username === user.username) {
      await loadProfile(user.username);
    }
  }

  async function handleTrophyResetSubmit(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();
    const form = event.currentTarget;
    const formData = new FormData(form);
    const payload = Object.fromEntries(formData.entries());
    const baseId = payload.baseId as string;
    if (!baseId) {
      setErrors((prev) => ({ ...prev, trophyReset: 'Base is required' }));
      return;
    }
    try {
      setErrors((prev) => ({ ...prev, trophyReset: '' }));
      await request('POST', API.addTrophyReset(baseId), payload);
      form.reset();
      await refreshData();
    } catch (error: any) {
      setErrors((prev) => ({ ...prev, trophyReset: error.message }));
    }
  }

  async function handleLogout() {
    try {
      await request('POST', API.logout);
    } catch (error) {
      console.error(error);
    } finally {
      setUser(null);
      setBases([]);
      setCategories([]);
      setDefenses([]);
      setSummaries(null);
      setSelectedBaseId(null);
      setSelectedCategoryId(null);
      setEditingBaseId(null);
      setEditingDefenseId(null);
      setEditImageMode('keep');
      setProfileResults([]);
      setProfileDetail(null);
      setProfileSelectedBase(null);
      setProfileSearchTerm('');
      setProfileError('');
      setProfileLoading(false);
      isAuthenticatedRef.current = false;
      setView('dashboard');
    }
  }

  function openBaseDetail(baseId: string) {
    setSelectedBaseId(baseId);
    setView('baseDetail');
  }

  function openCategoryDetail(categoryId: string) {
    setSelectedCategoryId(categoryId);
    setView('categoryDetail');
  }

  const baseDetail = selectedBaseId ? baseSummaryMap.get(selectedBaseId) : null;
  const baseDetailMeta = selectedBaseId ? bases.find((base) => base.id === selectedBaseId) : null;
  const categoryDetail = selectedCategoryId ? categorySummaryMap.get(selectedCategoryId) : null;

  const categoryNameMap = useMemo(() => {
    const map = new Map<string, string>();
    categories.forEach((category) => map.set(category.id, category.name));
    return map;
  }, [categories]);

function formatTrophies(value: number) {
  const sign = value > 0 ? '' : '+';
  let gained = false;
  if(sign === '+') gained = true;
  let suffix = gained ? 'gained' : 'lost';
  return `${sign}${value} trophies ${suffix}`; 
}

function summarizeProfileDefenses(defenses: ProfileDefense[]): Summary {
  if (!defenses.length) {
    return { count: 0, averageStars: 0, averagePercent: 0, averageTrophies: 0 };
  }
  const totalStars = defenses.reduce((sum, defense) => sum + Number(defense.stars || 0), 0);
  const totalPercent = defenses.reduce((sum, defense) => sum + Number(defense.percent || 0), 0);
  const totalTrophies = defenses.reduce((sum, defense) => sum + Number(defense.trophies || 0), 0);
  const count = defenses.length;
  return {
    count,
    averageStars: Number((totalStars / count).toFixed(2)),
    averagePercent: Number((totalPercent / count).toFixed(2)),
    averageTrophies: Number((totalTrophies / count).toFixed(2)),
  };
}

  if (loading) {
    return (
      <main className="container">
        <section className="card">
          <h1>Loading Base Tracker...</h1>
        </section>
      </main>
    );
  }

  if (!user) {
    return (
      <main className="container">
        <section id="auth-screen" className="card">
          <h1>Base Tracker</h1>
          <p className="subtitle">Track how each base defends against every army.</p>
          <div className="tabs">
            <button
              className={`tab-button ${authTab === 'login' ? 'active' : ''}`}
              onClick={() => setAuthTab('login')}
            >
              Log In
            </button>
            <button
              className={`tab-button ${authTab === 'signup' ? 'active' : ''}`}
              onClick={() => setAuthTab('signup')}
            >
              Sign Up
            </button>
          </div>
          <div className="form-wrapper">
            {authTab === 'login' ? (
              <form className="form auth-form active" onSubmit={handleLogin}>
                <label>
                  Username
                  <input name="username" type="text" required autoComplete="username" />
                </label>
                <label>
                  Password
                  <input name="password" type="password" required />
                </label>
                <button type="submit" className="primary">
                  Log In
                </button>
                <p className="form-error" data-for="login">
                  {errors.login}
                </p>
              </form>
            ) : (
              <form className="form auth-form active" onSubmit={handleSignup}>
                <label>
                  Username
                  <input name="username" type="text" minLength={3} required autoComplete="username" />
                </label>
                <label>
                  Password
                  <input name="password" type="password" minLength={6} required autoComplete="new-password" />
                </label>
                <button type="submit" className="primary">
                  Create Account
                </button>
                <p className="form-error" data-for="signup">
                  {errors.signup}
                </p>
              </form>
            )}
          </div>
        </section>
      </main>
    );
  }

  return (
    <main className="container">
      <section id="app-screen">
        <header className="top-bar">
          <div>
            <h1>Base Tracker</h1>
            <span id="user-username">{user.username}</span>
          </div>
          <div className="top-bar-actions">
            <button
              id="dashboard-button"
              className={`ghost ${view === 'dashboard' ? 'hidden' : ''}`}
              type="button"
              onClick={goToDashboard}
            >
              Dashboard
            </button>
            <button
              id="new-button"
              className={`ghost accent small ${view === 'forms' ? 'active' : ''}`}
              type="button"
              onClick={() => setView('forms')}
            >
              New Entry
            </button>
            <button id="logout-button" className="ghost" type="button" onClick={handleLogout}>
              Log Out
            </button>
          </div>
        </header>

        <section id="dashboard-view" className={`view-section ${view !== 'dashboard' ? 'hidden' : ''}`}>
          <section className="summary-grid">
            <div className="card">
              <h2>Overall Average</h2>
              <div className="stat" id="overall-summary">
                {summaries && summaries.overall.count ? (
                  <>
                    <strong>{summaries.overall.averageStars}★</strong> average •{' '}
                    <strong>{summaries.overall.averagePercent}%</strong> destruction
                    <br />
                    <span className="badge">{formatTrophies(summaries.overall.averageTrophies)}</span>{' '}
                    <span className="badge">{summaries.overall.count} attacks</span>
                  </>
                ) : (
                  'No defenses logged yet.'
                )}
              </div>
              <div className="subsection">
                <h3>Base Averages</h3>
                <ul id="base-summary" className="list compact">
                  {summaries && summaries.bases.length ? (
                    summaries.bases.map((base) => {
                      const baseMeta = bases.find((item) => item.id === base.baseId);
                      return (
                        <li
                          key={base.baseId}
                          className="list-item clickable"
                          onClick={() => openBaseDetail(base.baseId)}
                        >
                          <div className="defense-header">
                            <div>
                              <strong>{base.title}</strong>{' '}
                              {baseMeta?.isPrivate ? <span className="badge muted">Private</span> : null}
                            </div>
                            <span className="badge">{base.count} defenses</span>
                          </div>
                          <div className="defense-meta">
                            <span>{base.averageStars}★ avg</span>
                            <span>{base.averagePercent}% avg</span>
                            <span>{formatTrophies(base.averageTrophies)} avg</span>
                          </div>
                        </li>
                      );
                    })
                  ) : (
                    <li>
                      {bases.length
                        ? 'Bases have defenses pending tracking.'
                        : 'Add a base to start collecting its averages.'}
                    </li>
                  )}
                </ul>
              </div>
            </div>
            <div className="card">
              <h2>Category Averages</h2>
              <ul id="category-summary" className="list">
                {summaries && summaries.categories.length ? (
                  summaries.categories.map((category) => (
                    <li
                      key={category.categoryId}
                      className="list-item clickable"
                      onClick={() => openCategoryDetail(category.categoryId)}
                    >
                      <div className="defense-header">
                        <strong>{category.name}</strong>
                        <span className="badge">{category.count} attacks</span>
                      </div>
                      <div className="defense-meta">
                        <span>{category.averageStars}★ avg</span>
                        <span>{category.averagePercent}% avg</span>
                        <span>{formatTrophies(category.averageTrophies)} avg</span>
                      </div>
                    </li>
                  ))
                ) : (
                  <li>Create an army category to start tracking.</li>
                )}
              </ul>
            </div>
          </section>

          <div className="card">
            <h2>Search Profiles</h2>
            <form className="form compact" onSubmit={handleProfileSearch}>
              <label>
                Username
                <input
                  type="text"
                  value={profileSearchTerm}
                  onChange={(event) => setProfileSearchTerm(event.target.value)}
                  placeholder="Search by username"
                />
              </label>
              <div className="defense-meta">
                <button type="submit" className="primary" disabled={profileLoading}>
                  {profileLoading ? 'Searching…' : 'Search'}
                </button>
                <button
                  type="button"
                  className="ghost"
                  onClick={() => {
                    setProfileSearchTerm('');
                    setProfileResults([]);
                    setProfileDetail(null);
                    setProfileError('');
                  }}
                >
                  Clear
                </button>
              </div>
              <p className="form-error">{profileError}</p>
            </form>
            <div className="subsection">
              <h3>Results</h3>
              <ul className="list compact">
                {profileResults.length ? (
                    profileResults.map((profile) => (
                      <li key={profile.id} className="list-item">
                        <div className="defense-header">
                          <strong>{profile.username}</strong>
                          <button
                            type="button"
                            className="ghost small"
                            onClick={() => loadProfile(profile.username)}
                            disabled={profileLoading}
                          >
                            View
                          </button>
                        </div>
                      <div className="defense-meta">
                        <span>{profile.publicBaseCount} public bases</span>
                        <span>{profile.publicDefenseCount} public attacks</span>
                        <span>{new Date(profile.createdAt).toLocaleDateString()}</span>
                      </div>
                    </li>
                  ))
                ) : (
                  <li>
                    {profileSearchTerm
                      ? profileLoading
                        ? 'Searching…'
                        : 'No profiles matched that search.'
                      : 'Type a username to search the community.'}
                  </li>
                )}
              </ul>
            </div>
            {profileDetail && (
              <div className="subsection">
                <div className="defense-header">
                  <h3>Profile: {profileDetail.profile.username}</h3>
                  <button type="button" className="ghost small" onClick={clearProfileDetail}>
                    Close
                  </button>
                </div>
                <div className="defense-meta">
                  <span>{profileDetail.profile.visibleBaseCount} visible bases</span>
                  <span>{profileDetail.profile.summary.count} attacks</span>
                  <span>{profileDetail.profile.summary.averageStars}★ avg</span>
                  <span>{profileDetail.profile.summary.averagePercent}% avg</span>
                </div>
                <ul className="list compact">
                  {profileDetail.bases.length ? (
                    profileDetail.bases.map((base) => (
                      <li key={base.id} className="list-item clickable" onClick={() => openProfileBaseDetail(base)}>
                        <div className="defense-header">
                          <div>
                            <strong>{base.title}</strong>{' '}
                            {base.isPrivate ? <span className="badge muted">Private</span> : null}
                          </div>
                          <span className="badge">{base.summary.count} attacks</span>
                        </div>
                        <div className="defense-meta">
                          <span>{base.summary.averageStars}★ avg</span>
                          <span>{base.summary.averagePercent}% avg</span>
                          <span>{formatTrophies(base.summary.averageTrophies)}</span>
                        </div>
                        <p className="muted">Click to open full details.</p>
                      </li>
                    ))
                  ) : (
                    <li className="muted">No public bases to show.</li>
                  )}
                </ul>
                {!profileDetail.profile.isOwner ? (
                  <p className="muted">Private bases stay hidden from other players.</p>
                ) : null}
              </div>
            )}
          </div>

          <section className="card" id="defense-log-card">
            <h2>Defense Log</h2>
            <p className="subtitle">Newest entries appear on top.</p>
            <ul id="defense-list" className="list">
              {defenses.length ? (
                defenses.map((defense) => {
                  const date = new Date(defense.createdAt);
                  const categoryName = categoryNameMap.get(defense.armyCategoryId) || '(No category)';
                  return (
                    <li key={defense.id} className="list-item">
                      <div className="defense-header">
                        <div>
                          <strong>{defense.baseTitle}</strong>
                          <span className="badge">{categoryName}</span>
                        </div>
                        <div>
                          <strong>{defense.stars}★</strong> • {defense.percent}% • {formatTrophies(defense.trophies)}
                        </div>
                      </div>
                      <div className="defense-meta">
                        <span>{date.toLocaleString()}</span>
                      </div>
                    </li>
                  );
                })
              ) : (
                <li>No defenses recorded yet.</li>
              )}
            </ul>
          </section>
        </section>

        <section id="forms-view" className={`forms-grid view-section ${view !== 'forms' ? 'hidden' : ''}`}>
          <div className="card">
            <h2>New Army Category</h2>
            <form id="category-form" className="form compact" onSubmit={handleCategorySubmit}>
              <label>
                Name
                <input type="text" name="name" required />
              </label>
              <button type="submit" className="primary">
                Add Category
              </button>
              <p className="form-error" data-for="category">
                {errors.category}
              </p>
            </form>
            <div className="subsection">
              <details>
                <summary><h3>Existing Categories</h3></summary>
                <ul className="list compact">
                  {categories.length ? (
                    categories.map((category) => (
                      <li key={category.id} className="list-item">
                        <div className="defense-header">
                          <span>{category.name}</span>
                          <div className="defense-meta">
                            <button
                              type="button"
                              className="ghost small"
                              onClick={() => handleDeleteCategory(category.id)}
                            >
                              Delete
                            </button>
                          </div>
                        </div>
                        <div className="defense-meta">
                          <span>{new Date(category.createdAt).toLocaleDateString()}</span>
                        </div>
                      </li>
                    ))
                  ) : (
                    <li>No categories yet.</li>
                  )}
                </ul>
              </details>
            </div>
          </div>
          <div className="card">
            <h2>New Base</h2>
            <form id="base-form" className="form compact" onSubmit={handleBaseSubmit}>
              <label>
                Title
                <input type="text" name="title" required />
              </label>
              <label>
                Description
                <textarea name="description" rows={2}></textarea>
              </label>
              <label>
                Planning Link
                <input type="url" name="url" placeholder="https://" />
              </label>
              <div className="input-group">
                <span className="input-label">Image Source</span>
                <div className="image-mode">
                  <label>
                    <input
                      type="radio"
                      name="imageMode"
                      value="upload"
                      checked={imageMode === 'upload'}
                      onChange={() => setImageMode('upload')}
                    />
                    Upload
                  </label>
                  <label>
                    <input
                      type="radio"
                      name="imageMode"
                      value="url"
                      checked={imageMode === 'url'}
                      onChange={() => setImageMode('url')}
                    />
                    URL
                  </label>
                </div>
                {imageMode === 'upload' ? (
                  <input type="file" name="imageFile" accept="image/*" />
                ) : (
                  <input type="url" name="imageUrl" placeholder="https://" required />
                )}
              </div>
              <label>
                <input type="checkbox" name="isPrivate" /> Make this base private
              </label>
              <button type="submit" className="primary">
                Add Base
              </button>
              <p className="form-error" data-for="base">
                {errors.base}
              </p>
            </form>
            <div className="subsection">
              <details>
                <summary><h3>Manage Bases</h3></summary>
                <ul className="list compact">
                  {bases.length ? (
                    bases.map((base) => (
                      <li key={base.id} className="list-item">
                        <div className="defense-header">
                          <div>
                            <strong>{base.title}</strong>{' '}
                            {base.isPrivate ? <span className="badge muted">Private</span> : null}
                          </div>
                          <div className="defense-meta">
                            <button
                              type="button"
                              className="ghost small"
                              onClick={() => startEditingBase(base.id)}
                            >
                              Edit
                            </button>
                            <button
                              type="button"
                              className="ghost small"
                              onClick={() => handleDeleteBase(base.id)}
                            >
                              Delete
                            </button>
                          </div>
                        </div>
                        <div className="defense-meta">
                          <span>{new Date(base.createdAt).toLocaleDateString()}</span>
                        </div>
                      </li>
                    ))
                  ) : (
                    <li>No bases yet.</li>
                  )}
                </ul>
              </details>
            </div>
            {baseBeingEdited && (
              <div className="subsection">
                <h3>Edit Base: {baseBeingEdited.title}</h3>
                <form
                  key={baseBeingEdited.id}
                  className="form compact"
                  onSubmit={handleBaseEditSubmit}
                >
                  <label>
                    Title
                    <input type="text" name="title" defaultValue={baseBeingEdited.title} required />
                  </label>
                  <label>
                    Description
                    <textarea name="description" rows={2} defaultValue={baseBeingEdited.description}></textarea>
                  </label>
                  <label>
                    Planning Link
                    <input type="url" name="url" placeholder="https://" defaultValue={baseBeingEdited.url} />
                  </label>
                  <label>
                    <input type="checkbox" name="isPrivate" defaultChecked={baseBeingEdited.isPrivate} /> Keep this base private
                  </label>
                  <div className="input-group">
                    <span className="input-label">Image Options</span>
                    <div className="image-mode">
                      <label>
                        <input
                          type="radio"
                          name="imageMode"
                          value="keep"
                          checked={editImageMode === 'keep'}
                          onChange={() => setEditImageMode('keep')}
                        />
                        Keep current
                      </label>
                      <label>
                        <input
                          type="radio"
                          name="imageMode"
                          value="upload"
                          checked={editImageMode === 'upload'}
                          onChange={() => setEditImageMode('upload')}
                        />
                        Upload new
                      </label>
                      <label>
                        <input
                          type="radio"
                          name="imageMode"
                          value="url"
                          checked={editImageMode === 'url'}
                          onChange={() => setEditImageMode('url')}
                        />
                        Use link
                      </label>
                      <label>
                        <input
                          type="radio"
                          name="imageMode"
                          value="remove"
                          checked={editImageMode === 'remove'}
                          onChange={() => setEditImageMode('remove')}
                        />
                        Remove image
                      </label>
                    </div>
                    {editImageMode === 'upload' ? <input type="file" name="imageFile" accept="image/*" /> : null}
                    {editImageMode === 'url' ? (
                      <input
                        type="url"
                        name="imageUrl"
                        placeholder="https://"
                        defaultValue={
                          baseBeingEdited.imageUrl && baseBeingEdited.imageUrl.startsWith('http')
                            ? baseBeingEdited.imageUrl
                            : ''
                        }
                      />
                    ) : null}
                  </div>
                  <div className="defense-meta">
                    <button type="submit" className="primary">
                      Save Changes
                    </button>
                    <button type="button" className="ghost" onClick={cancelEditingBase}>
                      Cancel
                    </button>
                  </div>
                  {editingBaseId === baseBeingEdited.id && errors.base ? (
                    <p className="form-error" data-for="base">
                      {errors.base}
                    </p>
                  ) : null}
                </form>
              </div>
            )}
          </div>
          <div className="card">
            <h2>Log Defense</h2>
            <form id="defense-form" className="form compact" onSubmit={handleDefenseSubmit}>
              <label>
                Base
                <select name="baseId" required defaultValue="">
                  <option value="" disabled>
                    {bases.length ? 'Select a base' : 'Add a base first'}
                  </option>
                  {bases.map((base) => (
                    <option key={base.id} value={base.id}>
                      {base.title}
                    </option>
                  ))}
                </select>
              </label>
              <label>
                Army Category
                <select name="armyCategoryId" defaultValue="">
                  <option value="">
                    {categories.length ? '(No category)' : 'Add an army category first'}
                  </option>
                  {categories.map((category) => (
                    <option key={category.id} value={category.id}>
                      {category.name}
                    </option>
                  ))}
                </select>
              </label>
              <label>
                Stars
                <input type="number" name="stars" min={0} max={3} step={1} required className="styled-number" />
              </label>
              <label>
                Destruction %
                <input type="number" name="percent" min={0} max={100} step={1} required className="styled-number" />
              </label>
              <label>
                Trophies ±
                <input
                  type="number"
                  name="trophies"
                  min={-200}
                  max={200}
                  step={1}
                  defaultValue={0}
                  required
                  className="styled-number"
                />
              </label>
              <button type="submit" className="primary">
                Record Defense
              </button>
              <p className="form-error" data-for="defense">
                {errors.defense}
              </p>
            </form>
            <div className="subsection">
              <details>
                <summary><h3>Manage Attacks</h3></summary>
                <ul className="list compact">
                {defenses.length ? (
                  defenses.slice(0, 10).map((defense) => {
                    const categoryName =
                      categoryNameMap.get(defense.armyCategoryId) || defense.categoryName || '(No category)';
                    return (
                      <li key={defense.id} className="list-item">
                        <div className="defense-header">
                          <div>
                            <strong>{defense.baseTitle}</strong>{' '}
                            <span className="badge">{categoryName}</span>
                          </div>
                          <div className="defense-meta">
                            <button
                              type="button"
                              className="ghost small"
                              onClick={() => startEditingDefense(defense.id)}
                            >
                              Edit
                            </button>
                            <button
                              type="button"
                              className="ghost small"
                              onClick={() => handleDeleteDefense(defense.id)}
                            >
                              Delete
                            </button>
                          </div>
                        </div>
                        <div className="defense-meta">
                          <span>{defense.stars}★</span>
                          <span>{defense.percent}%</span>
                          <span>{formatTrophies(defense.trophies)}</span>
                          <span>{new Date(defense.createdAt).toLocaleString()}</span>
                        </div>
                      </li>
                    );
                  })
                ) : (
                  <li>No attacks logged yet.</li>
                )}
              </ul>
              {defenses.length > 10 ? (
                <p className="muted">Showing the latest 10 entries.</p>
              ) : null}
              </details>
            </div>
            {defenseBeingEdited && (
              <div className="subsection">
                <h3>Edit Attack</h3>
                <form
                  key={defenseBeingEdited.id}
                  className="form compact"
                  onSubmit={handleDefenseEditSubmit}
                >
                  <label>
                    Base
                    <select name="baseId" required defaultValue={defenseBeingEdited.baseId}>
                      {bases.map((base) => (
                        <option key={base.id} value={base.id}>
                          {base.title}
                        </option>
                      ))}
                    </select>
                  </label>
                  <label>
                    Army Category
                    <select name="armyCategoryId" defaultValue={defenseBeingEdited.armyCategoryId || ''}>
                      <option value="">(No category)</option>
                      {categories.map((category) => (
                        <option key={category.id} value={category.id}>
                          {category.name}
                        </option>
                      ))}
                    </select>
                  </label>
                  <label>
                    Stars
                    <input
                      type="number"
                      name="stars"
                      min={0}
                      max={3}
                      step={1}
                      required
                      defaultValue={defenseBeingEdited.stars}
                      className="styled-number"
                    />
                  </label>
                  <label>
                    Destruction %
                    <input
                      type="number"
                      name="percent"
                      min={0}
                      max={100}
                      step={1}
                      required
                      defaultValue={defenseBeingEdited.percent}
                      className="styled-number"
                    />
                  </label>
                  <label>
                    Trophies ±
                    <input
                      type="number"
                      name="trophies"
                      min={-200}
                      max={200}
                      step={1}
                      required
                      defaultValue={defenseBeingEdited.trophies}
                      className="styled-number"
                    />
                  </label>
                  <div className="defense-meta">
                    <button type="submit" className="primary">
                      Save Attack
                    </button>
                    <button type="button" className="ghost" onClick={cancelEditingDefense}>
                      Cancel
                    </button>
                  </div>
                  {editingDefenseId === defenseBeingEdited.id && errors.defense ? (
                    <p className="form-error" data-for="defense">
                      {errors.defense}
                    </p>
                  ) : null}
                </form>
              </div>
            )}
          </div>
          <div className="card">
            <h2>Log Legend League Day Reset</h2>
            <form id="trophy-reset-form" className="form compact" onSubmit={handleTrophyResetSubmit}>
              <label>
                Base
                <select name="baseId" required defaultValue="">
                  <option value="" disabled>
                    {bases.length ? 'Select a base' : 'Add a base first'}
                  </option>
                  {bases.map((base) => (
                    <option key={base.id} value={base.id}>
                      {base.title}
                    </option>
                  ))}
                </select>
              </label>
              <label>
                Date
                <input type="date" name="date" required />
              </label>
              <label>
                Trophies
                <input type="number" name="trophiesAtStart" min={0} step={1} required className="styled-number" />
              </label>
              <label>
                Trophies Gained/Lost
                <input type="number" name="trophiesLost" step={1} required className="styled-number" />
              </label>
              <label>
                Number of Defenses
                <input type="number" name="numberOfDefenses" min={0} step={1} required className="styled-number" />
              </label>
              <button type="submit" className="primary">
                Record Reset
              </button>
              <p className="form-error" data-for="trophyReset">
                {errors.trophyReset}
              </p>
            </form>
            <div className="subsection">
              <details>
                <summary><h3>Manage Resets</h3></summary>
                <ul className="list compact">
                  {bases.flatMap((base) => base.trophyResets).length ? (
                    bases.flatMap((base) => base.trophyResets).slice(0, 10).map((reset) => (
                      <li key={reset.id} className="list-item">
                        <div className="defense-header">
                          <div>
                            <strong>{bases.find((b) => b.id === bases.find((b) => b.trophyResets.some((r) => r.id === reset.id))?.id)?.title}</strong>{' '}
                            <span className="badge">{new Date(reset.date).toLocaleDateString()}</span>
                          </div>
                          <div className="defense-meta">
                            <button
                              type="button"
                              className="ghost small"
                              onClick={() => startEditingTrophyReset(reset.id)}
                            >
                              Edit
                            </button>
                            <button
                              type="button"
                              className="ghost small"
                              onClick={() => handleDeleteTrophyReset(reset.id)}
                            >
                              Delete
                            </button>
                          </div>
                        </div>
                        <div className="defense-meta">
                          <span>{reset.trophiesAtStart} trophies</span>
                          <span>{formatTrophies(reset.trophiesLost)}</span>
                          <span>{reset.numberOfDefenses} defenses</span>
                        </div>
                      </li>
                    ))
                  ) : (
                    <li>No resets logged yet.</li>
                  )}
                </ul>
              </details>
            </div>
            {editingTrophyResetId && trophyResetBeingEdited && (
              <div className="subsection">
                <h3>Edit Reset</h3>
                <form
                  key={editingTrophyResetId}
                  className="form compact"
                  onSubmit={handleTrophyResetEditSubmit}
                >
                  <label>
                    Base
                    <select name="baseId" required defaultValue={bases.find(b => b.trophyResets.some(r => r.id === editingTrophyResetId))?.id}>
                      {bases.map((base) => (
                        <option key={base.id} value={base.id}>
                          {base.title}
                        </option>
                      ))}
                    </select>
                  </label>
                  <label>
                    Date
                    <input type="date" name="date" required defaultValue={new Date(trophyResetBeingEdited.date).toISOString().split('T')[0]} />
                  </label>
                  <label>
                    Trophies
                    <input type="number" name="trophiesAtStart" min={0} step={1} required className="styled-number" defaultValue={trophyResetBeingEdited.trophiesAtStart} />
                  </label>
                  <label>
                    Trophies Gained/Lost
                    <input type="number" name="trophiesLost" step={1} required className="styled-number" defaultValue={trophyResetBeingEdited.trophiesLost} />
                  </label>
                  <label>
                    Number of Defenses
                    <input type="number" name="numberOfDefenses" min={0} step={1} required className="styled-number" defaultValue={trophyResetBeingEdited.numberOfDefenses} />
                  </label>
                  <div className="defense-meta">
                    <button type="submit" className="primary">
                      Save Reset
                    </button>
                    <button type="button" className="ghost" onClick={cancelEditingTrophyReset}>
                      Cancel
                    </button>
                  </div>
                  <p className="form-error">{errors.trophyReset}</p>
                </form>
              </div>
            )}
          </div>
        </section>

        <section id="base-detail-view" className={`view-section ${view !== 'baseDetail' ? 'hidden' : ''}`}>
          <div className="card">
            <div className="detail-header">
              <button className="ghost" type="button" onClick={() => setView('dashboard')}>
                Back
              </button>
              <span id="base-detail-created" className="detail-created">
                {baseDetailMeta ? `Created ${new Date(baseDetailMeta.createdAt).toLocaleString()}` : ''}
              </span>
            </div>
            <h2 id="base-detail-title">
              {baseDetailMeta?.title}{' '}
              {baseDetailMeta?.isPrivate ? <span className="badge muted">Private</span> : null}
            </h2>
            <p id="base-detail-description" className={baseDetailMeta?.description ? '' : 'muted'}>
              {baseDetailMeta?.description || 'No description yet.'}
            </p>
            <div id="base-detail-links" className={`detail-links ${baseDetailMeta?.url ? '' : 'hidden'}`}>
              {baseDetailMeta?.url && (
                <a href={baseDetailMeta.url} target="_blank" rel="noopener noreferrer">
                  Open planning link
                </a>
              )}
            </div>
            <div
              id="base-detail-image-wrapper"
              className={`detail-image ${baseDetailMeta?.imageUrl ? '' : 'hidden'}`}
            >
              {baseDetailMeta?.imageUrl && (
                // eslint-disable-next-line @next/next/no-img-element
                <img src={baseDetailMeta.imageUrl} alt={`Preview of ${baseDetailMeta.title}`} />
              )}
            </div>
          </div>
          <div className="card">
            <h3>Base Averages</h3>
            <div id="base-detail-stats" className="stat">
              {baseDetail && baseDetail.count ? (
                <>
                  <strong>{baseDetail.averageStars}★</strong> average •{' '}
                  <strong>{baseDetail.averagePercent}%</strong> destruction
                  <br />
                  <span className="badge">{formatTrophies(baseDetail.averageTrophies)} avg</span>{' '}
                  <span className="badge">{baseDetail.count} defenses</span>
                </>
              ) : (
                'No defenses logged yet.'
              )}
            </div>
          </div>
          <div className="card">
            <details open>
              <summary><h3>Army Categories vs This Base</h3></summary>
              <ul id="base-detail-categories" className="list">
              {baseDetail && baseDetail.categories.length ? (
                baseDetail.categories.map((category) => (
                  <li
                    key={category.categoryId}
                    className="list-item clickable"
                    onClick={() => openCategoryDetail(category.categoryId)}
                  >
                    <div className="defense-header">
                      <strong>{category.name}</strong>
                      <span className="badge">{category.count} attacks</span>
                    </div>
                    <div className="defense-meta">
                      <span>{category.averageStars}★ avg</span>
                      <span>{category.averagePercent}% avg</span>
                      <span>{formatTrophies(category.averageTrophies)} avg</span>
                    </div>
                  </li>
                ))
              ) : (
                <li>No army categories have attacked this base yet.</li>
              )}
            </ul>
            </details>
          </div>
          <div className="card">
            <details open>
              <summary><h3>Recent Resets</h3></summary>
              <ul className="list compact">
                {baseDetailMeta?.trophyResets?.length ? (
                  baseDetailMeta.trophyResets.map((reset) => (
                    <li key={reset.id} className="list-item">
                      <div className="defense-header">
                        <span>{new Date(reset.date).toLocaleDateString()}</span>
                        <div className="defense-meta">
                          <button
                            type="button"
                            className="ghost small"
                            onClick={() => startEditingTrophyReset(reset.id)}
                          >
                            Edit
                          </button>
                          <button
                            type="button"
                            className="ghost small"
                            onClick={() => handleDeleteTrophyReset(reset.id)}
                          >
                            Delete
                          </button>
                        </div>
                      </div>
                      <div className="defense-meta">
                        <span>{reset.trophiesAtStart} trophies</span>
                        <span>{formatTrophies(reset.trophiesLost)}</span>
                        <span>{reset.numberOfDefenses} defenses</span>
                      </div>
                    </li>
                  ))
                ) : (
                  <li>No resets logged yet.</li>
                )}
              </ul>
            </details>
          </div>
          <div className="card">
            <details open>
              <summary><h3>Defenses</h3></summary>
              <ul id="base-detail-defenses" className="list">
              {defenses.filter((defense) => defense.baseId === selectedBaseId).length ? (
                defenses
                  .filter((defense) => defense.baseId === selectedBaseId)
                  .map((defense) => {
                    const date = new Date(defense.createdAt);
                    const categoryName = categoryNameMap.get(defense.armyCategoryId) || '(No category)';
                    return (
                      <li key={defense.id} className="list-item">
                        <div className="defense-header">
                          <strong>{categoryName}</strong>
                          <div>
                            <strong>{defense.stars}★</strong> • {defense.percent}% • {formatTrophies(defense.trophies)}
                          </div>
                        </div>
                        <div className="defense-meta">
                          <span>{date.toLocaleString()}</span>
                        </div>
                      </li>
                    );
                  })
              ) : (
                <li>No defenses recorded for this base yet.</li>
              )}
            </ul>
            </details>
          </div>
        </section>

        <section
          id="profile-base-detail-view"
          className={`view-section ${view !== 'profileBaseDetail' ? 'hidden' : ''}`}
        >
          {profileSelectedBase ? (
            <>
              <div className="card">
                <div className="detail-header">
                  <button className="ghost" type="button" onClick={closeProfileBaseDetail}>
                    Back
                  </button>
                  <span className="detail-created">
                    {`Created ${new Date(profileSelectedBase.createdAt).toLocaleString()}`}
                  </span>
                </div>
                <h2>
                  {profileSelectedBase.title}{' '}
                  {profileSelectedBase.isPrivate ? <span className="badge muted">Private</span> : null}
                </h2>
                <p className={profileSelectedBase.description ? '' : 'muted'}>
                  {profileSelectedBase.description || 'No description yet.'}
                </p>
                <div className="defense-meta">
                  <span>
                    Shared by <strong>{profileDetail?.profile.username || 'Unknown player'}</strong>
                  </span>
                </div>
                <div className={`detail-links ${profileSelectedBase.url ? '' : 'hidden'}`}>
                  {profileSelectedBase.url && (
                    <a href={profileSelectedBase.url} target="_blank" rel="noopener noreferrer">
                      Planning Link
                    </a>
                  )}
                </div>
                <div className={`detail-image ${profileSelectedBase.imageUrl ? '' : 'hidden'}`}>
                  {profileSelectedBase.imageUrl && (
                    // eslint-disable-next-line @next/next/no-img-element
                    <img
                      src={profileSelectedBase.imageUrl}
                      alt={`Preview of ${profileSelectedBase.title}`}
                    />
                  )}
                </div>
              </div>
              <div className="card">
                <h3>Base Averages</h3>
                <div className="stat">
                  {profileSelectedBase.summary.count ? (
                    <>
                      <strong>{profileSelectedBase.summary.averageStars}★</strong> average •{' '}
                      <strong>{profileSelectedBase.summary.averagePercent}%</strong> destruction
                      <br />
                      <span className="badge">
                        {formatTrophies(profileSelectedBase.summary.averageTrophies)}
                      </span>{' '}
                      <span className="badge">{profileSelectedBase.summary.count} defenses</span>
                    </>
                  ) : (
                    'No defenses logged yet.'
                  )}
                </div>
              </div>
              <div className="card">
                <h3>Army Categories vs This Base</h3>
                <ul className="list">
                  {profileSelectedBaseCategories.length ? (
                    profileSelectedBaseCategories.map((category) => (
                      <li key={category.armyCategoryId} className="list-item">
                        <div className="defense-header">
                          <strong>{category.name}</strong>
                          <span className="badge">{category.count} attacks</span>
                        </div>
                        <div className="defense-meta">
                          <span>{category.averageStars}★ avg</span>
                          <span>{category.averagePercent}% avg</span>
                          <span>{formatTrophies(category.averageTrophies)} avg</span>
                        </div>
                      </li>
                    ))
                  ) : (
                    <li>No attacks recorded for this base yet.</li>
                  )}
                </ul>
              </div>
              <div className="card">
                <details open>
                  <summary><h3>Recent Resets</h3></summary>
                  <ul className="list compact">
                    {profileSelectedBase.trophyResets.length ? (
                      profileSelectedBase.trophyResets.map((reset) => (
                        <li key={reset.id} className="list-item">
                          <div className="defense-header">
                            <span>{new Date(reset.date).toLocaleDateString()}</span>
                            <div className="defense-meta">
                              <span>{reset.trophiesAtStart} trophies at start</span>
                              <span>{formatTrophies(reset.trophiesLost)} lost</span>
                              <span>{reset.numberOfDefenses} defenses</span>
                            </div>
                          </div>
                        </li>
                      ))
                    ) : (
                      <li>No resets logged yet.</li>
                    )}
                  </ul>
                </details>
              </div>
              <div className="card">
                <details>
                  <summary><h3>Defenses</h3></summary>
                  <ul className="list">
                    {profileSelectedBase.defenses.length ? (
                      profileSelectedBase.defenses.map((defense) => (
                        <li key={defense.id} className="list-item">
                          <div className="defense-header">
                            <strong>{defense.armyCategoryName || '(No category)'}</strong>
                            <div>
                              <strong>{defense.stars}★</strong> • {defense.percent}% • {formatTrophies(defense.trophies)}
                            </div>
                          </div>
                          <div className="defense-meta">
                            <span>{new Date(defense.createdAt).toLocaleString()}</span>
                          </div>
                        </li>
                      ))
                    ) : (
                      <li>No defenses recorded yet.</li>
                    )}
                  </ul>
                </details>
              </div>
            </>
          ) : (
            <div className="card">
              <div className="detail-header">
                <button className="ghost" type="button" onClick={closeProfileBaseDetail}>
                  Back
                </button>
              </div>
              <p className="muted">Select a base from a profile search to view its details.</p>
            </div>
          )}
        </section>

        <section id="category-detail-view" className={`view-section ${view !== 'categoryDetail' ? 'hidden' : ''}`}>
          <div className="card">
            <div className="detail-header">
              <button className="ghost" type="button" onClick={() => setView('dashboard')}>
                Back
              </button>
            </div>
            <h2 id="category-detail-title">{categoryDetail?.name}</h2>
            <p id="category-detail-description" className="muted">
              Average performance of this army across your bases.
            </p>
          </div>
          <div className="card">
            <h3>Category Averages</h3>
            <div id="category-detail-stats" className="stat">
              {categoryDetail && categoryDetail.count ? (
                <>
                  <strong>{categoryDetail.averageStars}★</strong> average •{' '}
                  <strong>{categoryDetail.averagePercent}%</strong> destruction
                  <br />
                  <span className="badge">{formatTrophies(categoryDetail.averageTrophies)} avg</span>{' '}
                  <span className="badge">{categoryDetail.count} attacks</span>
                </>
              ) : (
                'No defenses logged yet.'
              )}
            </div>
          </div>
          <div className="card">
            <h3>Performance by Base</h3>
            <ul id="category-detail-bases" className="list">
              {categoryDetail && categoryDetail.bases.length ? (
                categoryDetail.bases.map((base) => (
                  <li
                    key={base.baseId}
                    className="list-item clickable"
                    onClick={() => openBaseDetail(base.baseId)}
                  >
                    <div className="defense-header">
                      <strong>{base.title}</strong>
                      <span className="badge">{base.count} defenses</span>
                    </div>
                    <div className="defense-meta">
                      <span>{base.averageStars}★ avg</span>
                      <span>{base.averagePercent}% avg</span>
                      <span>{formatTrophies(base.averageTrophies)} avg</span>
                    </div>
                  </li>
                ))
              ) : (
                <li>This army has not attacked any bases yet.</li>
              )}
            </ul>
          </div>
          <div className="card">
            <h3>Defenses</h3>
            <ul id="category-detail-defenses" className="list">
              {defenses.filter((defense) => defense.armyCategoryId === selectedCategoryId).length ? (
                defenses
                  .filter((defense) => defense.armyCategoryId === selectedCategoryId)
                  .map((defense) => {
                    const date = new Date(defense.createdAt);
                    return (
                      <li key={defense.id} className="list-item">
                        <div className="defense-header">
                          <strong>{defense.baseTitle}</strong>
                          <div>
                            <strong>{defense.stars}★</strong> • {defense.percent}% • {formatTrophies(defense.trophies)}
                          </div>
                        </div>
                        <div className="defense-meta">
                          <span>{date.toLocaleString()}</span>
                        </div>
                      </li>
                    );
                  })
              ) : (
                <li>No logged defenses for this army yet.</li>
              )}
            </ul>
          </div>
        </section>
      </section>
    </main>
  );
}
