import { apiClient } from './api-client';

// ─── Enums ───────────────────────────────────────────────

export type TransactionType = 'SALE' | 'RENT';
export type PropertyType = 'APARTMENT' | 'HOUSE' | 'VILLA' | 'LAND' | 'OFFICE' | 'SHOPHOUSE';
export type ListingStatus =
  | 'DRAFT'
  | 'PENDING_REVIEW'
  | 'ACTIVE'
  | 'RESERVED'
  | 'SOLD'
  | 'RENTED'
  | 'EXPIRED'
  | 'REJECTED';
export type Direction =
  | 'NORTH'
  | 'SOUTH'
  | 'EAST'
  | 'WEST'
  | 'NORTHEAST'
  | 'NORTHWEST'
  | 'SOUTHEAST'
  | 'SOUTHWEST';

export type Furnishing = 'FULLY_FURNISHED' | 'BASIC_FURNISHED' | 'UNFURNISHED';
export type PropertyCondition = 'NEW' | 'LIKE_NEW' | 'RENOVATED' | 'USED';
export type LegalStatus = 'SO_DO' | 'SO_HONG' | 'LAND_USE_RIGHT' | 'JOINT_USE_RIGHT' | 'AWAITING' | 'NO_CERTIFICATE';

export type FlagReason = 'SCAM' | 'DUPLICATE' | 'WRONG_INFO' | 'ALREADY_SOLD' | 'INAPPROPRIATE';

export interface ReportListingResult {
  flagId: string;
  listingId: string;
  totalReports: number;
  autoFlagged: boolean;
}

// ─── Interfaces ──────────────────────────────────────────

export interface PropertyMedia {
  id: string;
  url: string;
  type: 'image' | 'video';
  order: number;
  caption: string | null;
}

// ─── Enrichment types ────────────────────────────────────

export interface ValuationEstimate {
  value: string;
  confidence: number;
  modelVersion: string;
  estimatedAt: string;
}

export interface AgentQualityScore {
  score: number;
  tier: 'BRONZE' | 'SILVER' | 'GOLD' | 'PLATINUM';
}

export interface ListingSimilarItem {
  id: string;
  title: string;
  priceVND: string;
  areaM2: number;
  district: string;
  thumbnailUrl: string | null;
  publishedAt: string | null;
}

// ─── Main types ───────────────────────────────────────────

export interface ListingDetail {
  id: string;
  status: ListingStatus;
  transactionType: TransactionType;
  priceVND: string;
  pricePerM2: number | null;
  rentPriceMonthly: string | null;
  commissionPct: number | null;
  viewCount: number;
  saveCount: number;
  inquiryCount: number | null;
  publishedAt: string | null;
  createdAt: string;
  /** AVM valuation estimate — null when service is unavailable */
  valuationEstimate: ValuationEstimate | null;
  /** Agent quality score — null when no agent is assigned */
  agentQualityScore: AgentQualityScore | null;
  /** Count of active comparable listings */
  similarCount: number;
  property: {
    id: string;
    propertyType: PropertyType;
    title: string;
    description: string;
    address: string;
    ward: string;
    district: string;
    city: string;
    areaM2: number;
    usableAreaM2: number | null;
    bedrooms: number | null;
    bathrooms: number | null;
    floors: number | null;
    floor: number | null;
    totalFloors: number | null;
    direction: Direction | null;
    yearBuilt: number | null;
    legalStatus: LegalStatus | null;
    certificateVerified: boolean;
    amenities: string[] | null;
    nearbyPOIs: unknown;
    metroDistanceM: number | null;
    projectName: string | null;
    latitude: number | null;
    longitude: number | null;
    furnishing: Furnishing | null;
    propertyCondition: PropertyCondition | null;
    balconyDirection: Direction | null;
    maintenanceFeeVND: string | null;
    parkingSlots: number | null;
    viewType: string[];
    petFriendly: boolean | null;
    suitableFor: string[];
    whyThisLocation: string | null;
    media: PropertyMedia[];
    thumbnail?: string | null;
  };
  seller: {
    id: string;
    fullName: string;
    phone: string;
  };
  agent: {
    id: string;
    userId: string;
    agency: string | null;
  } | null;
}

export interface PaginatedResult<T> {
  data: T[];
  total: number;
  page: number;
  limit: number;
  totalPages: number;
}

