import { randomUUID } from 'crypto';
import { readPersistentDataFile, writePersistentDataFile } from './local-store';

export type AgentDentalKnowledgeAudience = 'staff' | 'patient' | 'doctor-mobile' | 'guest';

export type AgentDentalKnowledgeAction = {
  label: string;
  path: string;
  description?: string;
};

export type StoredAgentDentalKnowledgeArticle = {
  id: string;
  title: string;
  summary: string;
  answer: string;
  audience: AgentDentalKnowledgeAudience[];
  keywords: string[];
  steps: string[];
  actions: AgentDentalKnowledgeAction[];
  relatedContextIds: string[];
  source: 'custom';
  createdAt: string;
  updatedAt: string;
  createdBy: string | null;
};

type AgentDentalKnowledgeInput = {
  id?: string;
  title: string;
  summary: string;
  answer: string;
  audience: AgentDentalKnowledgeAudience[];
  keywords?: string[];
  steps?: string[];
  actions?: AgentDentalKnowledgeAction[];
  relatedContextIds?: string[];
  createdBy?: string | null;
  createdAt?: string;
};

const knowledgeFileName = 'agent-dental-knowledge.json';
const allowedAudience = new Set<AgentDentalKnowledgeAudience>(['staff', 'patient', 'doctor-mobile', 'guest']);

const normalizeString = (value: unknown) => (typeof value === 'string' ? value.trim() : '');

const normalizeStringList = (value: unknown, limit = 16) => {
  if (!Array.isArray(value)) {
    return [];
  }

  const items: string[] = [];
  const seen = new Set<string>();

  for (const entry of value) {
    const nextValue = normalizeString(entry);

    if (!nextValue || seen.has(nextValue)) {
      continue;
    }

    seen.add(nextValue);
    items.push(nextValue);

    if (items.length >= limit) {
      break;
    }
  }

  return items;
};

const normalizeAudienceList = (value: unknown) =>
  normalizeStringList(value, 4).filter((entry): entry is AgentDentalKnowledgeAudience =>
    allowedAudience.has(entry as AgentDentalKnowledgeAudience),
  );

const normalizeActionList = (value: unknown) => {
  if (!Array.isArray(value)) {
    return [];
  }

  const items: AgentDentalKnowledgeAction[] = [];
  const seen = new Set<string>();

  for (const entry of value) {
    const label = normalizeString((entry as AgentDentalKnowledgeAction | undefined)?.label);
    const path = normalizeString((entry as AgentDentalKnowledgeAction | undefined)?.path);
    const description = normalizeString((entry as AgentDentalKnowledgeAction | undefined)?.description);
    const key = `${label}:${path}`;

    if (!label || !path || seen.has(key)) {
      continue;
    }

    seen.add(key);
    items.push(
      description
        ? {
            label,
            path,
            description,
          }
        : {
            label,
            path,
          },
    );

    if (items.length >= 3) {
      break;
    }
  }

  return items;
};

const sortArticles = (articles: StoredAgentDentalKnowledgeArticle[]) =>
  [...articles].sort((left, right) => Date.parse(right.updatedAt) - Date.parse(left.updatedAt));

const defaultKnowledgeArticles = () => [] as StoredAgentDentalKnowledgeArticle[];

export const listAgentDentalKnowledgeArticles = async () =>
  sortArticles(
    await readPersistentDataFile<StoredAgentDentalKnowledgeArticle[]>(knowledgeFileName, defaultKnowledgeArticles),
  );

export const upsertAgentDentalKnowledgeArticle = async (
  input: AgentDentalKnowledgeInput,
): Promise<{ article: StoredAgentDentalKnowledgeArticle; action: 'CREATED' | 'UPDATED' }> => {
  const title = normalizeString(input.title);
  const summary = normalizeString(input.summary);
  const answer = normalizeString(input.answer);
  const audience = normalizeAudienceList(input.audience);

  if (!title || !summary || !answer || audience.length === 0) {
    throw new Error('Articulo invalido');
  }

  const currentArticles = await listAgentDentalKnowledgeArticles();
  const existingArticle = currentArticles.find((article) => article.id === input.id) ?? null;
  const now = new Date().toISOString();

  const nextArticle: StoredAgentDentalKnowledgeArticle = {
    id: normalizeString(input.id) || existingArticle?.id || randomUUID(),
    title,
    summary,
    answer,
    audience,
    keywords: normalizeStringList(input.keywords, 16),
    steps: normalizeStringList(input.steps, 8),
    actions: normalizeActionList(input.actions),
    relatedContextIds: normalizeStringList(input.relatedContextIds, 12),
    source: 'custom',
    createdAt: normalizeString(input.createdAt) || existingArticle?.createdAt || now,
    updatedAt: now,
    createdBy: normalizeString(input.createdBy) || existingArticle?.createdBy || null,
  };

  const nextArticles = sortArticles([
    nextArticle,
    ...currentArticles.filter((article) => article.id !== nextArticle.id),
  ]).slice(0, 80);

  await writePersistentDataFile(knowledgeFileName, nextArticles);
  return {
    article: nextArticle,
    action: existingArticle ? 'UPDATED' : 'CREATED',
  };
};

export const deleteAgentDentalKnowledgeArticle = async (articleId: string) => {
  const normalizedId = normalizeString(articleId);

  if (!normalizedId) {
    return false;
  }

  const currentArticles = await listAgentDentalKnowledgeArticles();
  const nextArticles = currentArticles.filter((article) => article.id !== normalizedId);

  const deletedArticle = currentArticles.find((article) => article.id === normalizedId) ?? null;

  if (!deletedArticle) {
    return null;
  }

  await writePersistentDataFile(knowledgeFileName, nextArticles);
  return deletedArticle;
};
