/**
 * @copyright 2026 NHCarrigan
 * @license Naomi's Public License
 * @author Naomi Carrigan
 */

import { Component, OnInit, inject, signal, computed } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { RouterLink } from '@angular/router';
import { BooksService } from '../../services/books.service';
import { AuthService } from '../../services/auth.service';
import { CommentsService } from '../../services/comments.service';
import { SanitizeService } from '../../services/sanitize.service';
import { SuggestionService } from '../../services/suggestion.service';
import { PaginationComponent } from '../shared/pagination.component';
import { LikeButtonComponent } from '../shared/like-button.component';
import { Book, BookStatus, CreateBookDto, UpdateBookDto, Comment, SuggestionEntity, Link } from '@library/shared-types';

@Component({
  selector: 'app-books-list',
  standalone: true,
  imports: [CommonModule, FormsModule, RouterLink, PaginationComponent, LikeButtonComponent],
  template: `
    <div class="container">
      <div class="page-hero">
        <img src="/assets/avatars/books-avatar.jpg" alt="Books avatar" class="page-avatar" />
      </div>

      <div class="header-section">
        <h2>My Book Collection</h2>
        @if (authService.isAdmin()) {
          <button (click)="toggleAddForm()" class="btn btn-primary">
            {{ showAddForm() ? 'Cancel' : 'Add Book' }}
          </button>
        } @else if (authService.isAuthenticated() && !authService.user()?.isBanned) {
          <button (click)="toggleSuggestForm()" class="btn btn-primary">
            {{ showSuggestForm() ? 'Cancel' : 'Suggest a Book' }}
          </button>
        }
      </div>

      @if (showAddForm() && authService.isAdmin()) {
        <form (ngSubmit)="addBook()" class="add-form">
          <h3>Add New Book</h3>
          <div class="form-group">
            <label for="title">Title</label>
            <input
              type="text"
              id="title"
              [(ngModel)]="newBook.title"
              name="title"
              required
              placeholder="Enter book title"
            >
          </div>

          <div class="form-group">
            <label for="author">Author</label>
            <input
              type="text"
              id="author"
              [(ngModel)]="newBook.author"
              name="author"
              required
              placeholder="Enter author name"
            >
          </div>

          <div class="form-group">
            <label for="isbn">ISBN</label>
            <input
              type="text"
              id="isbn"
              [(ngModel)]="newBook.isbn"
              name="isbn"
              placeholder="ISBN (optional)"
            >
          </div>

          <div class="form-group">
            <label for="status">Status</label>
            <select id="status" [(ngModel)]="newBook.status" name="status" required>
              <option [value]="BookStatus.reading">Currently Reading</option>
              <option [value]="BookStatus.finished">Finished</option>
              <option [value]="BookStatus.toRead">To Read</option>
              <option [value]="BookStatus.retired">Retired</option>
            </select>
          </div>

          <div class="form-group">
            <label for="dateStarted">Date Started</label>
            <input
              type="date"
              id="dateStarted"
              [(ngModel)]="newBook.dateStarted"
              name="dateStarted"
            >
          </div>

          <div class="form-group">
            <label for="dateFinished">Date Finished</label>
            <input
              type="date"
              id="dateFinished"
              [(ngModel)]="newBook.dateFinished"
              name="dateFinished"
            >
          </div>

          <div class="form-group">
            <label for="rating">Rating (1-10)</label>
            <input
              type="number"
              id="rating"
              [(ngModel)]="newBook.rating"
              name="rating"
              min="1"
              max="10"
            >
          </div>

          <div class="form-row">
            <div class="form-group">
              <label for="timeHours">Time Spent (Hours)</label>
              <input
                type="number"
                id="timeHours"
                [(ngModel)]="newBookTimeHours"
                name="timeHours"
                min="0"
                placeholder="0"
                (ngModelChange)="updateNewBookTimeSpent()"
              >
            </div>
            <div class="form-group">
              <label for="timeMinutes">Time Spent (Minutes)</label>
              <input
                type="number"
                id="timeMinutes"
                [(ngModel)]="newBookTimeMinutes"
                name="timeMinutes"
                min="0"
                max="59"
                placeholder="0"
                (ngModelChange)="updateNewBookTimeSpent()"
              >
            </div>
          </div>

          <div class="form-group">
            <label for="notes">Notes</label>
            <textarea
              id="notes"
              [(ngModel)]="newBook.notes"
              name="notes"
              rows="3"
              placeholder="Your thoughts about the book..."
            ></textarea>
          </div>

          <div class="form-group">
            <label for="series">Series (optional)</label>
            <input
              type="text"
              id="series"
              [(ngModel)]="newBook.series"
              name="series"
              placeholder="e.g., Harry Potter"
            >
          </div>

          <div class="form-group">
            <label for="seriesOrder">Series Order (optional)</label>
            <input
              type="number"
              id="seriesOrder"
              [(ngModel)]="newBook.seriesOrder"
              name="seriesOrder"
              min="1"
              placeholder="Order in series"
            >
          </div>

          <div class="form-group">
            <label for="coverImage">Cover Image (max 500KB)</label>
            <input
              type="file"
              id="coverImage"
              name="coverImage"
              accept="image/*"
              (change)="onImageSelected($event, 'new')"
            >
            @if (newBookImagePreview()) {
              <div class="image-preview">
                <img [src]="newBookImagePreview()" alt="Cover preview">
                <button type="button" (click)="clearImage('new')" class="btn btn-danger btn-sm">Remove</button>
              </div>
            }
            @if (imageError()) {
              <span class="error-text">{{ imageError() }}</span>
            }
          </div>

          <div class="form-group">
            <div class="tags-input-container" aria-label="Tags">
              @for (tag of newBook.tags; track tag; let i = $index) {
                <span class="tag">
                  {{ tag }}
                  <button type="button" (click)="removeTag(i, 'new')" class="tag-remove">×</button>
                </span>
              }
              <input
                type="text"
                [(ngModel)]="newTagInput"
                name="newTagInput"
                placeholder="Add a tag and press Enter"
                (keydown.enter)="addTag('new'); $event.preventDefault()"
              >
            </div>
          </div>

          <div class="form-group" aria-label="External Links">
            <div class="links-list">
              @for (link of newBook.links; track link.url; let i = $index) {
                <div class="link-item">
                  <span>{{ link.title }}: {{ link.url }}</span>
                  <button type="button" (click)="removeLink(i, 'new')" class="btn btn-danger btn-sm">×</button>
                </div>
              }
            </div>
            <div class="link-add-form">
              <input
                type="text"
                [(ngModel)]="newLinkTitle"
                name="newLinkTitle"
                placeholder="Link title (e.g., Goodreads)"
              >
              <input
                type="url"
                [(ngModel)]="newLinkUrl"
                name="newLinkUrl"
                placeholder="https://..."
              >
              <button type="button" (click)="addLink('new')" class="btn btn-secondary btn-sm">Add Link</button>
            </div>
          </div>

          <div class="form-actions">
            <button type="submit" class="btn btn-primary">Add Book</button>
            <button type="button" (click)="toggleAddForm()" class="btn btn-secondary">Cancel</button>
          </div>
        </form>
      }

      @if (editingBook() && authService.isAdmin()) {
        <form (ngSubmit)="saveEdit()" class="add-form">
          <h3>Edit Book</h3>
          <div class="form-group">
            <label for="edit-title">Title</label>
            <input
              type="text"
              id="edit-title"
              [(ngModel)]="editBook.title"
              name="title"
              required
              placeholder="Enter book title"
            >
          </div>

          <div class="form-group">
            <label for="edit-author">Author</label>
            <input
              type="text"
              id="edit-author"
              [(ngModel)]="editBook.author"
              name="author"
              required
              placeholder="Enter author name"
            >
          </div>

          <div class="form-group">
            <label for="edit-isbn">ISBN</label>
            <input
              type="text"
              id="edit-isbn"
              [(ngModel)]="editBook.isbn"
              name="isbn"
              placeholder="ISBN (optional)"
            >
          </div>

          <div class="form-group">
            <label for="edit-status">Status</label>
            <select id="edit-status" [(ngModel)]="editBook.status" name="status" required>
              <option [value]="BookStatus.reading">Currently Reading</option>
              <option [value]="BookStatus.finished">Finished</option>
              <option [value]="BookStatus.toRead">To Read</option>
              <option [value]="BookStatus.retired">Retired</option>
            </select>
          </div>

          <div class="form-group">
            <label for="edit-dateStarted">Date Started</label>
            <input
              type="date"
              id="edit-dateStarted"
              [(ngModel)]="editBook.dateStarted"
              name="dateStarted"
            >
          </div>

          <div class="form-group">
            <label for="edit-dateFinished">Date Finished</label>
            <input
              type="date"
              id="edit-dateFinished"
              [(ngModel)]="editBook.dateFinished"
              name="dateFinished"
            >
          </div>

          <div class="form-group">
            <label for="edit-rating">Rating (1-10)</label>
            <input
              type="number"
              id="edit-rating"
              [(ngModel)]="editBook.rating"
              name="rating"
              min="1"
              max="10"
            >
          </div>

          <div class="form-row">
            <div class="form-group">
              <label for="edit-timeHours">Time Spent (Hours)</label>
              <input
                type="number"
                id="edit-timeHours"
                [(ngModel)]="editBookTimeHours"
                name="timeHours"
                min="0"
                placeholder="0"
                (ngModelChange)="updateEditBookTimeSpent()"
              >
            </div>
            <div class="form-group">
              <label for="edit-timeMinutes">Time Spent (Minutes)</label>
              <input
                type="number"
                id="edit-timeMinutes"
                [(ngModel)]="editBookTimeMinutes"
                name="timeMinutes"
                min="0"
                max="59"
                placeholder="0"
                (ngModelChange)="updateEditBookTimeSpent()"
              >
            </div>
          </div>

          <div class="form-group">
            <label for="edit-notes">Notes</label>
            <textarea
              id="edit-notes"
              [(ngModel)]="editBook.notes"
              name="notes"
              rows="3"
              placeholder="Your thoughts about the book..."
            ></textarea>
          </div>

          <div class="form-group">
            <label for="edit-series">Series (optional)</label>
            <input
              type="text"
              id="edit-series"
              [(ngModel)]="editBook.series"
              name="series"
              placeholder="e.g., Harry Potter"
            >
          </div>

          <div class="form-group">
            <label for="edit-seriesOrder">Series Order (optional)</label>
            <input
              type="number"
              id="edit-seriesOrder"
              [(ngModel)]="editBook.seriesOrder"
              name="seriesOrder"
              min="1"
              placeholder="Order in series"
            >
          </div>

          <div class="form-group">
            <label for="edit-coverImage">Cover Image (max 500KB)</label>
            <input
              type="file"
              id="edit-coverImage"
              name="coverImage"
              accept="image/*"
              (change)="onImageSelected($event, 'edit')"
            >
            @if (editBookImagePreview()) {
              <div class="image-preview">
                <img [src]="editBookImagePreview()" alt="Cover preview">
                <button type="button" (click)="clearImage('edit')" class="btn btn-danger btn-sm">Remove</button>
              </div>
            }
            @if (imageError()) {
              <span class="error-text">{{ imageError() }}</span>
            }
          </div>

          <div class="form-group">
            <div class="tags-input-container" aria-label="Tags">
              @for (tag of editBook.tags; track tag; let i = $index) {
                <span class="tag">
                  {{ tag }}
                  <button type="button" (click)="removeTag(i, 'edit')" class="tag-remove">×</button>
                </span>
              }
              <input
                type="text"
                [(ngModel)]="editTagInput"
                name="editTagInput"
                placeholder="Add a tag and press Enter"
                (keydown.enter)="addTag('edit'); $event.preventDefault()"
              >
            </div>
          </div>

          <div class="form-group" aria-label="External Links">
            <div class="links-list">
              @for (link of editBook.links; track link.url; let i = $index) {
                <div class="link-item">
                  <span>{{ link.title }}: {{ link.url }}</span>
                  <button type="button" (click)="removeLink(i, 'edit')" class="btn btn-danger btn-sm">×</button>
                </div>
              }
            </div>
            <div class="link-add-form">
              <input
                type="text"
                [(ngModel)]="editLinkTitle"
                name="editLinkTitle"
                placeholder="Link title (e.g., Goodreads)"
              >
              <input
                type="url"
                [(ngModel)]="editLinkUrl"
                name="editLinkUrl"
                placeholder="https://..."
              >
              <button type="button" (click)="addLink('edit')" class="btn btn-secondary btn-sm">Add Link</button>
            </div>
          </div>

          <div class="form-actions">
            <button type="submit" class="btn btn-primary">Save Changes</button>
            <button type="button" (click)="cancelEdit()" class="btn btn-secondary">Cancel</button>
          </div>
        </form>
      }

      @if (showSuggestForm() && !authService.isAdmin() && authService.isAuthenticated()) {
        <form (ngSubmit)="submitSuggestion()" class="add-form suggest-form">
          <h3>Suggest a Book</h3>
          <p class="suggest-note">Your suggestion will be reviewed by Naomi. If accepted, it will be added to the reading list!</p>
          <div class="form-group">
            <label for="suggest-title">Title</label>
            <input
              type="text"
              id="suggest-title"
              [(ngModel)]="suggestedBook.title"
              name="title"
              required
              placeholder="Enter book title"
            >
          </div>

          <div class="form-group">
            <label for="suggest-author">Author</label>
            <input
              type="text"
              id="suggest-author"
              [(ngModel)]="suggestedBook.author"
              name="author"
              required
              placeholder="Enter author name"
            >
          </div>

          <div class="form-group">
            <label for="suggest-isbn">ISBN (optional)</label>
            <input
              type="text"
              id="suggest-isbn"
              [(ngModel)]="suggestedBook.isbn"
              name="isbn"
              placeholder="ISBN (optional)"
            >
          </div>

          <div class="form-group">
            <label for="suggest-notes">Notes (why should Naomi read this?)</label>
            <textarea
              id="suggest-notes"
              [(ngModel)]="suggestedBook.notes"
              name="notes"
              rows="3"
              placeholder="Tell Naomi why this book is worth reading..."
            ></textarea>
          </div>

          <div class="form-group">
            <label for="suggest-coverImage">Cover Image (max 500KB)</label>
            <input
              type="file"
              id="suggest-coverImage"
              name="coverImage"
              accept="image/*"
              (change)="onImageSelected($event, 'suggest')"
            >
            @if (suggestBookImagePreview()) {
              <div class="image-preview">
                <img [src]="suggestBookImagePreview()" alt="Cover preview">
                <button type="button" (click)="clearImage('suggest')" class="btn btn-danger btn-sm">Remove</button>
              </div>
            }
            @if (imageError()) {
              <span class="error-text">{{ imageError() }}</span>
            }
          </div>

          <div class="form-actions">
            <button type="submit" class="btn btn-primary">Submit Suggestion</button>
            <button type="button" (click)="toggleSuggestForm()" class="btn btn-secondary">Cancel</button>
          </div>
        </form>
      }

      <div class="search-section">
        <input
          type="text"
          [(ngModel)]="searchQuery"
          (ngModelChange)="onSearchChange()"
          placeholder="Search by title, author, ISBN, or notes..."
          class="search-input"
        >
        <button
          (click)="toggleFilters()"
          class="btn btn-secondary"
          [class.active]="showFilters()"
        >
          <span>🔧 Advanced Filters</span>
          @if (selectedTags().length > 0) {
            <span class="filter-badge">{{ selectedTags().length }}</span>
          }
        </button>
      </div>

      @if (showFilters()) {
        <div class="advanced-filters">
          <div class="filter-group">
            <div class="tags-filter" aria-label="Filter by Tags">
              @for (tag of allTags(); track tag) {
                <label class="tag-checkbox">
                  <input
                    type="checkbox"
                    [checked]="selectedTags().includes(tag)"
                    (change)="toggleTag(tag)"
                  >
                  <span class="tag-label">{{ tag }}</span>
                </label>
              }
              @empty {
                <p class="no-tags">No tags available</p>
              }
            </div>
            @if (selectedTags().length > 0) {
              <button (click)="clearTags()" class="btn btn-sm btn-secondary clear-tags">
                Clear All Tags
              </button>
            }
          </div>
        </div>
      }

      <div class="filters">
        <button
          (click)="setFilter('all')"
          [class.active]="statusFilter() === 'all'"
          class="filter-btn"
        >
          All ({{ books().length }})
        </button>
        <button
          (click)="setFilter(BookStatus.reading)"
          [class.active]="statusFilter() === BookStatus.reading"
          class="filter-btn"
        >
          Reading ({{ readingCount() }})
        </button>
        <button
          (click)="setFilter(BookStatus.finished)"
          [class.active]="statusFilter() === BookStatus.finished"
          class="filter-btn"
        >
          Finished ({{ finishedCount() }})
        </button>
        <button
          (click)="setFilter(BookStatus.toRead)"
          [class.active]="statusFilter() === BookStatus.toRead"
          class="filter-btn"
        >
          To Read ({{ toReadCount() }})
        </button>
        <button
          (click)="setFilter(BookStatus.retired)"
          [class.active]="statusFilter() === BookStatus.retired"
          class="filter-btn"
        >
          Retired ({{ retiredCount() }})
        </button>
      </div>

      @if (loading()) {
        <div class="loading">Loading books...</div>
      } @else if (filteredBooks().length === 0) {
        <div class="empty-state">
          <p>No books found in this category.</p>
        </div>
      } @else {
        <app-pagination
          [currentPage]="currentPage()"
          [pageSize]="pageSize()"
          [totalItems]="totalFilteredBooks()"
          (pageChange)="onPageChange($event)"
          (pageSizeChange)="onPageSizeChange($event)"
        ></app-pagination>

        <div class="books-grid">
          @for (book of paginatedBooks(); track book.id) {
            <div class="book-card" [class.finished]="book.status === BookStatus.finished">
              <a [routerLink]="['/books', book.id]" class="card-link">
                <img [src]="book.coverImage || '/assets/default-cover.jpg'" [alt]="book.title" class="book-cover">

                <div class="book-info">
                  <h3>{{ book.title }}</h3>
                  <p class="author">by {{ book.author }}</p>

                  <span class="status status-{{ book.status }}">
                    {{ getStatusLabel(book.status) }}
                  </span>

                  @if (book.rating) {
                    <div class="rating">
                      @for (star of [1,2,3,4,5,6,7,8,9,10]; track star) {
                        <span [class.filled]="star <= book.rating!">★</span>
                      }
                    </div>
                  }
                </div>
              </a>

              <div class="card-actions">
                <app-like-button
                  entityType="book"
                  [entityId]="book.id"
                ></app-like-button>

                @if (authService.isAdmin()) {
                  <div class="admin-actions">
                    <button (click)="startEdit(book)" class="btn btn-secondary btn-sm">
                      Edit
                    </button>
                    <button (click)="deleteBook(book)" class="btn btn-danger btn-sm">
                      Delete
                    </button>
                  </div>
                }
              </div>
            </div>
          }
        </div>

        <app-pagination
          [currentPage]="currentPage()"
          [pageSize]="pageSize()"
          [totalItems]="totalFilteredBooks()"
          (pageChange)="onPageChange($event)"
          (pageSizeChange)="onPageSizeChange($event)"
        ></app-pagination>
      }
    </div>
  `,
  styles: [`
    .container {
      max-width: 1200px;
      margin: 0 auto;
      padding: 2rem;
    }

    .page-hero {
      text-align: center;
      margin-bottom: 2rem;
    }

    .page-avatar {
      width: 120px;
      height: 120px;
      border-radius: 50%;
      object-fit: cover;
      border: 3px solid #8b6f47;
      box-shadow: 0 4px 12px rgba(139, 111, 71, 0.3);
      transition: all 0.3s;
    }

    .page-avatar:hover {
      transform: scale(1.05);
      box-shadow: 0 8px 16px rgba(139, 111, 71, 0.5);
    }

    .header-section {
      display: flex;
      justify-content: space-between;
      align-items: center;
      margin-bottom: 2rem;
    }

    h2 {
      margin: 0;
    }

    .add-form {
      background: rgba(255, 255, 255, 0.95);
      padding: 1.5rem;
      border-radius: 8px;
      margin-bottom: 2rem;
      border: 2px solid var(--witch-lavender);
      backdrop-filter: blur(10px);
    }

    .suggest-form {
      border: 2px solid #8b6f47;
      background: #faf8f5;
    }

    .suggest-note {
      color: #666;
      font-size: 0.9rem;
      margin-bottom: 1rem;
      font-style: italic;
    }

    .form-row {
      display: grid;
      grid-template-columns: 1fr 1fr;
      gap: 1rem;
      margin-bottom: 1rem;
    }

    .form-group {
      margin-bottom: 1rem;
    }

    .form-group label {
      display: block;
      margin-bottom: 0.5rem;
      font-weight: 500;
    }

    .form-group input,
    .form-group select,
    .form-group textarea {
      width: 100%;
      padding: 0.5rem;
      border: 2px solid var(--witch-lavender);
      border-radius: 4px;
      font-size: 1rem;
      background-color: var(--witch-moon);
      color: var(--witch-purple);
      transition: border-color 0.3s;
    }

    .form-group input:focus,
    .form-group select:focus,
    .form-group textarea:focus {
      outline: none;
      border-color: var(--witch-rose);
      box-shadow: 0 0 0 3px rgba(168, 87, 126, 0.2);
    }

    .form-actions {
      display: flex;
      gap: 1rem;
      margin-top: 1rem;
    }

    .search-section {
      display: flex;
      gap: 1rem;
      margin-bottom: 1.5rem;
      align-items: center;
    }

    .search-input {
      flex: 1;
      padding: 0.75rem 1rem;
      border: 2px solid var(--witch-lavender);
      border-radius: 4px;
      font-size: 1rem;
      background-color: var(--witch-moon);
      color: var(--witch-purple);
      transition: border-color 0.3s;
    }

    .search-input:focus {
      outline: none;
      border-color: var(--witch-rose);
      box-shadow: 0 0 0 3px rgba(168, 87, 126, 0.2);
    }

    .search-input::placeholder {
      color: var(--witch-mauve);
    }

    .advanced-filters {
      background: rgba(255, 255, 255, 0.95);
      border: 2px solid var(--witch-lavender);
      border-radius: 8px;
      padding: 1.5rem;
      margin-bottom: 1.5rem;
      backdrop-filter: blur(10px);
    }

    .filter-group {
      margin-bottom: 1rem;
    }

    .filter-group:last-child {
      margin-bottom: 0;
    }

    .filter-group label {
      display: block;
      margin-bottom: 0.75rem;
      font-weight: 600;
      color: var(--witch-purple);
    }

    .tags-filter {
      display: flex;
      flex-wrap: wrap;
      gap: 0.75rem;
      margin-bottom: 1rem;
    }

    .tag-checkbox {
      display: flex;
      align-items: center;
      gap: 0.5rem;
      cursor: pointer;
      padding: 0.25rem 0.5rem;
      border: 2px solid var(--witch-lavender);
      border-radius: 4px;
      transition: all 0.2s;
      font-weight: 500;
    }

    .tag-checkbox:hover {
      background: var(--witch-lavender);
      transform: translateY(-1px);
    }

    .tag-checkbox input[type="checkbox"] {
      cursor: pointer;
    }

    .tag-checkbox input[type="checkbox"]:checked + .tag-label {
      color: #8b6f47;
    }

    .tag-checkbox:has(input:checked) {
      background: var(--witch-lavender);
      border-color: #8b6f47;
    }

    .tag-label {
      font-size: 0.9rem;
      color: var(--witch-plum);
    }

    .no-tags {
      color: var(--witch-mauve);
      font-style: italic;
      margin: 0;
    }

    .clear-tags {
      margin-top: 0.5rem;
    }

    .filter-badge {
      background: var(--witch-rose);
      color: var(--witch-moon);
      padding: 0.1rem 0.4rem;
      border-radius: 10px;
      font-size: 0.75rem;
      font-weight: 600;
      margin-left: 0.25rem;
    }

    .filters {
      display: flex;
      gap: 1rem;
      margin-bottom: 2rem;
      flex-wrap: wrap;
    }

    .filter-btn {
      padding: 0.5rem 1rem;
      background: var(--witch-lavender);
      color: var(--witch-purple);
      border: none;
      border-radius: 4px;
      cursor: pointer;
      transition: all 0.3s;
    }

    .filter-btn:hover {
      background: var(--witch-mauve);
      transform: translateY(-2px);
      box-shadow: 0 4px 8px var(--witch-shadow);
    }

    .filter-btn.active {
      background: #8b6f47;
      color: white;
    }

    .loading {
      text-align: center;
      padding: 2rem;
      color: var(--witch-plum);
    }

    .empty-state {
      text-align: center;
      padding: 3rem;
      color: var(--witch-plum);
    }

    .books-grid {
      display: grid;
      grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
      gap: 1.5rem;
    }

    .book-card {
      background: rgba(255, 255, 255, 0.95);
      border: 2px solid var(--witch-lavender);
      border-radius: 8px;
      overflow: hidden;
      transition: all 0.3s;
      backdrop-filter: blur(10px);
      display: flex;
      flex-direction: column;
    }

    .book-card:hover {
      transform: translateY(-2px);
      box-shadow: 0 4px 12px var(--witch-shadow);
      border-color: var(--witch-mauve);
    }

    .book-card.finished {
      opacity: 0.9;
      border-color: var(--witch-mauve);
    }

    .card-link {
      text-decoration: none;
      color: inherit;
      flex: 1;
      display: flex;
      flex-direction: column;
    }

    .card-link:hover h3 {
      color: var(--witch-rose);
    }

    .card-actions {
      padding: 1rem;
      border-top: 1px solid var(--witch-lavender);
      display: flex;
      gap: 0.5rem;
      align-items: center;
      flex-wrap: wrap;
    }

    .admin-actions {
      display: flex;
      gap: 0.5rem;
      margin-left: auto;
    }

    .book-cover {
      width: 100%;
      height: 250px;
      object-fit: cover;
    }

    .book-cover.placeholder {
      display: flex;
      align-items: center;
      justify-content: center;
      background: var(--witch-lavender);
      font-size: 4rem;
    }

    .book-info {
      padding: 1rem;
    }

    .book-info h3 {
      margin: 0 0 0.5rem 0;
      font-size: 1.1rem;
      transition: color 0.2s;
    }

    .author {
      color: var(--witch-plum);
      font-style: italic;
      margin: 0.5rem 0;
    }

    .status {
      display: inline-block;
      padding: 0.25rem 0.5rem;
      border-radius: 4px;
      font-size: 0.8rem;
      font-weight: 500;
    }

    .status-reading {
      background: var(--witch-rose);
      color: var(--witch-moon);
    }
    .status-finished {
      background: var(--witch-mauve);
      color: var(--witch-purple);
    }
    .status-toRead {
      background: var(--witch-lavender);
      color: var(--witch-purple);
    }

    .rating {
      margin: 0.5rem 0;
    }

    .rating span {
      color: var(--witch-lavender);
      font-size: 1.2rem;
    }

    .rating span.filled {
      color: var(--witch-rose);
    }

    .btn {
      padding: 0.5rem 1rem;
      border: none;
      border-radius: 4px;
      cursor: pointer;
      font-size: 0.9rem;
      transition: opacity 0.3s;
    }

    .btn:hover {
      opacity: 0.8;
    }

    .btn-primary {
      background: #8b6f47;
      color: white;
    }

    .btn-primary:hover {
      background: #725a3a;
      transform: translateY(-2px);
      box-shadow: 0 4px 8px var(--witch-shadow);
    }

    .btn-secondary {
      background: #6b7280;
      color: white;
    }

    .btn-secondary:hover {
      background: #4b5563;
      color: white;
    }

    .btn-danger {
      background: #ef4444;
      color: white;
    }

    .btn-danger:hover {
      background: #dc2626;
    }

    .btn-sm { padding: 0.25rem 0.75rem; font-size: 0.85rem; }
    .btn-xs { padding: 0.15rem 0.5rem; font-size: 0.75rem; }

    .image-preview {
      margin-top: 0.5rem;
      display: flex;
      align-items: center;
      gap: 1rem;
    }

    .image-preview img {
      max-width: 100px;
      max-height: 150px;
      border-radius: 4px;
      border: 2px solid var(--witch-lavender);
    }

    .error-text {
      color: var(--witch-rose);
      font-size: 0.875rem;
      display: block;
      margin-top: 0.25rem;
    }

    input[type="file"] {
      padding: 0.5rem;
      border: 2px dashed var(--witch-lavender);
      border-radius: 4px;
      background: var(--witch-moon);
      cursor: pointer;
    }

    input[type="file"]:hover {
      border-color: var(--witch-rose);
    }

    .tags-input-container {
      display: flex;
      flex-wrap: wrap;
      gap: 0.5rem;
      padding: 0.5rem;
      border: 2px solid var(--witch-lavender);
      border-radius: 4px;
      background: var(--witch-moon);
    }

    .tags-input-container input {
      flex: 1;
      min-width: 150px;
      border: none;
      padding: 0.25rem;
      font-size: 0.9rem;
      background: transparent;
    }

    .tags-input-container input:focus {
      outline: none;
    }

    .tag {
      display: inline-flex;
      align-items: center;
      gap: 0.25rem;
      background: #8b6f47;
      color: white;
      padding: 0.25rem 0.5rem;
      border-radius: 4px;
      font-size: 0.85rem;
    }

    .tag-remove {
      background: none;
      border: none;
      color: white;
      cursor: pointer;
      padding: 0;
      font-size: 1rem;
      line-height: 1;
    }

    .tag-remove:hover {
      opacity: 0.8;
    }

    .links-list {
      margin-bottom: 0.5rem;
    }

    .link-item {
      display: flex;
      justify-content: space-between;
      align-items: center;
      padding: 0.5rem;
      background: var(--witch-moon);
      border-radius: 4px;
      margin-bottom: 0.25rem;
    }

    .link-add-form {
      display: flex;
      gap: 0.5rem;
      flex-wrap: wrap;
    }

    .link-add-form input {
      flex: 1;
      min-width: 120px;
    }

    @media (max-width: 768px) {
      .search-section {
        flex-direction: column;
      }

      .search-input {
        width: 100%;
      }

      .filters {
        justify-content: center;
      }

      .filter-btn {
        font-size: 0.85rem;
        padding: 0.4rem 0.8rem;
      }
    }
  `]
})
export class BooksListComponent implements OnInit {
  booksService = inject(BooksService);
  authService = inject(AuthService);
  commentsService = inject(CommentsService);
  sanitizeService = inject(SanitizeService);
  suggestionService = inject(SuggestionService);