export interface CreateListingPayload {
  transactionType: TransactionType;
  priceVND: string;
  propertyType: PropertyType;
  title: string;
  description: string;
  address: string;
  ward: string;
  district: string;
  city: string;
  latitude: number;
  longitude: number;
  areaM2: number;
  usableAreaM2?: number;
  bedrooms?: number;
  bathrooms?: number;
  floors?: number;
  floor?: number;
  totalFloors?: number;
  direction?: Direction;
  yearBuilt?: number;
  legalStatus?: string;
  amenities?: string[];
  projectName?: string;
  rentPriceMonthly?: string;
  commissionPct?: number;
  // Rich property fields (Phase B)
  furnishing?: Furnishing;
  propertyCondition?: PropertyCondition;
  balconyDirection?: Direction;
  maintenanceFeeVND?: string;
  parkingSlots?: number;
  viewType?: string[];
  petFriendly?: boolean;
  suitableFor?: string[];
  whyThisLocation?: string;
}

export interface SearchListingsParams {
  status?: ListingStatus;
  transactionType?: TransactionType;
  propertyType?: PropertyType;
  city?: string;
  district?: string;
  ward?: string;
  minPrice?: string;
  maxPrice?: string;
  minArea?: number;
  maxArea?: number;
  bedrooms?: number;
  /** Filter by assigned agent ID */
  agentId?: string;
  /** Server-side sort column */
  sortBy?: string;
  /** Sort direction */
  order?: 'asc' | 'desc';
  /** Free-text search query */
  q?: string;
  page?: number;
  limit?: number;
}

export interface PriceHistoryItem {
  id: string;
  oldPrice: string;
  newPrice: string;
  source: string;
  changedAt: string;
}

export interface NeighborhoodScoreResult {
  district: string;
  city: string;
  educationScore: number;
  healthcareScore: number;
  transportScore: number;
  shoppingScore: number;
  greeneryScore: number;
  safetyScore: number;
  totalScore: number;
  poiCounts: Record<string, number>;
  calculatedAt: string;
}

// ─── API Functions ───────────────────────────────────────

const API_BASE_URL = process.env['NEXT_PUBLIC_API_URL'] || 'http://localhost:3001/api/v1';

// eslint-disable-next-line @typescript-eslint/no-empty-object-type
export interface UpdateListingPayload extends Partial<CreateListingPayload> {}

export const listingsApi = {
  create: (data: CreateListingPayload) =>
    apiClient.post<{ listingId: string; propertyId: string; status: string }>(
      '/listings',
      data,
    ),

  update: (id: string, data: UpdateListingPayload) =>
    apiClient.patch<{ listingId: string; propertyId: string; status: string }>(
      `/listings/${id}`,
      data,
    ),

  delete: (id: string) =>
    apiClient.delete<{ success: boolean }>(`/listings/${id}`),

  getById: (id: string) => apiClient.get<ListingDetail>(`/listings/${id}`),

  search: (params: SearchListingsParams = {}) => {
    const query = new URLSearchParams();
    Object.entries(params).forEach(([key, value]) => {
      if (value !== undefined && value !== '') query.append(key, String(value));
    });
    const qs = query.toString();
    return apiClient.get<PaginatedResult<ListingDetail>>(`/listings${qs ? `?${qs}` : ''}`);
  },

  updateStatus: (id: string, status: ListingStatus, moderationNotes?: string) =>
    apiClient.post<{ status: string }>(`/listings/${id}/status`, {
      status,
      moderationNotes,
    }),

  uploadMedia: async (listingId: string, file: File, caption?: string) => {
    const formData = new FormData();
    formData.append('file', file);
    if (caption) formData.append('caption', caption);

    const csrfToken = typeof document !== 'undefined'
      ? document.cookie.match(/(?:^|;\s*)XSRF-TOKEN=([^;]*)/)?.[1]
      : undefined;

    const headers: HeadersInit = {};
    if (csrfToken) {
      headers['X-CSRF-Token'] = decodeURIComponent(csrfToken);
    }

    const res = await fetch(`${API_BASE_URL}/listings/${listingId}/media`, {
      method: 'POST',
      credentials: 'include',
      headers,
      body: formData,
    });

    if (!res.ok) {
      const error = await res.json().catch(() => ({ message: res.statusText }));
      throw new Error(error.message || 'Upload failed');
    }

    return res.json() as Promise<{ mediaId: string; url: string }>;
  },

  getPriceHistory: (listingId: string) =>
    apiClient.get<PriceHistoryItem[]>(`/listings/${listingId}/price-history`),

  getSimilar: (listingId: string, limit = 5) =>
    apiClient.get<ListingSimilarItem[]>(`/listings/${listingId}/similar?limit=${limit}`),

  getNeighborhoodScore: (district: string, city: string = 'Hồ Chí Minh') =>
    apiClient
      .get<{ data: NeighborhoodScoreResult }>(
        `/analytics/neighborhoods/${encodeURIComponent(district)}/score?city=${encodeURIComponent(city)}`,
      )
      .then((res) => res.data),

  reportListing: (listingId: string, reason: FlagReason, description?: string) =>
    apiClient.post<ReportListingResult>(`/listings/${listingId}/report`, { reason, description }),
};
