import { Router } from "express";
import type { Request } from "express";
import { graphqlClient } from "../lib/graphqlClient";
import { respondWithError } from "../lib/error";
import {
  GetCollectionDocument,
  CollectionsDocument,
  CreateCollectionDocument,
  UpdateCollectionDocument,
  DeleteCollectionDocument,
  AddWorkToCollectionDocument,
  RemoveWorkFromCollectionDocument,
  type GetCollectionQuery,
  type CollectionsQuery,
  type CreateCollectionMutation,
  type UpdateCollectionMutation,
  type DeleteCollectionMutation,
  type AddWorkToCollectionMutation,
  type RemoveWorkFromCollectionMutation,
} from "../../shared/generated/graphql";

interface GqlRequest extends Request {
  gql?: typeof graphqlClient;
}

const router = Router();

// GET /api/collections/:id
router.get("/:id", async (req: GqlRequest, res) => {
  try {
    const client = req.gql || graphqlClient;
    const { collection } = await client.request<GetCollectionQuery>(
      GetCollectionDocument,
      { id: req.params.id }
    );
    if (!collection)
      return res.status(404).json({ message: "Collection not found" });
    res.json(collection);
  } catch (error) {
    respondWithError(res, error, "Failed to fetch collection");
  }
});

// GET /api/collections
router.get("/", async (req: GqlRequest, res) => {
  try {
    const client = req.gql || graphqlClient;
    const { collections } = await client.request<CollectionsQuery>(
      CollectionsDocument,
      {
        userId: req.query.userId as string | undefined,
        limit: req.query.limit ? Number(req.query.limit) : undefined,
        offset: req.query.offset ? Number(req.query.offset) : undefined,
      }
    );
    res.json(collections);
  } catch (error) {
    respondWithError(res, error, "Failed to fetch collections");
  }
});

// POST /api/collections
router.post("/", async (req: GqlRequest, res) => {
  try {
    const client = req.gql || graphqlClient;
    const { createCollection } = await client.request<CreateCollectionMutation>(
      CreateCollectionDocument,
      { input: req.body }
    );
    res.status(201).json(createCollection);
  } catch (error) {
    respondWithError(res, error, "Failed to create collection");
  }
});

// PUT /api/collections/:id
router.put("/:id", async (req: GqlRequest, res) => {
  try {
    const client = req.gql || graphqlClient;
    const { updateCollection } = await client.request<UpdateCollectionMutation>(
      UpdateCollectionDocument,
      { id: req.params.id, input: req.body }
    );
    res.json(updateCollection);
  } catch (error) {
    respondWithError(res, error, "Failed to update collection");
  }
});

// DELETE /api/collections/:id
router.delete("/:id", async (req: GqlRequest, res) => {
  try {
    const client = req.gql || graphqlClient;
    const { deleteCollection } = await client.request<DeleteCollectionMutation>(
      DeleteCollectionDocument,
      { id: req.params.id }
    );
    res.json({ success: deleteCollection });
  } catch (error) {
    respondWithError(res, error, "Failed to delete collection");
  }
});

// POST /api/collections/:id/works
router.post("/:id/works", async (req: GqlRequest, res) => {
  try {
    const client = req.gql || graphqlClient;
    const { addWorkToCollection } =
      await client.request<AddWorkToCollectionMutation>(
        AddWorkToCollectionDocument,
        {
          collectionId: req.params.id,
          workId: req.body.workId,
        }
      );
    res.status(201).json(addWorkToCollection);
  } catch (error) {
    respondWithError(res, error, "Failed to add work to collection");
  }
});

// DELETE /api/collections/:id/works/:workId
router.delete("/:id/works/:workId", async (req: GqlRequest, res) => {
  try {
    const client = req.gql || graphqlClient;
    const { removeWorkFromCollection } =
      await client.request<RemoveWorkFromCollectionMutation>(
        RemoveWorkFromCollectionDocument,
        {
          collectionId: req.params.id,
          workId: req.params.workId,
        }
      );
    res.json(removeWorkFromCollection);
  } catch (error) {
    respondWithError(res, error, "Failed to remove work from collection");
  }
});

export default router;