  books = signal<Book[]>([]);
  loading = signal(true);
  showAddForm = signal(false);
  editingBook = signal<Book | null>(null);
  statusFilter = signal<'all' | BookStatus>('all');
  searchQuery = signal('');
  selectedTags = signal<string[]>([]);
  showFilters = signal(false);

  // Pagination state
  currentPage = signal(1);
  pageSize = signal(25);

  // Comments state
  comments = signal<Record<string, Comment[]>>({});
  commentsLoading = signal<Record<string, boolean>>({});
  expandedComments = signal<Record<string, boolean>>({});
  newCommentContent: Record<string, string> = {};
  editingCommentId = signal<string | null>(null);
  editCommentContent = '';

  // Image upload state
  newBookImagePreview = signal<string | null>(null);
  editBookImagePreview = signal<string | null>(null);
  suggestBookImagePreview = signal<string | null>(null);
  imageError = signal<string | null>(null);
  private readonly MAX_IMAGE_SIZE = 500 * 1024; // 500KB

  // Suggestion state
  showSuggestForm = signal(false);
  suggestedBook: { title: string; author: string; isbn?: string; notes?: string; coverImage?: string } = {
    title: '',
    author: '',
    isbn: '',
    notes: '',
    coverImage: undefined
  };

  // Expose BookStatus enum to template
  BookStatus = BookStatus;

