"use server"

import { revalidatePath } from "next/cache"

import prisma from "@/lib/prisma"
import { AssetService } from "@/services/asset.service"
import { AssignmentService } from "@/services/assignment.service"
import { getAuthenticatedUserId } from "@/services/auth.service"
import { ItemService } from "@/services/item.service"
import { MovementService } from "@/services/movement.service"

import {
  assignmentSchema,
  CreateAssignmentFormType,
  ReturnAssignmentFormType,
  UpdateAssignmentFormType,
  updateAssignmentSchema,
} from "../schemas/assignment.schemas"

export async function getAssignments() {
  return await AssignmentService.findAllWithRecipient()
}

export async function getAssignmentById(id: string) {
  return await AssignmentService.findById(id)
}

export async function createAssignment(formData: CreateAssignmentFormType) {
  const createdBy = await getAuthenticatedUserId()

  const validatedFields = assignmentSchema.safeParse({
    ...formData,
    createdBy,
  })

  if (!validatedFields.success) {
    return {
      success: false,
      errors: validatedFields.error.flatten().fieldErrors,
    }
  }

  const { itemId, assetId, quantity, recipientId } = validatedFields.data

  if (!itemId || !recipientId || quantity <= 0) return

  try {
    const item = await ItemService.findById(itemId)

    if (!item) {
      return {
        success: false,
        errors: { itemId: ["Item not found"] },
      }
    }

    if (item.stock < quantity) {
      return {
        success: false,
        errors: { quantity: ["Item does not have enough stock"] },
      }
    }

    if (assetId) {
      const asset = await AssetService.findById(assetId)

      if (!asset) {
        return {
          success: false,
          errors: { assetId: ["Asset not found"] },
        }
      }

      if (asset.itemId !== item.id) {
        return {
          success: false,
          errors: { assetId: ["Asset does not belong to item"] },
        }
      }
    }

    await ItemService.updateStock(itemId, -quantity)

    if (assetId && recipientId) {
      await AssetService.update(assetId, {
        status: "ASSIGNED",
      })
    }

    const createdAssignment = await AssignmentService.create({
      itemId,
      assetId: assetId || undefined,
      quantity,
      recipientId,
    })

    await MovementService.create({
      itemId,
      assetId: assetId || undefined,
      quantity,
      type: "ASSIGNMENT",
      recipientId,
      assignmentId: createdAssignment.id,
    })

    revalidatePath("/assignments")

    return {
      success: true,
      message: "Assignment created successfully",
    }
  } catch (error) {
    console.error("Database error:", error)
    return {
      success: false,
      errors: { error: ["Error creating assignment"] },
    }
  }
}

export async function updateAssignment(formData: UpdateAssignmentFormType) {
  const validatedFields = updateAssignmentSchema.safeParse(formData)

  if (!validatedFields.success) {
    return {
      success: false,
      errors: validatedFields.error.flatten().fieldErrors,
    }
  }

  try {
    const { id, itemId, assetId, quantity } = validatedFields.data

    const assignment = await prisma.assignment.findUnique({
      where: { id },
    })

    if (!assignment) {
      return {
        success: false,
        errors: { id: ["Assignment not found"] },
      }
    }

    if (itemId) {
      const item = await prisma.item.findUnique({
        where: { id: itemId },
      })

      if (!item) {
        return {
          success: false,
          errors: { itemId: ["Item not found"] },
        }
      }

      if (item.stock < quantity) {
        return {
          success: false,
          errors: { quantity: ["Item does not have enough stock"] },
        }
      }
    }

    if (assetId) {
      const asset = await prisma.asset.findUnique({
        where: { id: assetId },
      })

      if (!asset) {
        return {
          success: false,
          errors: { assetId: ["Asset not found"] },
        }
      }

      if (asset.itemId !== itemId) {
        await prisma.asset.update({
          where: { id: assetId },
          data: { itemId },
        })

        return {
          success: false,
          errors: { assetId: ["Asset does not belong to item"] },
        }
      }
    }

    await prisma.assignment.update({
      where: { id },
      data: {
        ...validatedFields.data,
        itemId,
        assetId,
        quantity,
        returnDate: new Date(),
      },
    })

    revalidatePath("/assignments")

    return {
      success: true,
      message: "Assignment updated successfully",
    }
  } catch (error) {
    console.error("Database error:", error)
    return {
      success: false,
      errors: { error: ["Error creating assignment"] },
    }
  }
}

export async function returnAssignment(formData: ReturnAssignmentFormType) {
  const { id } = formData

  const assignment = await AssignmentService.findById(id)

  if (!assignment) {
    return {
      success: false,
      errors: { id: ["Assignment not found"] },
    }
  }

  if (assignment.returnDate) {
    return {
      success: false,
      errors: { id: ["Assignment already returned"] },
    }
  }

  if (assignment.itemId && assignment.quantity) {
    await ItemService.update(assignment.itemId, {
      stock: { increment: assignment.quantity || 1 },
    })
  }

  if (assignment.assetId) {
    await AssetService.update(assignment.assetId, {
      status: "AVAILABLE",
    })
  }

  await AssignmentService.delete(id)

  await MovementService.create({
    type: "RETURN",
    quantity: assignment.quantity || 1,
    itemId: assignment.itemId || undefined,
    assetId: assignment.assetId || undefined,
    assignmentId: id,
  })

  revalidatePath("/assignments")

  return {
    success: true,
    message: "Assignment returned successfully",
  }
}
