import { Hono } from "hono";
import { zValidator } from "@hono/zod-validator";
import { z } from "zod";
import { auth } from "@/auth";
import { prisma } from "@/lib/prisma";
import { TaskStatus, MemberRole } from "@prisma/client";

import { createEpicSchema, getEpicsSchema, updateEpicSchema } from "../schemas";

const app = new Hono()
  .get(
    "/",
    zValidator("query", getEpicsSchema),
    async (c) => {
      const session = await auth();
      const { workspaceId, projectId, assigneeId, status, search, dueDate } = c.req.valid("query");

      if (!session?.user?.email) {
        return c.json({ error: "Unauthorized" }, 401);
      }

      const currentUser = await prisma.user.findUnique({
        where: { email: session.user.email },
      });

      if (!currentUser) {
        return c.json({ error: "User not found" }, 404);
      }

      // Check if user is a member of the workspace
      const member = await prisma.member.findFirst({
        where: {
          workspaceId,
          userId: currentUser.id,
        },
      });

      if (!member) {
        return c.json({ error: "Unauthorized" }, 401);
      }

      const epics = await prisma.epic.findMany({
        where: {
          workspaceId,
          ...(projectId && { projectId }),
          ...(assigneeId && { assigneeId }),
          ...(status && { status }),
          ...(search && {
            name: {
              contains: search,
              mode: "insensitive",
            },
          }),
          ...(dueDate && {
            dueDate: {
              lte: new Date(dueDate),
            },
          }),
        },
        include: {
          project: {
            select: {
              id: true,
              name: true,
              imageUrl: true,
              workspaceId: true,
            },
          },
          assignee: {
            include: {
              user: {
                select: {
                  name: true,
                  email: true,
                  image: true,
                },
              },
            },
          },
          tasks: {
            select: {
              id: true,
              name: true,
              status: true,
              assigneeId: true,
              projectId: true,
              dueDate: true,
            },
          },
          _count: {
            select: {
              tasks: true,
            },
          },
        },
        orderBy: {
          createdAt: "desc",
        },
      });

      // Transform the data to include computed epic status
      const epicsWithStats = epics.map((epic: any) => {
        const totalTasks = epic.tasks.length;
        const completedTasks = epic.tasks.filter((task: any) => task.status === TaskStatus.DONE).length;
        
        // Auto-compute epic status based on tasks
        let computedStatus = epic.status;
        if (totalTasks > 0) {
          if (completedTasks === totalTasks) {
            computedStatus = TaskStatus.DONE;
          } else if (completedTasks > 0 || epic.tasks.some((task: any) => task.status === TaskStatus.IN_PROGRESS)) {
            computedStatus = TaskStatus.IN_PROGRESS;
          } else if (epic.tasks.some((task: any) => task.status === TaskStatus.TODO || task.status === TaskStatus.IN_REVIEW)) {
            computedStatus = TaskStatus.TODO;
          }
        }

        return {
          ...epic,
          status: computedStatus,
          stats: {
            totalTasks,
            completedTasks,
            progressPercentage: totalTasks > 0 ? Math.round((completedTasks / totalTasks) * 100) : 0,
          },
        };
      });

      return c.json({ data: epicsWithStats });
    }
  )
  .post(
    "/",
    zValidator("json", createEpicSchema),
    async (c) => {
      const session = await auth();
      const { name, description, workspaceId, projectId, assigneeId, dueDate, labels } = c.req.valid("json");

      if (!session?.user?.email) {
        return c.json({ error: "Unauthorized" }, 401);
      }

      const currentUser = await prisma.user.findUnique({
        where: { email: session.user.email },
      });

      if (!currentUser) {
        return c.json({ error: "User not found" }, 404);
      }

      // Check if user is a member of the workspace
      const member = await prisma.member.findFirst({
        where: {
          workspaceId,
          userId: currentUser.id,
        },
      });

      if (!member) {
        return c.json({ error: "Unauthorized" }, 401);
      }

      const epic = await prisma.epic.create({
        data: {
          name,
          description,
          status: TaskStatus.BACKLOG, // Default status for new epics
          workspaceId,
          projectId,
          assigneeId,
          dueDate,
          labels: labels || [],
        },
        include: {
          project: {
            select: {
              id: true,
              name: true,
              imageUrl: true,
              workspaceId: true,
            },
          },
          assignee: {
            include: {
              user: {
                select: {
                  name: true,
                  email: true,
                  image: true,
                },
              },
            },
          },
          _count: {
            select: {
              tasks: true,
            },
          },
        },
      });

      return c.json({ data: epic });
    }
  )
  .patch(
    "/:epicId",
    zValidator("json", updateEpicSchema),
    async (c) => {
      const session = await auth();
      const { name, description, assigneeId, projectId, dueDate, labels } = c.req.valid("json");
      const { epicId } = c.req.param();

      if (!session?.user?.email) {
        return c.json({ error: "Unauthorized" }, 401);
      }

      const currentUser = await prisma.user.findUnique({
        where: { email: session.user.email },
      });

      if (!currentUser) {
        return c.json({ error: "User not found" }, 404);
      }

      const existingEpic = await prisma.epic.findUnique({
        where: { id: epicId },
      });

      if (!existingEpic) {
        return c.json({ error: "Epic not found" }, 404);
      }

      // Check if user is a member of the workspace
      const member = await prisma.member.findFirst({
        where: {
          workspaceId: existingEpic.workspaceId,
          userId: currentUser.id,
        },
      });

      if (!member) {
        return c.json({ error: "Unauthorized" }, 401);
      }

      const epic = await prisma.epic.update({
        where: { id: epicId },
        data: {
          ...(name !== undefined && { name }),
          ...(description !== undefined && { description }),
          ...(assigneeId !== undefined && { assigneeId }),
          ...(projectId !== undefined && { projectId }),
          ...(dueDate !== undefined && { dueDate }),
          ...(labels !== undefined && { labels }),
        },
        include: {
          project: {
            select: {
              id: true,
              name: true,
              imageUrl: true,
              workspaceId: true,
            },
          },
          assignee: {
            include: {
              user: {
                select: {
                  name: true,
                  email: true,
                  image: true,
                },
              },
            },
          },
          tasks: {
            select: {
              id: true,
              name: true,
              status: true,
              assigneeId: true,
              projectId: true,
              dueDate: true,
            },
          },
          _count: {
            select: {
              tasks: true,
            },
          },
        },
      });

      return c.json({ data: epic });
    }
  )
  .delete(
    "/:epicId",
    async (c) => {
      const session = await auth();
      const { epicId } = c.req.param();

      if (!session?.user?.email) {
        return c.json({ error: "Unauthorized" }, 401);
      }

      const currentUser = await prisma.user.findUnique({
        where: { email: session.user.email },
      });

      if (!currentUser) {
        return c.json({ error: "User not found" }, 404);
      }

      const existingEpic = await prisma.epic.findUnique({
        where: { id: epicId },
        include: {
          tasks: true,
        },
      });

      if (!existingEpic) {
        return c.json({ error: "Epic not found" }, 404);
      }

      // Check if user is a member of the workspace and has admin role
      const member = await prisma.member.findFirst({
        where: {
          workspaceId: existingEpic.workspaceId,
          userId: currentUser.id,
        },
      });

      if (!member) {
        return c.json({ error: "Unauthorized" }, 401);
      }

      // Only admins can delete epics
      if (member.role !== MemberRole.ADMIN) {
        return c.json({ error: "Only workspace administrators can delete epics" }, 403);
      }

      // Delete all related tasks (cascade delete)
      await prisma.task.deleteMany({
        where: { epicId },
      });

      await prisma.epic.delete({
        where: { id: epicId },
      });

      return c.json({ data: { id: epicId } });
    }
  )
  .get(
    "/:epicId",
    async (c) => {
      const session = await auth();
      const { epicId } = c.req.param();

      if (!session?.user?.email) {
        return c.json({ error: "Unauthorized" }, 401);
      }

      const currentUser = await prisma.user.findUnique({
        where: { email: session.user.email },
      });

      if (!currentUser) {
        return c.json({ error: "User not found" }, 404);
      }

      const epic = await prisma.epic.findUnique({
        where: { id: epicId },
        include: {
          project: {
            select: {
              id: true,
              name: true,
              imageUrl: true,
              workspaceId: true,
            },
          },
          assignee: {
            include: {
              user: {
                select: {
                  name: true,
                  email: true,
                  image: true,
                },
              },
            },
          },
          tasks: {
            include: {
              assignee: {
                include: {
                  user: {
                    select: {
                      name: true,
                      email: true,
                      image: true,
                    },
                  },
                },
              },
              project: {
                select: {
                  id: true,
                  name: true,
                  imageUrl: true,
                },
              },
            },
            orderBy: {
              position: "asc",
            },
          },
          _count: {
            select: {
              tasks: true,
            },
          },
        },
      });

      if (!epic) {
        return c.json({ error: "Epic not found" }, 404);
      }

      // Check if user is a member of the workspace
      const member = await prisma.member.findFirst({
        where: {
          workspaceId: epic.workspaceId,
          userId: currentUser.id,
        },
      });

      if (!member) {
        return c.json({ error: "Unauthorized" }, 401);
      }

      return c.json({ data: epic });
    }
  );

export default app; 