import * as fs from 'node:fs';
import * as path from 'node:path';
import { randomUUID } from 'node:crypto';

export type GuestbookAuthor = {
  beatleaderId: string;
  name: string | null;
  avatar: string | null;
  country: string | null;
  rank: number | null;
  techPp: number | null;
  accPp: number | null;
  passPp: number | null;
};

export type GuestbookComment = {
  id: string;
  message: string;
  author: GuestbookAuthor;
  createdAt: number;
  updatedAt: number | null;
};

type GuestbookFileData = {
  comments: GuestbookComment[];
};

const DATA_DIR = '.data';
const GUESTBOOK_FILE = 'guestbook.json';

const EMPTY_DATA: GuestbookFileData = { comments: [] };

const CONTROL_CHARS_REGEX = /[\u0000-\u001F\u007F]/g;
const HTML_TAG_REGEX = /<[^>]*>/g;
const JAVASCRIPT_PROTOCOL_REGEX = /javascript:/gi;

function sanitizeGuestbookMessage(value: string): string {
  if (!value) return '';
  const withoutTags = value.replace(HTML_TAG_REGEX, '');
  const withoutControl = withoutTags.replace(CONTROL_CHARS_REGEX, ' ');
  const withoutJsProtocol = withoutControl.replace(JAVASCRIPT_PROTOCOL_REGEX, '');
  return withoutJsProtocol.trim();
}

function ensureDataDir(): void {
  if (!fs.existsSync(DATA_DIR)) {
    fs.mkdirSync(DATA_DIR, { recursive: true });
  }
}

function resolveGuestbookPath(): string {
  return path.join(process.cwd(), DATA_DIR, GUESTBOOK_FILE);
}

function loadGuestbookFile(): GuestbookFileData {
  try {
    const filePath = resolveGuestbookPath();
    if (!fs.existsSync(filePath)) {
      return { ...EMPTY_DATA, comments: [] };
    }
    const raw = fs.readFileSync(filePath, 'utf-8');
    const parsed = JSON.parse(raw);
    if (!parsed || typeof parsed !== 'object') {
      return { ...EMPTY_DATA, comments: [] };
    }
    const comments = Array.isArray((parsed as GuestbookFileData).comments)
      ? ((parsed as GuestbookFileData).comments as GuestbookComment[])
      : [];
    return { comments };
  } catch (error) {
    console.error('Failed to read guestbook store', error);
    return { ...EMPTY_DATA, comments: [] };
  }
}

function persistGuestbookFile(data: GuestbookFileData): void {
  try {
    ensureDataDir();
    fs.writeFileSync(resolveGuestbookPath(), JSON.stringify(data, null, 2), 'utf-8');
  } catch (error) {
    console.error('Failed to persist guestbook store', error);
  }
}

export function listGuestbookComments(): GuestbookComment[] {
  const data = loadGuestbookFile();
  return [...data.comments]
    .map((comment) => ({ ...comment, message: sanitizeGuestbookMessage(comment.message) }))
    .sort((a, b) => b.createdAt - a.createdAt);
}

export function addGuestbookComment(input: {
  message: string;
  author: GuestbookAuthor;
}): GuestbookComment {
  const data = loadGuestbookFile();

  const sanitizedMessage = sanitizeGuestbookMessage(input.message);

  const comment: GuestbookComment = {
    id: randomUUID(),
    message: sanitizedMessage,
    author: input.author,
    createdAt: Date.now(),
    updatedAt: null
  };

  data.comments.push(comment);
  persistGuestbookFile(data);
  return comment;
}

export function getGuestbookComments(): GuestbookComment[] {
  return listGuestbookComments();
}

export function deleteGuestbookComment(id: string, requesterBeatleaderId: string): boolean {
  if (!id) return false;
  const data = loadGuestbookFile();
  const index = data.comments.findIndex(
    (comment) => comment.id === id && comment.author.beatleaderId === requesterBeatleaderId
  );
  if (index === -1) return false;

  data.comments.splice(index, 1);
  persistGuestbookFile(data);
  return true;
}