  // Computed signals for reactive count updates
  readingCount = computed(() => this.books().filter(book => book.status === BookStatus.reading).length);
  finishedCount = computed(() => this.books().filter(book => book.status === BookStatus.finished).length);
  toReadCount = computed(() => this.books().filter(book => book.status === BookStatus.toRead).length);
  retiredCount = computed(() => this.books().filter(book => book.status === BookStatus.retired).length);

  // Get all unique tags from all books
  allTags = computed(() => {
    const tags = new Set<string>();
    this.books().forEach(book => {
      book.tags?.forEach(tag => tags.add(tag));
    });
    return Array.from(tags).sort();
  });

  filteredBooks = computed(() => {
    let books = this.books();

    // Apply status filter
    const statusFilter = this.statusFilter();
    if (statusFilter !== 'all') {
      books = books.filter(book => book.status === statusFilter);
    }

    // Apply search filter
    const searchQuery = this.searchQuery().toLowerCase().trim();
    if (searchQuery) {
      books = books.filter(book =>
        book.title.toLowerCase().includes(searchQuery) ||
        book.author.toLowerCase().includes(searchQuery) ||
        book.isbn?.toLowerCase().includes(searchQuery) ||
        book.notes?.toLowerCase().includes(searchQuery)
      );
    }

    // Apply tag filter
    const selectedTags = this.selectedTags();
    if (selectedTags.length > 0) {
      books = books.filter(book =>
        selectedTags.every(tag => book.tags?.includes(tag))
      );
    }

    return books;
  });

