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

import { MangaStatus } from "../src/lib/manga.types";
import type { Manga, CreateMangaDto, UpdateMangaDto } from "../src/lib/manga.types";

describe("manga Types", () => {
  describe("mangaStatus enum", () => {
    it("should have the correct values", () => {
      expect(MangaStatus.reading).toBe("READING");
      expect(MangaStatus.completed).toBe("COMPLETED");
      expect(MangaStatus.wantToRead).toBe("WANT_TO_READ");
    });

    it("should have all expected enum values", () => {
      const values = Object.values(MangaStatus);
      expect(values).toHaveLength(4);
      expect(values).toContain("READING");
      expect(values).toContain("COMPLETED");
      expect(values).toContain("WANT_TO_READ");
      expect(values).toContain("RETIRED");
    });
  });

  describe("manga interface", () => {
    it("should accept valid manga object with minimal fields", () => {
      const manga: Manga = {
        author:    "Tsugumi Ohba",
        createdAt: new Date("2024-01-15"),
        dateAdded: new Date("2024-01-15"),
        id:        "manga123",
        links:     [],
        status:    MangaStatus.reading,
        tags:      [],
        title:     "Death Note",
        updatedAt: new Date("2024-01-16"),
      };

      expect(manga.dateCompleted).toBeUndefined();
      expect(manga.rating).toBeUndefined();
      expect(manga.notes).toBeUndefined();
      expect(manga.coverImage).toBeUndefined();
    });

    it("should accept valid manga object with all fields", () => {
      const fullManga: Manga = {
        author:        "Eiichiro Oda",
        coverImage:    "https://example.com/onepiece-cover.jpg",
        createdAt:     new Date("2024-01-01"),
        dateAdded:     new Date("2024-01-01"),
        dateCompleted: undefined,
        id:            "manga456",
        links:         [
          { title: "MyAnimeList", url: "https://myanimelist.net/manga/13" },
          { title: "Official Site", url: "https://one-piece.com" },
        ],

        notes: "Epic adventure that keeps getting better",

        // Still ongoing
        rating: 5,

        status: MangaStatus.reading,

        tags:      [ "adventure", "shounen", "pirates", "long-running" ],
        title:     "One Piece",
        updatedAt: new Date("2024-02-01"),
      };

      expect(fullManga.author).toBe("Eiichiro Oda");
      expect(fullManga.rating).toBe(5);
      expect(fullManga.tags).toHaveLength(4);
      expect(fullManga.links).toHaveLength(2);
    });

    it("should accept completed manga", () => {
      const completedManga: Manga = {
        author:        "Hiromu Arakawa",
        coverImage:    "https://example.com/fma-cover.jpg",
        createdAt:     new Date("2023-12-01"),
        dateAdded:     new Date("2023-12-01"),
        dateCompleted: new Date("2024-01-30"),
        id:            "manga789",
        links:         [],
        notes:         "Perfect from start to finish",
        rating:        5,
        status:        MangaStatus.completed,
        tags:          [ "shounen", "adventure", "alchemy" ],
        title:         "Fullmetal Alchemist",
        updatedAt:     new Date("2024-01-30"),
      };

      expect(completedManga.status).toBe(MangaStatus.completed);
      expect(completedManga.dateCompleted).toEqual(new Date("2024-01-30"));
    });
  });

  describe("createMangaDto interface", () => {
    it("should accept DTO with required fields only", () => {
      const createDto: CreateMangaDto = {
        author: "Hajime Isayama",
        status: MangaStatus.wantToRead,
        title:  "Attack on Titan",
      };

      expect(createDto.rating).toBeUndefined();
      expect(createDto.notes).toBeUndefined();
      expect(createDto.coverImage).toBeUndefined();
      expect(createDto.tags).toBeUndefined();
      expect(createDto.links).toBeUndefined();
    });

    it("should accept DTO with all fields", () => {
      const fullCreateDto: CreateMangaDto = {
        author:     "Kohei Horikoshi",
        coverImage: "https://example.com/mha-cover.jpg",
        links:      [ { title: "Wiki", url: "https://mha.wiki" } ],
        notes:      "Great superhero manga with unique powers",
        rating:     4,
        status:     MangaStatus.reading,
        tags:       [ "shounen", "superhero", "school" ],
        title:      "My Hero Academia",
      };

      expect(fullCreateDto.author).toBe("Kohei Horikoshi");
      expect(fullCreateDto.rating).toBe(4);
      expect(fullCreateDto.tags).toEqual([ "shounen", "superhero", "school" ]);
      expect(fullCreateDto.links).toHaveLength(1);
    });
  });

  describe("updateMangaDto type", () => {
    it("should accept empty update DTO", () => {
      const emptyUpdate: UpdateMangaDto = {};
      expect(emptyUpdate).toEqual({});
    });

    it("should accept partial updates including dateCompleted", () => {
      const partialUpdate: UpdateMangaDto = {
        dateCompleted: new Date("2024-02-10"),
        rating:        4,
        status:        MangaStatus.completed,
      };

      expect(partialUpdate.status).toBe(MangaStatus.completed);
      expect(partialUpdate.dateCompleted).toEqual(new Date("2024-02-10"));
      expect(partialUpdate.rating).toBe(4);
      expect(partialUpdate.title).toBeUndefined();
    });

    it("should accept full update", () => {
      const fullUpdate: UpdateMangaDto = {
        author:        "Different Author",
        coverImage:    "https://example.com/new-manga-cover.jpg",
        dateCompleted: new Date("2024-02-15"),
        links:         [ { title: "New Link", url: "https://newlink.com" } ],
        notes:         "Updated after finishing the series",
        rating:        3,
        status:        MangaStatus.completed,
        tags:          [ "updated", "tags" ],
        title:         "Updated Manga Title",
      };

      expect(fullUpdate.title).toBe("Updated Manga Title");
      expect(fullUpdate.author).toBe("Different Author");
      expect(fullUpdate.dateCompleted).toEqual(new Date("2024-02-15"));
      expect(fullUpdate.links).toHaveLength(1);
    });
  });
});
