"use server";

import { revalidatePath } from "next/cache";
import { api } from "../../../convex/_generated/api";
import { m, q } from "@/lib/convex-server";
import { run, type ActionResult } from "@/lib/action";
import type { Alternative } from "@/lib/inventory";

function revalidateAll(id?: string, apartmentId?: string) {
  for (const p of ["/dashboard", "/reservations", "/calendar", "/apartments", "/financials", "/payments"]) revalidatePath(p);
  if (id) revalidatePath(`/reservations/${id}`);
  if (apartmentId) revalidatePath(`/apartments/${apartmentId}`);
}
const num = (x: unknown) => (x === undefined || x === null || x === "" ? undefined : Number(x));

export async function checkAvailabilityWithAlternatives(input: { apartmentId: string; checkIn: string; checkOut: string; guests: number; excludeReservationId?: string }): Promise<ActionResult<{ available: boolean; conflicts: { kind: string; label: string; start: string; end: string }[]; alternatives: Alternative[] }>> {
  return run(async () => (await q(api.inventoryOps.checkAvailability, { apartmentId: input.apartmentId as never, checkIn: input.checkIn, checkOut: input.checkOut, guests: input.guests, excludeReservationId: input.excludeReservationId as never })) as { available: boolean; conflicts: { kind: string; label: string; start: string; end: string }[]; alternatives: Alternative[] });
}

export async function earlyCheckout(input: { id: string; actualCheckOut: string; policy: "IMMEDIATE" | "AFTER_CLEANING" | "KEEP"; refundAmount?: number; refundDeposit?: number; keysReturned: boolean; notes?: string | null }): Promise<ActionResult<{ releasedNights: number; holdId: string | null }>> {
  return run(async () => {
    const r = await m(api.inventoryOps.earlyCheckout, { ...input, refundAmount: num(input.refundAmount), refundDeposit: num(input.refundDeposit) });
    revalidateAll(input.id);
    return r;
  });
}

export async function cancelReservation(input: { id: string; reason: string; policy: "IMMEDIATE" | "APPROVAL" | "KEEP"; refundAmount?: number; refundMethod?: string }): Promise<ActionResult<{ releasedNights: number; holdId: string | null }>> {
  return run(async () => {
    const r = await m(api.inventoryOps.cancel, { ...input, refundAmount: num(input.refundAmount) });
    revalidateAll(input.id);
    return r;
  });
}

export async function releaseHold(holdId: string, reason?: string): Promise<ActionResult<undefined>> {
  return run(async () => {
    await m(api.inventoryOps.releaseHold, { holdId, reason });
    revalidateAll();
    return undefined;
  });
}

export interface BlockInput {
  apartmentId: string;
  startDate: string;
  endDate: string;
  source?: string;
  reason?: string | null;
  externalRef?: string | null;
  guestName?: string | null;
  amount?: number | null;
  notes?: string | null;
}

export async function createBlock(input: BlockInput): Promise<ActionResult<{ id: string }>> {
  return run(async () => {
    const r = await m(api.inventoryOps.createBlock, { ...input, amount: input.amount === null || input.amount === undefined || (input.amount as unknown) === "" ? null : Number(input.amount) });
    revalidateAll(undefined, input.apartmentId);
    return r;
  });
}

export async function removeBlock(blockId: string, reason?: string): Promise<ActionResult<undefined>> {
  return run(async () => {
    await m(api.inventoryOps.removeBlock, { blockId, reason });
    revalidateAll();
    return undefined;
  });
}

export async function extendStay(input: { id: string; newCheckOut: string; recalculate: boolean; reason?: string }): Promise<ActionResult<{ addedNights: number; priceDifference: number }>> {
  return run(async () => {
    const r = await m(api.inventoryOps.extendStay, input);
    revalidateAll(input.id);
    return r;
  });
}

export async function shortenStay(input: { id: string; newCheckOut: string; policy: "IMMEDIATE" | "APPROVAL" | "KEEP"; recalculate: boolean; reason?: string }): Promise<ActionResult<{ releasedNights: number; priceDifference: number }>> {
  return run(async () => {
    const r = await m(api.inventoryOps.shortenStay, input);
    revalidateAll(input.id);
    return r;
  });
}

export async function splitStay(input: { id: string; splitDate: string; newApartmentId: string; recalculate: boolean; reason?: string }): Promise<ActionResult<{ newReservationId: string; newCode: string }>> {
  return run(async () => {
    const r = await m(api.inventoryOps.splitStay, input);
    revalidateAll(input.id);
    return r;
  });
}
