import { NextResponse } from "next/server"
import { createClient } from "@/lib/supabase/server"
import { isAdminUser } from "@/lib/auth/is-admin"
import { isAllowedUntilStart, resolveReservationRules } from "@/lib/reservations/rules"

function humanizeMinutes(minutes: number | undefined) {
  if (!minutes || !Number.isFinite(minutes) || minutes <= 0) return null
  if (minutes % (24 * 60) === 0) {
    const days = minutes / (24 * 60)
    return `${days} día${days === 1 ? "" : "s"}`
  }
  if (minutes % 60 === 0) {
    const hours = minutes / 60
    return `${hours} hora${hours === 1 ? "" : "s"}`
  }
  return `${minutes} minutos`
}

function getPolicyScopeLabel(policyScope: "resource" | "resource_type" | "default") {
  switch (policyScope) {
    case "resource":
      return "de este recurso"
    case "resource_type":
      return "de este tipo de recurso"
    default:
      return "general del sistema"
  }
}

export async function POST(
  _request: Request,
  { params }: { params: Promise<{ id: string }> },
) {
  const { id } = await params
  const reservationId = id?.trim()

  if (!reservationId) {
    return NextResponse.json({ error: "El id de la reserva es obligatorio" }, { status: 400 })
  }

  const supabase = await createClient()
  const {
    data: { user },
    error: userError,
  } = await supabase.auth.getUser()

  if (userError || !user) {
    return NextResponse.json({ error: "No autorizado" }, { status: 401 })
  }

  const { data: reservation, error: reservationError } = await supabase
    .from("reservations")
    .select("id, user_id, resource_id, start_at, status")
    .eq("id", reservationId)
    .maybeSingle()

  if (reservationError) {
    return NextResponse.json({ error: "No se pudo consultar la reserva" }, { status: 500 })
  }
  if (!reservation) {
    return NextResponse.json({ error: "Reserva no encontrada" }, { status: 404 })
  }

  const canManage = reservation.user_id === user.id || isAdminUser(user)
  if (!canManage) {
    return NextResponse.json({ error: "No tienes permisos para cancelar esta reserva" }, { status: 403 })
  }
  if (reservation.status !== "confirmed") {
    return NextResponse.json({ error: "Solo se pueden cancelar reservas confirmadas" }, { status: 409 })
  }

  const { data: resource, error: resourceError } = await supabase
    .from("resources")
    .select("id, resource_type_id")
    .eq("id", reservation.resource_id)
    .maybeSingle()

  if (resourceError) {
    return NextResponse.json({ error: "No se pudo consultar el recurso" }, { status: 500 })
  }
  if (!resource) {
    return NextResponse.json({ error: "Recurso no encontrado" }, { status: 404 })
  }

  const { data: policies, error: policyError } = await supabase.from("resource_policies").select("*")
  if (policyError) {
    return NextResponse.json({ error: "No se pudieron consultar las políticas de reserva" }, { status: 500 })
  }

  const rules = resolveReservationRules({
    resourceId: resource.id,
    resourceTypeId: resource.resource_type_id,
    policies: policies ?? [],
  })

  const now = new Date()
  const canCancelNow = isAllowedUntilStart({
    now,
    startAt: reservation.start_at,
    minutesBeforeStart: rules.cancellationDeadlineMinutes,
  })

  if (!canCancelNow) {
    const readableDeadline = humanizeMinutes(rules.cancellationDeadlineMinutes)
    const scopeLabel = getPolicyScopeLabel(rules.policyScope)
    return NextResponse.json(
      {
        error: `No se puede cancelar esta reserva por la política de cancelación ${scopeLabel}${readableDeadline ? `: debía cancelarse con al menos ${readableDeadline} de anticipación.` : "."}`,
        errorCode: "CANCELLATION_POLICY_WINDOW_CLOSED",
        policyScope: rules.policyScope,
        cancellationDeadlineMinutes: rules.cancellationDeadlineMinutes,
      },
      { status: 409 },
    )
  }

  const { data: updated, error: updateError } = await (supabase.from("reservations") as any)
    .update({ status: "cancelled" })
    .eq("id", reservation.id)
    .eq("status", "confirmed")
    .select("id, status")
    .maybeSingle()

  if (updateError) {
    return NextResponse.json({ error: "No se pudo cancelar la reserva" }, { status: 500 })
  }
  if (!updated) {
    return NextResponse.json({ error: "No se pudo cancelar la reserva" }, { status: 409 })
  }

  return NextResponse.json({ ok: true, reservation: updated })
}
