/**
 * useVendorDashboardData - react-query loader for vendor dashboard (FDS §5.2).
 *
 * Maps the GET /api/vendor/dashboard response to the internal data shape consumed
 * by VendorDashboard and VendorWelcomeWrapper.
 *
 * API response shape:
 *   { ok, metrics: { totalRevenue, customerCount, returnPercent },
 *     deals: RawDeal[], insight: string, notifications: ApiNotification[] }
 *
 * Internal shape (VendorDashboardData):
 *   { metrics: { earnedThisMonth, customersThisMonth, returnedToBuy },
 *     activeDeals: VendorActiveDeal[], dailyInsight: string | null,
 *     notifications: VendorNotification[], hasAnyDeals: boolean }
 */

'use client';

import { keepPreviousData, useQuery } from '@tanstack/react-query';
import type { DealState as RegistryDealState } from '@/lib/enums/deal-state';
import type { ImageRejectionNotification } from '@/components/ui/domain/RejectionBannerList';
import type { DashboardPrefetchDescriptor } from '@/lib/query/prefetch-registry';

export interface VendorKpiDeltas {
  revenueDelta: number;
  ordersDelta: number;
  ratingDelta: number | null;
}

export interface VendorMetrics {
  earnedThisMonth: number;
  customersThisMonth: number;
  returnedToBuy: number;
  activeDealsCount: number;
  deltas: VendorKpiDeltas | null;
}

export interface VendorActiveDeal {
  id: string;
  title: string;
  dealType?: string;
  vendorName: string;
  imageSrc: string;
  imageAlt: string;
  // vendor dashboard list excludes DRAFT/UNDER_REVIEW/ARCHIVED
  state: Exclude<RegistryDealState, 'DRAFT' | 'UNDER_REVIEW' | 'ARCHIVED'>;
  stockRemaining: number;
  stockTotal: number;
  windowEnd: string;
}

export interface VendorNotification {
  id: string;
  type: 'sale' | 'return' | 'personal_deal_request' | 'team_message' | 'purchase_message';
  title: string;
  sub?: string;
  tone: 'success' | 'warning' | 'danger' | 'neutral';
  timestamp: string;
  actionHref?: string;
  actionLabel?: string;
}

export interface VendorFeedEvent {
  id: string;
  eventType: string;
  createdAt: string;
  payload: Record<string, unknown>;
}

export interface VendorAiRec {
  id: string;
  kind: string;
  payload: Record<string, unknown>;
  createdAt: string;
}

export interface VendorInfo {
  id: string;
  businessName: string;
  displayName: string;
  accountState: string;
  email: string;
  flagReason: string | null;
  rejectReason: string | null;
  draftsCount: number;
  stripeAccountId: string | null;
  stripeOnboardingState: string | null;
  imageRejections: ImageRejectionNotification[];
}

export interface VendorDashboardData {
  vendor: VendorInfo | null;
  metrics: VendorMetrics;
  activeDeals: VendorActiveDeal[];
  topActiveDeals: VendorActiveDeal[];
  feedEvents: VendorFeedEvent[];
  aiRecs: VendorAiRec[];
  dailyInsight: string | null;
  notifications: VendorNotification[];
  hasAnyDeals: boolean;
}

// ─── Raw API response shape ────────────────────────────────────────────────────

interface ApiPeriodComparison {
  deltas: {
    revenueDelta: number;
    ordersDelta: number;
    ratingDelta: number | null;
  };
}

interface ApiMetrics {
  earnedThisMonth: number;
  customersThisMonth: number;
  returnedToBuyCount: number;
  activeDealsCount: number;
  periodComparison: ApiPeriodComparison | null;
}

interface ApiDeal {
  id: string;
  title: string;
  dealType?: string;
  dealState: string;
  heroImageUrl?: string | null;
  quantityTotal: number;
  quantitySold: number;
  quantityRemaining?: number;
  revenueTotal?: number;
  windowEnd?: string | null;
  vendorId?: string;
}