  paginatedBooks = computed(() => {
    const books = this.filteredBooks();
    const start = (this.currentPage() - 1) * this.pageSize();
    const end = start + this.pageSize();
    return books.slice(start, end);
  });

  totalFilteredBooks = computed(() => this.filteredBooks().length);

  newBook: Partial<CreateBookDto> & { dateStarted?: Date; dateFinished?: Date } = {
    title: '',
    author: '',
    isbn: '',
    status: BookStatus.toRead,
    dateStarted: undefined,
    dateFinished: undefined,
    rating: undefined,
    notes: '',
    tags: [],
    links: []
  };

  editBook: Partial<UpdateBookDto> = {};

  newBookTimeHours = 0;
  newBookTimeMinutes = 0;
  editBookTimeHours = 0;
  editBookTimeMinutes = 0;

  // Tags and links input state
  newTagInput = '';
  editTagInput = '';
  newLinkTitle = '';
  newLinkUrl = '';
  editLinkTitle = '';
  editLinkUrl = '';

  ngOnInit() {
    this.loadBooks();
  }

  loadBooks() {
    this.loading.set(true);
    this.booksService.getAllBooks().subscribe({
      next: (books) => {
        this.books.set(books);
        this.loading.set(false);
      },
      error: () => {
        this.loading.set(false);
      }
    });
  }

