import { mutation } from "../_generated/server";
import { v } from "convex/values";
import {
  sanitizeString,
  sanitizeOptionalString,
} from "../helpers/sanitize";
import {
  vehicleTypeValidator,
  rentalStatusValidator,
  vehicleFuelTypeValidator,
  transmissionValidator,
} from "../schema/vehicles";

export const createVehicle = mutation({
  args: {
    organizationId: v.string(),
    userId: v.string(),
    make: v.string(),
    model: v.string(),
    year: v.number(),
    type: vehicleTypeValidator,
    color: v.optional(v.string()),
    licensePlate: v.optional(v.string()),
    seats: v.optional(v.number()),
    fuelType: v.optional(vehicleFuelTypeValidator),
    transmission: v.optional(transmissionValidator),
    pricePerDay: v.number(),
    pricePerWeek: v.optional(v.number()),
    pricePerMonth: v.optional(v.number()),
    currency: v.string(),
    depositAmount: v.optional(v.number()),
    descriptionEn: v.optional(v.string()),
  },
  handler: async (ctx, args) => {
    // Auth check — API layer validates ownership; warn if no identity in Convex
    const identity = await ctx.auth.getUserIdentity();
    if (!identity) {
      console.warn(
        "createVehicle called without Convex auth identity — relying on API-layer auth",
      );
    }
    const now = Date.now();
    return ctx.db.insert("vehicles", {
      ...args,
      make: sanitizeString(args.make, 100),
      model: sanitizeString(args.model, 100),
      color: sanitizeOptionalString(args.color, 50),
      licensePlate: sanitizeOptionalString(args.licensePlate, 20),
      descriptionEn: sanitizeOptionalString(args.descriptionEn, 5000),
      isAvailable: true,
      isActive: true,
      totalRentals: 0,
      totalRevenue: 0,
      createdAt: now,
      updatedAt: now,
    });
  },
});

export const updateVehicle = mutation({
  args: {
    id: v.id("vehicles"),
    make: v.optional(v.string()),
    model: v.optional(v.string()),
    year: v.optional(v.number()),
    type: v.optional(vehicleTypeValidator),
    color: v.optional(v.string()),
    licensePlate: v.optional(v.string()),
    seats: v.optional(v.number()),
    fuelType: v.optional(vehicleFuelTypeValidator),
    transmission: v.optional(transmissionValidator),
    pricePerDay: v.optional(v.number()),
    pricePerWeek: v.optional(v.number()),
    pricePerMonth: v.optional(v.number()),
    depositAmount: v.optional(v.number()),
    descriptionEn: v.optional(v.string()),
    isAvailable: v.optional(v.boolean()),
  },
  handler: async (ctx, { id, ...fields }) => {
    // Text fields that should be sanitized
    const textFieldLimits: Record<string, number> = {
      make: 100,
      model: 100,
      color: 50,
      licensePlate: 20,
      descriptionEn: 5000,
    };

    const patch: Record<string, unknown> = { updatedAt: Date.now() };
    for (const [key, value] of Object.entries(fields)) {
      if (value !== undefined) {
        if (typeof value === "string" && key in textFieldLimits) {
          patch[key] = sanitizeString(value, textFieldLimits[key]);
        } else {
          patch[key] = value;
        }
      }
    }
    await ctx.db.patch(id, patch);
  },
});

export const deleteVehicle = mutation({
  args: { id: v.id("vehicles") },
  handler: async (ctx, { id }) => {
    await ctx.db.patch(id, { isActive: false, updatedAt: Date.now() });
  },
});

export const createRental = mutation({
  args: {
    organizationId: v.string(),
    userId: v.string(),
    vehicleId: v.string(),
    customerName: v.string(),
    customerPhone: v.string(),
    customerEmail: v.optional(v.string()),
    customerLicenseNumber: v.optional(v.string()),
    pickupDate: v.number(),
    returnDate: v.number(),
    durationDays: v.number(),
    dailyRate: v.number(),
    totalAmount: v.number(),
    depositAmount: v.optional(v.number()),
    depositPaid: v.optional(v.boolean()),
    depositPaymentId: v.optional(v.string()),
    depositPaymentMethod: v.optional(v.string()),
    currency: v.string(),
    agreementNumber: v.optional(v.string()),
    notes: v.optional(v.string()),
  },
  handler: async (ctx, args) => {
    // Auth check — API layer validates ownership; warn if no identity in Convex
    const identity = await ctx.auth.getUserIdentity();
    if (!identity) {
      console.warn(
        "createRental called without Convex auth identity — relying on API-layer auth",
      );
    }
    const now = Date.now();
    const {
      depositPaid: dpPaid,
      depositPaymentId,
      depositPaymentMethod,
      agreementNumber,
      ...rest
    } = args;
    const depositPaid = dpPaid ?? false;
    const amountPaid = depositPaid && args.depositAmount ? args.depositAmount : 0;

    const id = await ctx.db.insert("vehicle_rentals", {
      ...rest,
      customerName: sanitizeString(rest.customerName, 200),
      customerPhone: sanitizeString(rest.customerPhone, 30),
      customerEmail: rest.customerEmail ? sanitizeString(rest.customerEmail, 254) : rest.customerEmail,
      customerLicenseNumber: sanitizeOptionalString(rest.customerLicenseNumber, 50),
      notes: sanitizeOptionalString(rest.notes, 5000),
      depositPaid,
      depositPaymentId,
      depositPaymentMethod,
      amountPaid,
      agreementNumber,
      status: "active",
      createdAt: now,
      updatedAt: now,
    });
    await ctx.db.patch(args.vehicleId as never, {
      isAvailable: false,
      updatedAt: now,
    });
    return id;
  },
});

export const updateRentalStatus = mutation({
  args: {
    id: v.id("vehicle_rentals"),
    status: rentalStatusValidator,
    actualReturnDate: v.optional(v.number()),
    mileageAtReturn: v.optional(v.number()),
    damageNotes: v.optional(v.string()),
  },
  handler: async (ctx, { id, status, ...extra }) => {
    const rental = await ctx.db.get(id);
    if (!rental) throw new Error("Rental not found");
    const now = Date.now();
    const sanitizedExtra = {
      ...extra,
      damageNotes: sanitizeOptionalString(extra.damageNotes, 5000),
    };
    await ctx.db.patch(id, { status, ...sanitizedExtra, updatedAt: now });
    if (status === "completed" || status === "cancelled") {
      const vehicle = await ctx.db.get(rental.vehicleId as never);
      if (vehicle) {
        const updates: Record<string, unknown> = {
          isAvailable: true,
          updatedAt: now,
        };
        if (status === "completed") {
          updates.totalRentals =
            (((vehicle as Record<string, unknown>).totalRentals as number) ||
              0) + 1;
          updates.totalRevenue =
            (((vehicle as Record<string, unknown>).totalRevenue as number) ||
              0) + rental.totalAmount;
        }
        await ctx.db.patch(rental.vehicleId as never, updates);
      }
    }
  },
});