interface ApiNotification {
  id: string;
  type?: string;
  message: string;
  severity?: string;
  createdAt: string;
}

interface ApiFeedEvent {
  id: string;
  eventType: string;
  createdAt: string;
  payload: Record<string, unknown>;
}

interface ApiAiRec {
  id: string;
  kind: string;
  payload: Record<string, unknown>;
  createdAt: string;
}

interface ApiVendor {
  id: string;
  businessName: string;
  displayName: string;
  accountState: string;
  email: string;
  flagReason: string | null;
  rejectReason: string | null;
  draftsCount: number;
  stripeAccountId: string | null;
  stripeOnboardingState: string | null;
  imageRejections: ImageRejectionNotification[];
}

interface ApiResponse {
  ok: boolean;
  vendor?: ApiVendor;
  metrics: ApiMetrics;
  deals: ApiDeal[];
  topActiveDeals: ApiDeal[];
  feedEvents: ApiFeedEvent[];
  aiRecs: ApiAiRec[];
  insight: string;
  notifications: ApiNotification[];
}

export const VENDOR_DASHBOARD_QUERY_KEY = ['vendor-dashboard'] as const;
export type VendorDashboardApiResponse = ApiResponse;

// ─── Mapping helpers ───────────────────────────────────────────────────────────

const VALID_STATES = new Set([
  'ACTIVE',
  'PENDING_APPROVAL',
  'REJECTED',
  'EXPIRED',
  'SOLD_OUT',
  'PAUSED',
]);

function toValidDealState(raw: string): VendorActiveDeal['state'] {
  // UNDER_REVIEW (freshly submitted, awaiting LLM moderation) and PENDING_APPROVAL
  // (admin queue) both surface to the vendor as a single "pending" state. Without this
  // translation, UNDER_REVIEW deals fall through to 'EXPIRED' and disappear from the
  // dashboard list right after submission.
  if (raw === 'UNDER_REVIEW') return 'PENDING_APPROVAL';
  return VALID_STATES.has(raw) ? (raw as VendorActiveDeal['state']) : 'EXPIRED';
}

function toNotificationTone(type: string): VendorNotification['tone'] {
  if (type === 'sale') return 'success';
  if (type === 'return') return 'warning';
  if (type === 'personal_deal_request') return 'warning';
  return 'neutral';
}

function severityToTone(severity: string | undefined): VendorNotification['tone'] | null {
  if (severity === 'error' || severity === 'danger') return 'danger';
  if (severity === 'warning') return 'warning';
  if (severity === 'success') return 'success';
  if (severity === 'info') return 'neutral';
  return null;
}

function toValidNotificationType(type: string | undefined): VendorNotification['type'] {
  const valid: VendorNotification['type'][] = [
    'sale',
    'return',
    'personal_deal_request',
    'team_message',
    'purchase_message',
  ];
  return valid.includes(type as VendorNotification['type'])
    ? (type as VendorNotification['type'])
    : 'team_message';
}

function mapApiDeal(d: ApiDeal): VendorActiveDeal {
  return {
    id: d.id,
    title: d.title,
    dealType: d.dealType,
    vendorName: '',
    imageSrc: d.heroImageUrl ?? '',
    imageAlt: d.title,
    state: toValidDealState(d.dealState),
    stockRemaining:
      d.quantityRemaining !== undefined ? d.quantityRemaining : d.quantityTotal - d.quantitySold,
    stockTotal: d.quantityTotal,
    windowEnd: d.windowEnd ?? new Date().toISOString(),
  };
}

