import { DepartmentKey, PmWorkOrderState } from "@prisma/client";
import { prisma } from "@/lib/prisma";
import type { OperationsDashboardResponse } from "@/lib/operations/types";

export function canAccessOperations(role: string | undefined, department: string | null | undefined): boolean {
  return role === "owner" || department === "operaciones";
}

export function canManageOperations(role: string | undefined, department: string | null | undefined): boolean {
  if (role === "owner") {
    return true;
  }

  return role === "leader" && department === "operaciones";
}

export async function ensureDefaultMaintenancePolicy(ownerUserId: string | null = null) {
  const existing = await prisma.maintenanceApprovalPolicy.findUnique({
    where: {
      department: DepartmentKey.operaciones,
    },
    select: { id: true, ownerUserId: true },
  });

  if (existing) {
    if (!existing.ownerUserId && ownerUserId) {
      await prisma.maintenanceApprovalPolicy.update({
        where: { id: existing.id },
        data: { ownerUserId },
      });
    }
    return;
  }

  await prisma.maintenanceApprovalPolicy.create({
    data: {
      department: DepartmentKey.operaciones,
      costThreshold: 5000,
      downtimeThresholdHours: 4,
      ownerUserId,
    },
  });
}

export async function resolveOwnerUserId() {
  const owner = await prisma.user.findFirst({
    where: {
      userRoles: {
        some: {
          role: {
            key: "owner",
          },
        },
      },
    },
    select: { id: true },
  });

  return owner?.id ?? null;
}

export async function getOperationsDashboardData(): Promise<OperationsDashboardResponse> {
  const [assets, templates, workOrders, approvals, forecasts, plans] = await Promise.all([
    prisma.factoryAsset.findMany({
      where: { department: DepartmentKey.operaciones },
      orderBy: { updatedAt: "desc" },
      take: 400,
    }),
    prisma.pmTemplate.findMany({
      where: {
        asset: {
          department: DepartmentKey.operaciones,
        },
      },
      orderBy: { updatedAt: "desc" },
      take: 400,
    }),
    prisma.pmWorkOrder.findMany({
      where: {
        asset: {
          department: DepartmentKey.operaciones,
        },
      },
      include: {
        asset: {
          select: {
            id: true,
            name: true,
          },
        },
      },
      orderBy: [{ dueBy: "asc" }, { updatedAt: "desc" }],
      take: 500,
    }),
    prisma.approvalRequest.findMany({
      where: { department: DepartmentKey.operaciones },
      orderBy: { createdAt: "desc" },
      take: 120,
    }),
    prisma.salesForecast.findMany({
      where: { department: DepartmentKey.operaciones },
      orderBy: { weekStart: "desc" },
      take: 80,
    }),
    prisma.productionPlan.findMany({
      where: { department: DepartmentKey.operaciones },
      orderBy: { weekStart: "desc" },
      take: 80,
    }),
  ]);

  const openStates = new Set<PmWorkOrderState>(["scheduled", "in_progress", "overdue"]);
  const criticalAssets = assets.filter((asset) => asset.criticality >= 4).length;
  const downAssets = assets.filter((asset) => asset.state === "down").length;
  const activeTemplates = templates.filter((template) => template.state === "active").length;
  const openWorkOrders = workOrders.filter((order) => openStates.has(order.state)).length;
  const overdueWorkOrders = workOrders.filter((order) => order.state === "overdue").length;
  const pendingApprovals = approvals.filter((approval) => approval.state === "pending_owner" || approval.state === "submitted").length;

  const latestWeekStart = forecasts[0]?.weekStart ?? null;
  const forecastUnits = forecasts
    .filter((item) => latestWeekStart && item.weekStart.getTime() === latestWeekStart.getTime())
    .reduce((acc, item) => acc + item.forecastUnits, 0);
  const plannedUnits = plans
    .filter((item) => latestWeekStart && item.weekStart.getTime() === latestWeekStart.getTime())
    .reduce((acc, item) => acc + item.plannedUnits, 0);
  const actualVarianceUnits = plannedUnits - forecastUnits;

  const stateCounts = new Map<string, number>();
  for (const order of workOrders) {
    stateCounts.set(order.state, (stateCounts.get(order.state) ?? 0) + 1);
  }

  return {
    generatedAt: new Date().toISOString(),
    summary: {
      totalAssets: assets.length,
      criticalAssets,
      downAssets,
      activeTemplates,
      openWorkOrders,
      overdueWorkOrders,
      pendingApprovals,
      forecastUnits: Math.round(forecastUnits * 100) / 100,
      plannedUnits: Math.round(plannedUnits * 100) / 100,
      actualVarianceUnits: Math.round(actualVarianceUnits * 100) / 100,
    },
    workOrdersByState: ([
      "draft",
      "scheduled",
      "in_progress",
      "completed",
      "verified",
      "overdue",
      "cancelled",
    ] as const).map((state) => ({
      state,
      count: stateCounts.get(state) ?? 0,
    })),
    upcomingMaintenance: workOrders.slice(0, 10).map((order) => ({
      id: order.id,
      assetName: order.asset.name,
      title: order.title,
      dueBy: order.dueBy.toISOString(),
      state: order.state,
    })),
    approvalInbox: approvals.slice(0, 10).map((approval) => ({
      id: approval.id,
      requestType: approval.requestType,
      state: approval.state,
      workOrderId: approval.workOrderId,
      productionPlanId: approval.productionPlanId,
      createdAt: approval.createdAt.toISOString(),
      reason: approval.reason,
    })),
  };
}
