import { NextResponse } from "next/server";
import { ApprovalState, DepartmentKey, PmWorkOrderState, ReminderEventState } from "@prisma/client";
import { getServerSession } from "next-auth";
import { authOptions } from "@/lib/auth";
import { prisma } from "@/lib/prisma";
import {
  canAccessOperations,
  canManageOperations,
  ensureDefaultMaintenancePolicy,
  resolveOwnerUserId,
  shouldRequireOwnerApproval,
} from "@/lib/operations";

type CreateWorkOrderBody = {
  assetId?: string;
  templateId?: string | null;
  title?: string;
  description?: string | null;
  scheduledFor?: string;
  dueBy?: string;
  estimatedCost?: number;
  expectedDowntimeHours?: number;
};

export async function GET() {
  const session = await getServerSession(authOptions);
  if (!session?.user) {
    return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
  }

  if (!canAccessOperations(session.user.role, session.user.department)) {
    return NextResponse.json({ error: "Forbidden" }, { status: 403 });
  }

  const workOrders = await prisma.pmWorkOrder.findMany({
    where: {
      asset: {
        department: DepartmentKey.operaciones,
      },
    },
    include: {
      asset: {
        select: {
          id: true,
          name: true,
          assetCode: true,
        },
      },
      reminders: true,
      approvalRequests: true,
    },
    orderBy: [{ dueBy: "asc" }, { createdAt: "desc" }],
    take: 500,
  });

  return NextResponse.json({ ok: true, workOrders });
}

export async function POST(request: Request) {
  const session = await getServerSession(authOptions);
  if (!session?.user) {
    return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
  }

  if (!canManageOperations(session.user.role, session.user.department)) {
    return NextResponse.json({ error: "Only owner/operations leader can create work orders." }, { status: 403 });
  }

  await ensureDefaultMaintenancePolicy(session.user.role === "owner" ? session.user.id : null);
  const policy = await prisma.maintenanceApprovalPolicy.findUnique({
    where: { department: DepartmentKey.operaciones },
  });

  if (!policy) {
    return NextResponse.json({ error: "Approval policy missing." }, { status: 500 });
  }

  const body = (await request.json()) as CreateWorkOrderBody;
  if (!body.assetId || !body.title?.trim()) {
    return NextResponse.json({ error: "assetId and title are required." }, { status: 400 });
  }
  const asset = await prisma.factoryAsset.findFirst({
    where: {
      id: body.assetId,
      department: DepartmentKey.operaciones,
    },
    select: { id: true },
  });
  if (!asset) {
    return NextResponse.json({ error: "Asset not found in operations department." }, { status: 404 });
  }
  if (body.templateId) {
    const template = await prisma.pmTemplate.findFirst({
      where: {
        id: body.templateId,
        asset: {
          department: DepartmentKey.operaciones,
        },
      },
      select: { id: true },
    });
    if (!template) {
      return NextResponse.json({ error: "Template not found in operations department." }, { status: 404 });
    }
  }
  const ownerUserId = policy.ownerUserId ?? (await resolveOwnerUserId());
  if (!policy.ownerUserId && ownerUserId) {
    await prisma.maintenanceApprovalPolicy.update({
      where: { id: policy.id },
      data: {
        ownerUserId,
      },
    });
  }

  const scheduledFor = body.scheduledFor ? new Date(body.scheduledFor) : new Date();
  const dueBy = body.dueBy ? new Date(body.dueBy) : new Date(new Date().getTime() + 3 * 24 * 60 * 60 * 1000);
  if (Number.isNaN(scheduledFor.getTime()) || Number.isNaN(dueBy.getTime())) {
    return NextResponse.json({ error: "Invalid scheduledFor/dueBy date." }, { status: 400 });
  }

  const estimatedCost = Math.max(0, body.estimatedCost ?? 0);
  const expectedDowntimeHours = Math.max(0, body.expectedDowntimeHours ?? 0);
  const requiresApproval = shouldRequireOwnerApproval({
    estimatedCost,
    expectedDowntimeHours,
    costThreshold: policy.costThreshold,
    downtimeThresholdHours: policy.downtimeThresholdHours,
  });

  const workOrder = await prisma.pmWorkOrder.create({
    data: {
      assetId: body.assetId,
      templateId: body.templateId ?? null,
      title: body.title.trim(),
      description: body.description?.trim() || null,
      scheduledFor,
      dueBy,
      estimatedCost,
      expectedDowntimeHours,
      state: requiresApproval ? PmWorkOrderState.draft : PmWorkOrderState.scheduled,
      requestedById: session.user.id,
    },
    include: {
      asset: {
        select: {
          id: true,
          name: true,
          assetCode: true,
        },
      },
    },
  });

  await prisma.reminderEvent.create({
    data: {
      workOrderId: workOrder.id,
      remindAt: new Date(dueBy.getTime() - 24 * 60 * 60 * 1000),
      channel: "in_app",
      message: `Recordatorio de mantenimiento para ${workOrder.asset.name}`,
      state: ReminderEventState.queued,
    },
  });

  if (requiresApproval) {
    await prisma.approvalRequest.create({
      data: {
        department: DepartmentKey.operaciones,
        requestType: "maintenance_work_order",
        workOrderId: workOrder.id,
        submittedById: session.user.id,
        approverId: ownerUserId,
        state: ApprovalState.pending_owner,
        reason: `Costo estimado ${estimatedCost.toFixed(2)} o downtime ${expectedDowntimeHours.toFixed(2)}h excede umbral.`,
      },
    });
  }

  return NextResponse.json({ ok: true, workOrder, requiresApproval });
}
