export interface ChatUser {
  id: string;
  firstName: string;
  lastName: string;
  avatarUrl?: string | null;
  lastActiveAt?: string | null;
}

export interface ChatMessage {
  id: string;
  conversationId: string;
  senderId: string;
  content: string;
  metadata?: Record<string, unknown> | null;
  isRead: boolean;
  readAt?: string | null;
  createdAt: string;
  sender: ChatUser;
}

export interface Conversation {
  id: string;
  jobId?: string | null;
  contextWorkerId?: string | null;
  updatedAt: string;
  unreadCount?: number;
  relatedConversationIds?: string[];
  jobCount?: number;
  /** Most recent message sender who is not the viewing user (from API list/detail). */
  otherParticipant?: ChatUser | null;
  contextWorker?: {
    id: string;
    displayName?: string | null;
    user: ChatUser;
  } | null;
  job?: {
    id: string;
    title: string;
    location?: string;
    budget?: number | string | null;
    status?: string;
    category?: { name: string };
    customerId?: string | null;
    workerId?: string | null;
    customer?: ChatUser;
    worker?: { id?: string; user: ChatUser };
    quotations?: {
      status: string;
      worker: { id: string; user: ChatUser };
    }[];
  } | null;
  messages: ChatMessage[];
}

function resolveWorkerUser(
  job: NonNullable<Conversation['job']>,
  preferredWorkerId?: string
): ChatUser | null {
  if (job.worker?.user) return job.worker.user;

  const quotations = job.quotations ?? [];
  if (preferredWorkerId) {
    const match = quotations.find((q) => q.worker.id === preferredWorkerId);
    if (match?.worker.user) return match.worker.user;
  }

  const pending = quotations.find((q) => q.status === 'PENDING');
  if (pending?.worker.user) return pending.worker.user;

  const accepted = quotations.find((q) => q.status === 'ACCEPTED');
  return accepted?.worker.user ?? null;
}

function getOtherFromLastMessage(
  conversation: Conversation,
  currentUserId: string
): ChatUser | null {
  const last = conversation.messages[0];
  if (last && last.senderId !== currentUserId) return last.sender;
  return null;
}

function resolveCustomerWorkerName(
  conversation: Conversation,
  currentUserId: string,
  preferredWorkerId?: string
): ChatUser | null {
  const job = conversation.job;
  if (!job || job.customerId !== currentUserId) return null;

  return (
    resolveWorkerUser(job, preferredWorkerId) ??
    conversation.otherParticipant ??
    getOtherFromLastMessage(conversation, currentUserId)
  );
}

export function getConversationTitle(
  conversation: Conversation,
  currentUserId: string,
  preferredWorkerId?: string
): string {
  const job = conversation.job;
  if (!job) {
    const other =
      conversation.otherParticipant ?? getOtherFromLastMessage(conversation, currentUserId);
    if (other) return `${other.firstName} ${other.lastName}`;
    return 'Conversation';
  }

  if (job.customerId === currentUserId) {
    const workerUser = resolveCustomerWorkerName(conversation, currentUserId, preferredWorkerId);
    if (workerUser) {
      return `${workerUser.firstName} ${workerUser.lastName}`;
    }
  }
  if (job.customer && job.customerId !== currentUserId) {
    return `${job.customer.firstName} ${job.customer.lastName}`;
  }
  return job.title;
}

export function getConversationSubtitle(conversation: Conversation): string {
  const jobCount = conversation.jobCount ?? 0;
  if (jobCount > 1) {
    return `${jobCount} jobs`;
  }
  if (conversation.job?.title) return conversation.job.title;
  return 'Direct message';
}

export function formatMessageDayLabel(date: string) {
  const d = new Date(date);
  const now = new Date();
  const startToday = new Date(now.getFullYear(), now.getMonth(), now.getDate());
  const startMsg = new Date(d.getFullYear(), d.getMonth(), d.getDate());
  const diffDays = Math.round((startToday.getTime() - startMsg.getTime()) / 86400000);

  if (diffDays === 0) return 'Today';
  if (diffDays === 1) return 'Yesterday';
  return d.toLocaleDateString('en-PH', {
    weekday: 'short',
    month: 'short',
    day: 'numeric',
    year: d.getFullYear() !== now.getFullYear() ? 'numeric' : undefined,
  });
}

export function isSameMessageDay(a: string, b: string) {
  const da = new Date(a);
  const db = new Date(b);
  return (
    da.getFullYear() === db.getFullYear() &&
    da.getMonth() === db.getMonth() &&
    da.getDate() === db.getDate()
  );
}

export function conversationMatchesThread(
  conversation: Conversation,
  threadId?: string
): boolean {
  if (!threadId) return false;
  if (conversation.id === threadId) return true;
  return conversation.relatedConversationIds?.includes(threadId) ?? false;
}

export function getConversationJobHref(
  conversation: Conversation,
  role: 'customer' | 'worker'
): string | null {
  const jobId = conversation.job?.id ?? conversation.jobId;
  if (!jobId) return null;
  return role === 'worker' ? `/worker/jobs/${jobId}` : `/customer/jobs/${jobId}`;
}

export function getConversationOtherUser(
  conversation: Conversation,
  currentUserId: string,
  preferredWorkerId?: string
): ChatUser | null {
  const job = conversation.job;
  if (!job) {
    return conversation.otherParticipant ?? getOtherFromLastMessage(conversation, currentUserId);
  }

  if (job.customerId === currentUserId) {
    return resolveCustomerWorkerName(conversation, currentUserId, preferredWorkerId);
  }
  if (job.customer && job.customerId !== currentUserId) {
    return job.customer;
  }
  return conversation.otherParticipant ?? null;
}

export function formatMessageTime(date: string) {
  const d = new Date(date);
  const now = new Date();
  const isToday = d.toDateString() === now.toDateString();
  if (isToday) {
    return d.toLocaleTimeString('en-PH', { hour: 'numeric', minute: '2-digit' });
  }
  return d.toLocaleDateString('en-PH', { month: 'short', day: 'numeric' });
}
