import { api } from '../auth/http';
import { URL_CONSTANTS } from '@/constants/URLS';
import type { FeePreview } from '@/types/warehouse';

export const LAST_MILE_STATUSES = [
  'PAYMENT_PENDING',
  'READY_TO_TRANSIT',
  'IN_TRANSIT',
  'DELIVERED',
] as const;
export type LastMileApiStatus = (typeof LAST_MILE_STATUSES)[number];

export interface LastMileBooking {
  id: string;
  reference: string;
  lastMileDeliveryAddress?: string | null;
  cargoFreeText?: string | null;
  cargoTotalWeightVgm: number;
  totalAmount: number;
  paymentCurrency?: string | null;
  scheduledDate?: string | null;
  company?: { id: string; name?: string; phone?: string | null; contactPersonName?: string | null; contactPersonPhone?: string | null } | null;
  serviceType?: { id: string; name?: string; label?: string } | null;
  originYard?: { id: string; name?: string; label?: string } | null;
  destinationYard?: { id: string; name?: string; label?: string } | null;
  cargoType?: { id: string; name?: string; label?: string; cargoTypeName?: string } | null;
  /** Container lines — total container count drives how many trucks are needed. */
  bookingContainers?: Array<{
    id: string;
    quantity: number;
    containerNumber?: string | null;
    containerSize?: string | null;
    containerType?: { id: string; name?: string; label?: string; code?: string } | null;
    /** Physical containers under this line — their real numbers (line-level
     *  containerNumber is often a TBD placeholder). */
    units?: Array<{ id: string; containerNumber?: string | null; sortOrder?: number }>;
  }>;
}

export interface LastMileVehicle {
  id: string;
  plateNumber: string;
  manufacturer: string;
  model: string;
  vehicleType?: string | null;
  code?: string | null;
  powerPlateNo?: string | null;
  trailerPlateNo?: string | null;
  assignedDriverId?: string | null;
  assignedDriverName?: string | null;
  pricePerKm?: number | string | null;
  currency?: string | null;
}

export interface LastMileRecord {
  id: string;
  bookingId: string;
  status: LastMileApiStatus;
  advancedPayment: number;
  remainingPayment: number;
  estimatedKm?: number | null;
  exactKm?: number | null;
  vehicleId?: string | null;
  booking?: LastMileBooking | null;
  vehicle?: LastMileVehicle | null;
  /** Full set of vehicles serving this delivery (multi-truck). */
  vehicleAssignments?: Array<{
    id: string;
    vehicleId: string;
    /** @deprecated Legacy single container — `containers` is authoritative. */
    containerNumber?: string | null;
    /** Containers riding this truck: one 40ft, or up to two 20ft. */
    containers?: Array<{ id: string; containerNumber: string }>;
    distanceKm?: number | null;
    /** Per-truck arrival / exit, stamped by the warehouse weighing steps. */
    arrivedAt?: string | null;
    departedAt?: string | null;
    grossWeightTons?: number | null;
    netWeightTons?: number | null;
    vehicle?: LastMileVehicle | null;
  }>;
  /** Present only when an invoice has actually been generated (not on distance). */
  invoice?: { id: string; number: string; status: string } | null;
  /** Truck-detention clock: vehicle arrival + delivery/return times. */
  arrivedAt?: string | null;
  deliveredAt?: string | null;
  createdAt: string;
  updatedAt: string;
}

export interface LastMileListResponse {
  data: LastMileRecord[];
  meta: { total: number; page: number; pageSize: number; totalPages: number };
}

const LM = URL_CONSTANTS.LAST_MILE;

export const lastMileService = {
  list: (pageSize = 1000) =>
    api.get<LastMileListResponse>(`${LM.BASE}?pageSize=${pageSize}`),
  getById: (id: string) => api.get<LastMileRecord>(LM.BY_ID(id)),
  update: (id: string, data: { status?: LastMileApiStatus; vehicleId?: string | null; estimatedKm?: number | null; exactKm?: number | null; paid?: boolean; arrivedAt?: string | null; deliveredAt?: string | null }) =>
    api.patch<LastMileRecord>(LM.BY_ID(id), data),
  accept: (bookingReference: string) =>
    api.post<LastMileRecord>(LM.ACCEPT(encodeURIComponent(bookingReference))),
  remove: (id: string) =>
    api.delete<void>(LM.BY_ID(id)),
  setVehicles: (
    id: string,
    vehicles: Array<{ vehicleId: string; containerNumbers?: string[] }>,
  ) => api.post<LastMileRecord>(`${LM.BASE}/${id}/vehicles`, { vehicles }),
  /** Bulk drawdown: tonnage still to be hauled on this booking. */
  remainingTons: (bookingId: string) =>
    api.get<{ totalTons: number; hauledTons: number; remainingTons: number; complete: boolean }>(
      `${LM.BASE}/booking/${bookingId}/remaining-tons`,
    ),
  setDistances: (
    id: string,
    distances: Array<{ vehicleId: string; distanceKm: number }>,
    remainingPayment?: number,
  ) => api.post<LastMileRecord>(`${LM.BASE}/${id}/distances`, { distances, remainingPayment }),
  generateInvoice: (id: string) =>
    api.post<{ id: string; invoiceNumber?: string } | null>(`${LM.BASE}/${id}/invoice`),
  /** Record proof of delivery (recipient signature + photos) and complete the leg. */
  recordProofOfDelivery: (
    id: string,
    payload: { recipientName: string; notes?: string; signature?: Blob | null; photos?: File[] },
  ) => {
    const form = new FormData();
    form.append("recipientName", payload.recipientName);
    if (payload.notes) form.append("notes", payload.notes);
    if (payload.signature) form.append("signature", payload.signature, "signature.png");
    (payload.photos ?? []).forEach((photo) => form.append("photos", photo));
    return api.post<LastMileRecord>(LM.PROOF_OF_DELIVERY(id), form, {
      headers: { "Content-Type": "multipart/form-data" },
    });
  },
  /** Generate a truck-detention invoice (per truck per day after the grace window). */
  generateTruckDetentionInvoice: (id: string) =>
    api.post<{ id: string; invoiceNumber?: string } | null>(
      `${LM.BASE}/${id}/generate-truck-detention-invoice`,
    ),
  /** Preview the truck-detention charge for a last-mile leg. */
  truckDetentionPreview: (id: string) =>
    api.get<FeePreview>(`${LM.BASE}/${id}/truck-detention-preview`),
};
