/**
 * Admin Provider Management types.
 *
 * These mirror the backend Prisma schema and the `/providers/admin` controller
 * exactly — the backend is the source of truth. Notable constraints baked in
 * here so callers can't get them wrong:
 *
 * - The backend runs `ValidationPipe({ forbidNonWhitelisted: true })`, so any
 *   unknown query/body key returns 400. Request types are therefore closed —
 *   don't add convenience fields the API doesn't declare.
 * - The list endpoint has NO sort parameter (it hardcodes
 *   `orderBy: { createdAt: 'desc' }`), which is why `ProviderListParams` has no
 *   sort field and the list columns aren't marked `sortable`.
 * - `customCommissionRate` is a PERCENTAGE (0–100), not a 0–1 fraction.
 */

import type { WashPackage } from "@/types/catalog";

// ─── Enums (verbatim from backend/prisma/schema.prisma) ───────────────────────

/**
 * The backend has no TERMINATED state — the requirement doc's "terminate" has
 * no API to call, so the UI exposes only the four values below.
 */
export enum ProviderStatus {
  PENDING_VERIFICATION = "PENDING_VERIFICATION",
  ACTIVE = "ACTIVE",
  SUSPENDED = "SUSPENDED",
  REJECTED = "REJECTED",
}

/** Document verification state — named VerificationStatus backend-side */
export enum VerificationStatus {
  PENDING = "PENDING",
  APPROVED = "APPROVED",
  REJECTED = "REJECTED",
}

export enum DocumentType {
  BUSINESS_REGISTRATION = "BUSINESS_REGISTRATION",
  TRADE_LICENSE = "TRADE_LICENSE",
  NATIONAL_ID = "NATIONAL_ID",
  TAX_CERTIFICATE = "TAX_CERTIFICATE",
}

// ─── Geo ─────────────────────────────────────────────────────────────────────

/**
 * GeoJSON polygon as returned by `ST_AsGeoJSON`. Coordinates are
 * `[longitude, latitude]` (GeoJSON order — the reverse of Leaflet's LatLng),
 * outer ring first, optional holes after.
 */
export interface GeoJSONPolygon {
  type: "Polygon";
  coordinates: number[][][];
}

// ─── List ────────────────────────────────────────────────────────────────────

/** Query accepted by `GET /providers/admin` — every field optional */
export interface ProviderListParams {
  /** Matches `businessName` only (contains, case-insensitive) */
  search?: string;
  status?: ProviderStatus;
  /** 1-based */
  page?: number;
  limit?: number;
}

export interface ProviderListItem {
  id: string;
  businessName: string;
  logoUrl: string | null;
  averageRating: number;
  totalReviews: number;
  status: ProviderStatus;
  /** Percentage 0–100, or null when the platform default applies */
  customCommissionRate: number | null;
  verifiedAt: string | null;
  createdAt: string;
  updatedAt: string;
  /** Counts are nested by Prisma — not flat on the row */
  _count: {
    users: number;
    documents: number;
  };
}

export interface ProviderListResponse {
  data: ProviderListItem[];
  total: number;
  page: number;
  limit: number;
  totalPages: number;
}

// ─── Detail ──────────────────────────────────────────────────────────────────

export interface ProviderTeamMember {
  id: string;
  firstName: string;
  lastName: string;
  email: string | null;
  phoneNumber: string | null;
  role: string;
  isActive: boolean;
  createdAt: string;
}

export interface ProviderDocumentVerifier {
  id: string;
  firstName: string;
  lastName: string;
}

export interface ProviderDocument {
  id: string;
  documentType: DocumentType;
  documentUrl: string;
  status: VerificationStatus;
  rejectionReason: string | null;
  uploadedAt: string;
  verifiedAt: string | null;
  verifiedById: string | null;
  verifiedBy: ProviderDocumentVerifier | null;
}

/**
 * One admin catalog package this provider has opted into, with its own price.
 * The package itself is owned by the catalog module — see `types/catalog.ts`.
 */
export interface ProviderServiceOffering {
  id: string;
  /** Provider's own price for this package, in SAR */
  price: number;
  washPackage: WashPackage;
}

export interface ProviderDetail {
  id: string;
  businessName: string;
  logoUrl: string | null;
  averageRating: number;
  totalReviews: number;
  status: ProviderStatus;
  customCommissionRate: number | null;
  verifiedAt: string | null;
  createdAt: string;
  updatedAt: string;
  users: ProviderTeamMember[];
  documents: ProviderDocument[];
  services: ProviderServiceOffering[];
  /**
   * `null` is ambiguous backend-side: it means either "no polygon set" OR
   * "the PostGIS query failed" (the backend swallows that error and still
   * returns 200). The UI treats both as "no coverage area recorded".
   */
  coverageArea: GeoJSONPolygon | null;
}

// ─── Mutations ───────────────────────────────────────────────────────────────

/**
 * Body for `PUT /providers/admin/:id/status`.
 *
 * `status` is always required — even when the intent is only to change the
 * commission rate, the current status must be resent.
 *
 * The endpoint accepts NO reason/note field, so status changes are not
 * annotated backend-side. Omitting `customCommissionRate` preserves the stored
 * value; it cannot be cleared back to null through this endpoint.
 */
export interface UpdateProviderStatusRequest {
  status: ProviderStatus;
  /** Percentage 0–100 */
  customCommissionRate?: number;
}

/** Body for `PUT /providers/admin/:id/documents/:documentId` */
export interface VerifyDocumentRequest {
  status: VerificationStatus;
  /** Required (min 3 chars) when `status` is REJECTED; ignored otherwise */
  rejectionReason?: string;
}

/** The updated document row, returned with its verifier joined in */
export interface VerifyDocumentResponse extends ProviderDocument {
  providerId: string;
}