  setFilter(filter: 'all' | BookStatus) {
    this.statusFilter.set(filter);
    this.currentPage.set(1); // Reset to first page when filter changes
  }

  onSearchChange() {
    this.currentPage.set(1); // Reset to first page when search changes
  }

  toggleFilters() {
    this.showFilters.update(show => !show);
  }

  toggleTag(tag: string) {
    this.selectedTags.update(tags => {
      const index = tags.indexOf(tag);
      if (index === -1) {
        return [...tags, tag];
      } else {
        return tags.filter(t => t !== tag);
      }
    });
    this.currentPage.set(1); // Reset to first page when tags change
  }

  clearTags() {
    this.selectedTags.set([]);
    this.currentPage.set(1); // Reset to first page when tags are cleared
  }

  onPageChange(page: number) {
    this.currentPage.set(page);
  }

  onPageSizeChange(pageSize: number) {
    this.pageSize.set(pageSize);
    // Calculate new current page to stay on approximately the same content
    const firstItemIndex = (this.currentPage() - 1) * this.pageSize();
    const newPage = Math.floor(firstItemIndex / pageSize) + 1;
    this.currentPage.set(newPage);
  }

  getStatusLabel(status: BookStatus): string {
    switch (status) {
      case BookStatus.reading: return 'Currently Reading';
      case BookStatus.finished: return 'Finished';
      case BookStatus.toRead: return 'To Read';
      case BookStatus.retired: return 'Retired';
    }
  }

