"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 { RISK_LEVELS, VERIFICATION_STATUSES } from "@/lib/domain";

export interface CustomerInput {
  firstName: string;
  lastName: string;
  phone: string;
  secondaryPhone?: string | null;
  email?: string | null;
  nationality?: string | null;
  dateOfBirth?: string | null;
  idType?: string | null;
  idNumber?: string | null;
  idExpiration?: string | null;
  address?: string | null;
  preferredLanguage?: "fr" | "ar" | "en" | "es";
  notes?: string | null;
}

export interface DuplicateMatch {
  id: string;
  code: string;
  fullName: string;
  phone: string;
  idNumber: string | null;
  email: string | null;
  reason: string;
  confidence: number;
  fields: ("idNumber" | "phone" | "email" | "name")[];
  reservations: number;
}

const nul = <T,>(x: T | "" | undefined | null) => (x === "" || x === undefined ? null : x);
const clean = (d: CustomerInput) => ({ firstName: d.firstName, lastName: d.lastName, phone: d.phone, secondaryPhone: nul(d.secondaryPhone), email: nul(d.email), nationality: nul(d.nationality), dateOfBirth: nul(d.dateOfBirth), idType: nul(d.idType), idNumber: nul(d.idNumber), idExpiration: nul(d.idExpiration), address: nul(d.address), preferredLanguage: d.preferredLanguage ?? "fr", notes: nul(d.notes) });
const rev = (id?: string) => {
  revalidatePath("/customers");
  revalidatePath("/customers/risk");
  if (id) revalidatePath(`/customers/${id}`);
};

export async function findDuplicates(input: { phone?: string; idNumber?: string; email?: string; firstName?: string; lastName?: string; excludeId?: string }): Promise<DuplicateMatch[]> {
  try {
    return (await q(api.customers.findDuplicates, { phone: input.phone ?? null, idNumber: input.idNumber ?? null, email: input.email ?? null, firstName: input.firstName ?? null, lastName: input.lastName ?? null, excludeId: (input.excludeId ?? null) as never })) as DuplicateMatch[];
  } catch {
    return [];
  }
}

export async function createCustomer(input: CustomerInput, opts: { ignoreDuplicates?: boolean } = {}): Promise<ActionResult<{ id: string; code: string; duplicates?: DuplicateMatch[] }>> {
  return run(async () => {
    const r = await m(api.customers.create, { ...clean(input), ignoreDuplicates: opts.ignoreDuplicates });
    rev();
    return r;
  });
}

export async function updateCustomer(id: string, input: CustomerInput): Promise<ActionResult<undefined>> {
  return run(async () => {
    await m(api.customers.update, { id, ...clean(input) });
    rev(id);
    return undefined;
  });
}

export async function setCustomerAvatar(customerId: string, avatarIndex: number | null): Promise<ActionResult<undefined>> {
  return run(async () => {
    await m(api.customers.setAvatar, { customerId, avatarIndex });
    rev(customerId);
    return undefined;
  });
}

export async function addCustomerNote(customerId: string, body: string): Promise<ActionResult<undefined>> {
  return run(async () => {
    await m(api.customers.addNote, { customerId, body });
    rev(customerId);
    return undefined;
  });
}

export async function toggleBlacklist(customerId: string, value: boolean, reason: string): Promise<ActionResult<undefined>> {
  return run(async () => {
    await m(api.customers.toggleBlacklist, { customerId, value, reason });
    rev(customerId);
    return undefined;
  });
}

export async function deleteCustomer(id: string, reason: string): Promise<ActionResult<undefined>> {
  return run(async () => {
    await m(api.customers.remove, { id, reason });
    rev();
    return undefined;
  });
}

export async function setCustomerRisk(customerId: string, level: (typeof RISK_LEVELS)[number], reason: string): Promise<ActionResult<undefined>> {
  return run(async () => {
    await m(api.customers.setRisk, { customerId, level, reason });
    rev(customerId);
    return undefined;
  });
}

export interface IncidentInput {
  customerId: string;
  reservationId?: string | null;
  type: string;
  severity?: string;
  title: string;
  description?: string | null;
  amount?: number | null;
  occurredAt?: string | null;
}

export async function recordIncident(input: IncidentInput): Promise<ActionResult<{ id: string; code: string }>> {
  return run(async () => {
    const r = await m(api.customers.recordIncident, { customerId: input.customerId, reservationId: nul(input.reservationId), type: input.type, severity: input.severity, title: input.title, description: nul(input.description), amount: input.amount === null || input.amount === undefined || (input.amount as unknown) === "" ? null : Number(input.amount), occurredAt: nul(input.occurredAt) });
    rev(input.customerId);
    return r;
  });
}

export async function resolveIncident(id: string, resolution: string): Promise<ActionResult<undefined>> {
  return run(async () => {
    await m(api.customers.resolveIncident, { id, resolution });
    rev();
    return undefined;
  });
}

export async function setVerification(customerId: string, status: (typeof VERIFICATION_STATUSES)[number]): Promise<ActionResult<undefined>> {
  return run(async () => {
    await m(api.customers.setVerification, { customerId, status });
    rev(customerId);
    return undefined;
  });
}

export async function requestRiskApproval(customerId: string, note: string, dates?: { checkIn: string; checkOut: string; apartmentId?: string }): Promise<ActionResult<undefined>> {
  return run(async () => {
    await m(api.customers.requestRiskApproval, { customerId, note, dates });
    return undefined;
  });
}

export async function mergeCustomers(winnerId: string, loserId: string, reason: string): Promise<ActionResult<{ moved: Record<string, number> }>> {
  return run(async () => {
    const r = await m(api.customers.merge, { winnerId, loserId, reason });
    rev(winnerId);
    return r as { moved: Record<string, number> };
  });
}
