import { existsSync } from 'node:fs';

import db from './sqlite';

interface MediaRow {
  id: number;
  chat_id: number;
  message_id: number;
  user_id: number;
  username: null | string;
  display_name: null | string;
  file_type: string;
  file_id: string;
  file_unique_id: null | string;
  caption: null | string;
  file_name: null | string;
  file_path: string;
  file_size: null | number;
  mime_type: null | string;
  duration: null | number;
  width: null | number;
  height: null | number;
  forwarded_to: null | number;
  created_at: string;
  updated_at: string;
}

export interface MediaMessage {
  id: number;
  chatId: number;
  messageId: number;
  userId: number;
  username?: string;
  displayName?: string;
  fileType: string;
  fileId: string;
  fileUniqueId?: string;
  caption?: string;
  fileName?: string;
  filePath: string;
  fileSize?: number;
  mimeType?: string;
  duration?: number;
  width?: number;
  height?: number;
  forwardedTo?: number;
  createdAt: string;
  updatedAt: string;
  available: boolean;
  downloadUrl: string | null;
}

function mapMediaRow(row: MediaRow): MediaMessage {
  const fileExists = existsSync(row.file_path);
  return {
    id: row.id,
    chatId: row.chat_id,
    messageId: row.message_id,
    userId: row.user_id,
    username: row.username ?? undefined,
    displayName: row.display_name ?? undefined,
    fileType: row.file_type,
    fileId: row.file_id,
    fileUniqueId: row.file_unique_id ?? undefined,
    caption: row.caption ?? undefined,
    fileName: row.file_name ?? undefined,
    filePath: row.file_path,
    fileSize: row.file_size ?? undefined,
    mimeType: row.mime_type ?? undefined,
    duration: row.duration ?? undefined,
    width: row.width ?? undefined,
    height: row.height ?? undefined,
    forwardedTo: row.forwarded_to ?? undefined,
    createdAt: row.created_at,
    updatedAt: row.updated_at,
    available: fileExists,
    downloadUrl: fileExists ? `/finance/media/${row.id}/download` : null,
  };
}

export function fetchMediaMessages(params: {
  limit?: number;
  fileTypes?: string[];
} = {}) {
  const clauses: string[] = [];
  const bindParams: Record<string, unknown> = {};

  if (params.fileTypes && params.fileTypes.length > 0) {
    clauses.push(
      `file_type IN (${params.fileTypes.map((_, index) => `@type${index}`).join(', ')})`,
    );
    params.fileTypes.forEach((type, index) => {
      bindParams[`type${index}`] = type;
    });
  }

  const where = clauses.length > 0 ? `WHERE ${clauses.join(' AND ')}` : '';
  const limitClause =
    params.limit && params.limit > 0 ? `LIMIT ${Number(params.limit)}` : '';

  const stmt = db.prepare<MediaRow>(
    `SELECT id, chat_id, message_id, user_id, username, display_name, file_type, file_id, file_unique_id, caption, file_name, file_path, file_size, mime_type, duration, width, height, forwarded_to, created_at, updated_at FROM finance_media_messages ${where} ORDER BY datetime(created_at) DESC, id DESC ${limitClause}`,
  );

  return stmt.all(bindParams).map(mapMediaRow);
}

export function getMediaMessageById(id: number) {
  const stmt = db.prepare<MediaRow>(
    `SELECT id, chat_id, message_id, user_id, username, display_name, file_type, file_id, file_unique_id, caption, file_name, file_path, file_size, mime_type, duration, width, height, forwarded_to, created_at, updated_at FROM finance_media_messages WHERE id = ?`,
  );

  const row = stmt.get(id);

  return row ? mapMediaRow(row) : null;
}