  toggleAddForm() {
    this.showAddForm.update(v => !v);
    if (!this.showAddForm()) {
      this.resetForm();
    }
  }

  resetForm() {
    this.newBook = {
      title: '',
      author: '',
      isbn: '',
      status: BookStatus.toRead,
      dateStarted: undefined,
      dateFinished: undefined,
      rating: undefined,
      notes: '',
      coverImage: undefined,
      tags: [],
      links: []
    };
    this.newBookImagePreview.set(null);
    this.imageError.set(null);
    this.newTagInput = '';
    this.newLinkTitle = '';
    this.newLinkUrl = '';
    this.newBookTimeHours = 0;
    this.newBookTimeMinutes = 0;
  }

  addTag(target: 'new' | 'edit') {
    const input = target === 'new' ? this.newTagInput.trim() : this.editTagInput.trim();
    if (!input) return;

    if (target === 'new') {
      this.newBook.tags = [...(this.newBook.tags || []), input];
      this.newTagInput = '';
    } else {
      this.editBook.tags = [...(this.editBook.tags || []), input];
      this.editTagInput = '';
    }
  }

  removeTag(index: number, target: 'new' | 'edit') {
    if (target === 'new') {
      this.newBook.tags = (this.newBook.tags || []).filter((_, i) => i !== index);
    } else {
      this.editBook.tags = (this.editBook.tags || []).filter((_, i) => i !== index);
    }
  }