export function mapVendorDashboardApiResponse(raw: ApiResponse): VendorDashboardData {
  const vendor: VendorInfo | null = raw.vendor
    ? {
        id: raw.vendor.id,
        businessName: raw.vendor.businessName,
        displayName: raw.vendor.displayName,
        accountState: raw.vendor.accountState,
        email: raw.vendor.email,
        flagReason: raw.vendor.flagReason,
        rejectReason: raw.vendor.rejectReason,
        draftsCount: raw.vendor.draftsCount,
        stripeAccountId: raw.vendor.stripeAccountId,
        stripeOnboardingState: raw.vendor.stripeOnboardingState,
        imageRejections: raw.vendor.imageRejections ?? [],
      }
    : null;

  const deltas = raw.metrics.periodComparison?.deltas ?? null;
  const metrics: VendorMetrics = {
    earnedThisMonth: raw.metrics.earnedThisMonth ?? 0,
    customersThisMonth: raw.metrics.customersThisMonth ?? 0,
    returnedToBuy: raw.metrics.returnedToBuyCount ?? 0,
    activeDealsCount: raw.metrics.activeDealsCount ?? 0,
    deltas,
  };

  const activeDeals: VendorActiveDeal[] = raw.deals.map(mapApiDeal);
  const topActiveDeals: VendorActiveDeal[] = (raw.topActiveDeals ?? []).map(mapApiDeal);

  const feedEvents: VendorFeedEvent[] = (raw.feedEvents ?? []).map((e) => ({
    id: e.id,
    eventType: e.eventType,
    createdAt: e.createdAt,
    payload: e.payload ?? {},
  }));

  const aiRecs: VendorAiRec[] = (raw.aiRecs ?? []).map((r) => ({
    id: r.id,
    kind: r.kind,
    payload: r.payload ?? {},
    createdAt: r.createdAt,
  }));

  const notifications: VendorNotification[] = raw.notifications.map((n) => ({
    id: n.id,
    type: toValidNotificationType(n.type),
    title: n.message,
    tone: severityToTone(n.severity) ?? toNotificationTone(n.type ?? ''),
    timestamp: n.createdAt,
    sub: n.severity ? String(n.severity) : undefined,
  }));

  return {
    vendor,
    metrics,
    activeDeals,
    topActiveDeals,
    feedEvents,
    aiRecs,
    dailyInsight: raw.insight || null,
    notifications,
    hasAnyDeals: raw.deals.length > 0,
  };
}

// ─── Fetch + hook ──────────────────────────────────────────────────────────────

async function fetchDashboard(): Promise<VendorDashboardData> {
  // Retry on 503 (CF Workers Free tier CPU ceiling) — up to 4 attempts with back-off
  for (let attempt = 0; attempt < 4; attempt++) {
    if (attempt > 0) await new Promise<void>((r) => setTimeout(r, 1000 * attempt));
    const res = await fetch('/api/vendor/dashboard');
    if (res.status === 503 && attempt < 3) continue;
    if (!res.ok) throw new Error('Failed to load dashboard data');
    const raw = (await res.json()) as ApiResponse | { data: ApiResponse };
    return mapVendorDashboardApiResponse('data' in raw ? raw.data : raw);
  }
  throw new Error('Service temporarily unavailable');
}

export const VENDOR_DASHBOARD_PREFETCH_DESCRIPTOR = {
  href: '/vendor/dashboard',
  queryKey: VENDOR_DASHBOARD_QUERY_KEY,
  queryFn: fetchDashboard,
  staleTime: 5 * 60_000,
  gcTime: 10 * 60_000,
} satisfies DashboardPrefetchDescriptor;

export function useVendorDashboardData(options?: { enabled?: boolean }) {
  return useQuery<VendorDashboardData, Error>({
    queryKey: VENDOR_DASHBOARD_PREFETCH_DESCRIPTOR.queryKey,
    queryFn: VENDOR_DASHBOARD_PREFETCH_DESCRIPTOR.queryFn,
    placeholderData: keepPreviousData,
    staleTime: VENDOR_DASHBOARD_PREFETCH_DESCRIPTOR.staleTime,
    gcTime: VENDOR_DASHBOARD_PREFETCH_DESCRIPTOR.gcTime,
    refetchInterval: 60_000,
    enabled: options?.enabled ?? true,
  });
}