  addLink(target: 'new' | 'edit') {
    const title = target === 'new' ? this.newLinkTitle.trim() : this.editLinkTitle.trim();
    const url = target === 'new' ? this.newLinkUrl.trim() : this.editLinkUrl.trim();
    if (!title || !url) return;

    if (target === 'new') {
      this.newBook.links = [...(this.newBook.links || []), { title, url }];
      this.newLinkTitle = '';
      this.newLinkUrl = '';
    } else {
      this.editBook.links = [...(this.editBook.links || []), { title, url }];
      this.editLinkTitle = '';
      this.editLinkUrl = '';
    }
  }

  removeLink(index: number, target: 'new' | 'edit') {
    if (target === 'new') {
      this.newBook.links = (this.newBook.links || []).filter((_, i) => i !== index);
    } else {
      this.editBook.links = (this.editBook.links || []).filter((_, i) => i !== index);
    }
  }

  addBook() {
    if (!this.newBook.title || !this.newBook.author || !this.newBook.status) return;

    const bookToAdd: CreateBookDto = {
      title: this.newBook.title,
      author: this.newBook.author,
      isbn: this.newBook.isbn,
      status: this.newBook.status,
      dateStarted: this.newBook.dateStarted ? new Date(this.newBook.dateStarted) : undefined,
      dateFinished: this.newBook.dateFinished ? new Date(this.newBook.dateFinished) : undefined,
      rating: this.newBook.rating,
      notes: this.newBook.notes,
      coverImage: this.newBook.coverImage,
      tags: this.newBook.tags || [],
      links: this.newBook.links || []
    };

    this.booksService.createBook(bookToAdd).subscribe(() => {
      this.loadBooks();
      this.toggleAddForm();
    });
  }

  deleteBook(book: Book) {
    if (confirm(`Are you sure you want to delete "${book.title}"?`)) {
      this.booksService.deleteBook(book.id).subscribe(() => {
        this.loadBooks();
      });
    }
  }

  startEdit(book: Book) {
    this.editingBook.set(book);
    this.editBook = {
      title: book.title,
      author: book.author,
      isbn: book.isbn,
      status: book.status,
      dateStarted: book.dateStarted,
      dateFinished: book.dateFinished,
      rating: book.rating,
      notes: book.notes,
      coverImage: book.coverImage,
      tags: [...(book.tags || [])],
      links: [...(book.links || [])],
      series: book.series,
      seriesOrder: book.seriesOrder
    };
    this.editBookImagePreview.set(book.coverImage || null);
    this.showAddForm.set(false);
    this.imageError.set(null);
    this.editTagInput = '';
    this.editLinkTitle = '';
    this.editLinkUrl = '';
    if (book.timeSpent) {
      this.editBookTimeHours = Math.floor(book.timeSpent / 60);
      this.editBookTimeMinutes = book.timeSpent % 60;
    } else {
      this.editBookTimeHours = 0;
      this.editBookTimeMinutes = 0;
    }

    // Scroll to top so the form is visible
    window.scrollTo({ top: 0, behavior: 'smooth' });
  }

  cancelEdit() {
    this.editingBook.set(null);
    this.editBook = {};
    this.editBookImagePreview.set(null);
    this.imageError.set(null);
    this.editTagInput = '';
    this.editLinkTitle = '';
    this.editLinkUrl = '';
  }

  saveEdit() {
    const book = this.editingBook();
    if (!book || !this.editBook.title || !this.editBook.author || !this.editBook.status) return;

    const updateData = {
      ...this.editBook,
      dateStarted: this.editBook.dateStarted ? new Date(this.editBook.dateStarted) : undefined,
      dateFinished: this.editBook.dateFinished ? new Date(this.editBook.dateFinished) : undefined,
    };

    this.booksService.updateBook(book.id, updateData).subscribe(() => {
      this.loadBooks();
      this.cancelEdit();
    });
  }

  formatDate(date: Date | string): string {
    return new Date(date).toLocaleDateString();
  }

  updateNewBookTimeSpent() {
    const totalMinutes = (this.newBookTimeHours * 60) + this.newBookTimeMinutes;
    this.newBook.timeSpent = totalMinutes > 0 ? totalMinutes : undefined;
  }

  updateEditBookTimeSpent() {
    const totalMinutes = (this.editBookTimeHours * 60) + this.editBookTimeMinutes;
    this.editBook.timeSpent = totalMinutes > 0 ? totalMinutes : undefined;
  }

  formatTimeSpent(minutes: number): string {
    const hours = Math.floor(minutes / 60);
    const mins = minutes % 60;

    if (hours === 0) {
      return `${mins}m`;
    } else if (mins === 0) {
      return `${hours}h`;
    } else {
      return `${hours}h ${mins}m`;
    }
  }

  // Image handling methods
  onImageSelected(event: Event, target: 'new' | 'edit' | 'suggest') {
    const input = event.target as HTMLInputElement;
    const file = input.files?.[0];

    if (!file) return;

    this.imageError.set(null);

    if (file.size > this.MAX_IMAGE_SIZE) {
      this.imageError.set(`Image too large. Maximum size is ${this.MAX_IMAGE_SIZE / 1024}KB.`);
      input.value = '';
      return;
    }

    if (!file.type.startsWith('image/')) {
      this.imageError.set('Please select an image file.');
      input.value = '';
      return;
    }

    const reader = new FileReader();
    reader.onload = () => {
      const base64 = reader.result as string;
      if (target === 'new') {
        this.newBookImagePreview.set(base64);
        this.newBook.coverImage = base64;
      } else if (target === 'edit') {
        this.editBookImagePreview.set(base64);
        this.editBook.coverImage = base64;
      } else {
        this.suggestBookImagePreview.set(base64);
        this.suggestedBook.coverImage = base64;
      }
    };
    reader.readAsDataURL(file);
  }

  clearImage(target: 'new' | 'edit' | 'suggest') {
    if (target === 'new') {
      this.newBookImagePreview.set(null);
      this.newBook.coverImage = undefined;
    } else if (target === 'edit') {
      this.editBookImagePreview.set(null);
      this.editBook.coverImage = undefined;
    } else {
      this.suggestBookImagePreview.set(null);
      this.suggestedBook.coverImage = undefined;
    }
    this.imageError.set(null);
  }

  // Comments methods
  toggleComments(bookId: string) {
    const expanded = this.expandedComments();
    const isCurrentlyExpanded = expanded[bookId];

    this.expandedComments.set({
      ...expanded,
      [bookId]: !isCurrentlyExpanded
    });

    if (!isCurrentlyExpanded && !this.comments()[bookId]) {
      this.loadComments(bookId);
    }
  }

  loadComments(bookId: string) {
    this.commentsLoading.set({
      ...this.commentsLoading(),
      [bookId]: true
    });

    this.commentsService.getCommentsForBook(bookId).subscribe({
      next: (comments) => {
        this.comments.set({
          ...this.comments(),
          [bookId]: comments
        });
        this.commentsLoading.set({
          ...this.commentsLoading(),
          [bookId]: false
        });
      },
      error: () => {
        this.commentsLoading.set({
          ...this.commentsLoading(),
          [bookId]: false
        });
      }
    });
  }

  getCommentCount(bookId: string): number {
    return this.comments()[bookId]?.length || 0;
  }

  addComment(bookId: string) {
    const content = this.newCommentContent[bookId];
    if (!content?.trim()) return;

    this.commentsService.addCommentToBook(bookId, { content }).subscribe({
      next: (comment) => {
        this.comments.set({
          ...this.comments(),
          [bookId]: [comment, ...(this.comments()[bookId] || [])]
        });
        this.newCommentContent[bookId] = '';
      }
    });
  }

  deleteComment(bookId: string, commentId: string) {
    if (!confirm('Are you sure you want to delete this comment?')) return;

    this.commentsService.deleteCommentFromBook(bookId, commentId).subscribe({
      next: () => {
        this.comments.set({
          ...this.comments(),
          [bookId]: (this.comments()[bookId] || []).filter(c => c.id !== commentId)
        });
      }
    });
  }

  canEditComment(comment: Comment): boolean {
    const user = this.authService.user();
    if (!user) return false;
    return comment.userId === user.id || this.authService.isAdmin();
  }

  canDeleteComment(comment: Comment): boolean {
    const user = this.authService.user();
    if (!user) return false;
    return comment.userId === user.id || this.authService.isAdmin();
  }

  startEditComment(bookId: string, comment: Comment) {
    this.editingCommentId.set(comment.id);
    this.editCommentContent = comment.rawContent ?? comment.content;
  }

  cancelCommentEdit() {
    this.editingCommentId.set(null);
    this.editCommentContent = '';
  }

  saveCommentEdit(bookId: string, commentId: string) {
    if (!this.editCommentContent.trim()) return;

    this.commentsService.updateCommentOnBook(bookId, commentId, this.editCommentContent).subscribe({
      next: (updatedComment) => {
        this.comments.set({
          ...this.comments(),
          [bookId]: (this.comments()[bookId] || []).map(c =>
            c.id === commentId ? updatedComment : c
          )
        });
        this.cancelCommentEdit();
      }
    });
  }

  // Suggestion methods
  toggleSuggestForm() {
    this.showSuggestForm.update(v => !v);
    if (!this.showSuggestForm()) {
      this.resetSuggestForm();
    }
  }

  resetSuggestForm() {
    this.suggestedBook = {
      title: '',
      author: '',
      isbn: '',
      notes: '',
      coverImage: undefined
    };
    this.suggestBookImagePreview.set(null);
    this.imageError.set(null);
  }

  async submitSuggestion() {
    if (!this.suggestedBook.title || !this.suggestedBook.author) return;

    try {
      await this.suggestionService.createSuggestion({
        entityType: SuggestionEntity.book,
        title: this.suggestedBook.title,
        author: this.suggestedBook.author,
        isbn: this.suggestedBook.isbn,
        notes: this.suggestedBook.notes,
        coverImage: this.suggestedBook.coverImage
      });
      alert('Thank you for your suggestion! It will be reviewed soon.');
      this.toggleSuggestForm();
    } catch {
      alert('Failed to submit suggestion. Please try again.');
    }
  }

  handleCommentEdit(bookId: string, event: { commentId: string; content: string }) {
    this.commentsService.updateCommentOnBook(bookId, event.commentId, event.content).subscribe({
      next: (updatedComment) => {
        this.comments.set({
          ...this.comments(),
          [bookId]: (this.comments()[bookId] || []).map(c =>
            c.id === event.commentId ? updatedComment : c
          )
        });
      }
    });
  }

  getCommentsSignal(bookId: string) {
    return signal(this.comments()[bookId] || []);
  }
}